본문 바로가기
Python

Python - HTTPConnectionPool 문제 해결, Max retries

by 올엠 2024. 3. 14.
반응형

Python을 하다보면 가장 많은 오류를 볼 수 있는 부분이 Max retries 오류이다.

HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /xxx (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x00000000>: Failed to establish a new connection: [Errno 61] Connection refused'))

이는 2가지 경우인데 자신의 Connection Pool이 꽉 차서 나타나거나, 반대로 상대방이 요청을 거부하는 경우이다.

보통 HTTPAdapter Retry 옵션을 구성해서 사용하는데 세밀하게 설정할 수 있다.

Retry 설정

def requests_retry_session(
    retries=10, # 재시도 횟수
    backoff_factor=2, # 재시도시 대기 시간, 재시도 횟수가 올라갈 때 제곱으로 시간이 올라간다.
    status_forcelist=(500, 502, 504), # 재시도에 추가할 HTTP Status, 500, 502, 504 에러시 기본적으로 Retry를 하지 않는다.
    session=None, # 세션이 함께 함수에 넘어오는지 확인
):

    session = session or requests.Session()

    retry = Retry(
        total=retries,
        read=retries,
        connect=retries,
        backoff_factor=backoff_factor,
        status_forcelist=status_forcelist,
    )

    adapter = HTTPAdapter(max_retries=retry)
    session.mount('http://', adapter)
    session.mount('https://', adapter)
    return session


#사용

requests_retry_session.get('https://asecurity.dev')

 

다만 위 HTTPAdapter를 조정하게 되면, 전체 세션에 영향을 주게된다. 따라서 sleep을 활용하는 것을 추천한다.

재시도 함수

지정된 status code가 아닌 경우 50초까지 return을 통해 다시 실행하도록 한다.

def http_request(method, url, data=None, headers=None, num_of_seconds_to_wait=3):

"""HTTP Request 정리"""
    try:
        res = requests.request(method,
                               url,
                               verify=False,
                               data=data,
                               headers=headers,
                               timeout=15
                               )

        if res.status_code not in (200, 204, 202):
             if random_num_of_seconds <= 50: # 50초가 넘어가면 멈춘다.
                random_num_of_seconds = random.randint(num_of_seconds_to_wait, num_of_seconds_to_wait + 3)
                time.sleep(random_num_of_seconds)
                return http_request(method, url, data, headers=headers,
                                    num_of_seconds_to_wait=num_of_seconds_to_wait + 3)
            else:
             	raise Exception(f'Your request failed with the following error: {res.status_code}')
    except Exception as e:
        logging.warning(f'Http request failed with url={url}\tdata={data}')
        logging.warning(e)
        raise e
    return res
 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형