Gdy kilka wątków współdzieli małą pulę serwerów proxy, wybór losowego wpisu może dać dwóm aktywnym operacjom ten sam serwer proxy. Kolejka może przechowywać wpisy aktualnie dostępne do wypożyczenia:

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)

Zbuduj kolejkę raz, przed uruchomieniem wątków roboczych. proxy_urls zawiera pełne adresy URL punktów końcowych. Publiczni kandydaci są dostępni na liście darmowych serwerów proxy; użyj protokołu i formatu URL obsługiwanego przez fetch_one. Istniejąca synchroniczna funkcja fetch_one musi zakończyć operację sieciową i zamknąć każdą odpowiedź przed powrotem. W przeciwnym razie wypożyczenie zakończyłoby się, gdy połączenie nadal używa tego serwera proxy.

Queue.get atomowo usuwa jeden dostępny wpis. Wyczerpana pula czeka, zamiast wielokrotnie skanować współdzielone flagi. Jeśli w ciągu pięciu sekund nie pojawi się żaden wpis, queue.Empty dociera do wywołującego; wybierz politykę ponawiania, błędu lub anulowania aplikacji dla tego wyniku.

Blok finally zwraca pozyskany wpis po sukcesie lub wyjątku. Nie ogłasza, że nieudany punkt końcowy jest zdrowy. Zasady kwarantanny, wymiany i schładzania wymagają jawnej ścieżki, zamiast po cichu odrzucać każdy serwer proxy, który napotka tymczasowy błąd.

Usuwanie duplikatów identycznych ciągów URL zapobiega podwójnym wpisom w kolejce. Różne adresy URL nadal mogą wskazywać ten sam fizyczny serwer proxy lub wyjście; grupuj je świadomie, jeśli wyłączność ma dotyczyć tego współdzielonego zasobu. Kolejka koordynuje wątki w tym procesie, a nie procesy robocze na innych maszynach.

Powiązane artykuły