프록시 풀에는 용량이 매우 다른 엔드포인트가 포함될 수 있습니다. 애플리케이션 전체에서 50개의 작업을 허용해도 그중 49개가 동일한 프록시를 선택하는 것을 막지 못합니다.

정책이 “선택한 각 프록시를 통해 최대 4개의 진행 중인 작업”이라면 그 정책을 그대로 표현하세요. 각 프록시 식별자에 대해 세마포어를 유지하고, 프록시의 용량을 소비하는 작업 주변에서 이를 획득하세요.

limits = {proxy: asyncio.Semaphore(4) for proxy in proxy_urls}

async def fetch(session, proxy, url):
    async with limits[proxy]:
        async with session.get(url, proxy=proxy) as response:
            return await response.read()

이 스케치는 asyncio가 임포트되었고 프록시 URL이 검증되었다고 가정합니다. 허용된 공용 프록시 경로의 공개 요청에는 HTTP 프록시 목록이 aiohttp의 프록시 URL 후보를 제공합니다. 실제 애플리케이션은 자체 요청 시간 제한을 설정하고 필요한 응답 데이터의 양을 결정해야 합니다. 큰 파일을 전부 메모리로 읽는 것은 별개의 리소스 결정입니다.

비싼 부분을 위해 허가를 유지하세요

응답 헤더가 도착하자마자 세마포어를 해제하면 의도한 제한이 무력화될 수 있습니다. 스트리밍 본문은 그 후에도 오랫동안 연결을 계속 사용할 수 있습니다. 본문이 소비되거나 애플리케이션의 워크플로에 따라 응답이 닫힐 때까지 허가를 유지하세요.

중첩된 컨텍스트 관리자는 예외나 취소가 작업을 떠날 때 정리가 드러나게 합니다. 수동으로 획득하고 성공한 함수의 맨 아래에서만 해제하는 것을 피하세요.

연결 제한은 다른 질문에 답합니다

aiohttp의 커넥터 제한은 커넥터의 문서화된 규칙에 따라 연결을 제한합니다. 애플리케이션 세마포어와 함께 여전히 유용합니다. 대상별 연결 제한은 이름만으로는 하나의 프록시에 할당된 모든 대상이 공유하는 예산을 표현하지 않습니다.

동시성과 요청 속도도 구분하세요. 4개의 장기 요청과 4개의 매우 짧은 요청은 동일한 동시성 할당량을 사용하지만 서로 다른 초당 요청 속도를 만듭니다. 속도 정책이 있는 서비스는 페이싱이나 별도의 속도 제한기가 필요할 수 있습니다.

로그와 지표에는 안정적이고 비밀이 아닌 프록시 식별자를 선택하세요. 자격 증명이 포함된 두 URL이 동일한 용량 풀을 가리킨다면 하나의 예산을 공유해야 하는지 결정하세요. 반대로 서로 다른 포트나 계정은 운영자가 그렇게 문서화한 경우 별도의 제한을 나타낼 수 있습니다.

처리량이 떨어지면 작업이 어디에서 기다리는지 확인하세요: 세마포어, 커넥터, 프록시 연결 설정 또는 응답 읽기입니다. 모든 제한을 한꺼번에 올리면 그 구분이 어려워지고 대기열이 통제하지 못하는 프록시로 이동할 수 있습니다.

관련 글