Compartilhar um pool de proxies entre threads Python com uma fila
Use uma fila sincronizada e um bloco finally para reservar um proxy para uma operação de thread síncrona e devolvê-lo depois.
Quando várias threads compartilham um pool pequeno de proxies, escolher uma entrada aleatória pode dar o mesmo proxy a duas operações ativas. Uma fila pode conter as entradas disponíveis para empréstimo no momento:
from contextlib import contextmanager
from queue import Queue
available = Queue()
for endpoint in dict.fromkeys(proxy_urls):
available.put(endpoint)
@contextmanager
def borrow_proxy():
endpoint = available.get(timeout=5)
try:
yield endpoint
finally:
available.put(endpoint)
def process_url(url):
with borrow_proxy() as endpoint:
return fetch_one(url, endpoint)
Construa a fila uma vez, antes de iniciar as threads de trabalho. proxy_urls contém URLs de endpoint completas. Candidatos públicos estão disponíveis na lista de proxies gratuitos; use o protocolo e o formato de URL suportados por fetch_one. A função fetch_one síncrona existente precisa concluir sua operação de rede e fechar qualquer resposta antes de retornar. Caso contrário, o empréstimo terminaria enquanto a conexão ainda usa esse proxy.
Queue.get remove atomicamente uma entrada disponível. Um pool esgotado espera em vez de verificar repetidamente sinalizadores compartilhados. Se nenhuma entrada chegar em cinco segundos, queue.Empty chega ao chamador; escolha a política de nova tentativa, falha ou cancelamento da aplicação para esse resultado.
O bloco finally devolve uma entrada adquirida após sucesso ou exceção. Ele não declara que um endpoint com falha está saudável. Políticas de quarentena, substituição e resfriamento precisam de um caminho explícito em vez de descartar silenciosamente todo proxy que vê um erro temporário.
Desduplicar strings de URL idênticas evita entradas duplicadas na fila. URLs distintas ainda podem se referir ao mesmo proxy físico ou saída; agrupe-as deliberadamente se a exclusividade precisar valer para esse recurso compartilhado. A fila coordena threads neste processo, não workers em outras máquinas.