Коли кілька потоків ділять невеликий пул проксі, вибір випадкового запису може дати двом активним операціям той самий проксі. Черга може зберігати записи, доступні для позичання зараз:

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)

Побудуйте чергу один раз, перед запуском робочих потоків. proxy_urls містить повні URL кінцевих точок. Публічні кандидати доступні в списку безкоштовних проксі; використовуйте протокол і формат URL, які підтримує fetch_one. Наявна синхронна функція fetch_one має завершити мережеву операцію й закрити будь-яку відповідь перед поверненням. Інакше позичання закінчиться, поки з’єднання ще використовує цей проксі.

Queue.get атомарно видаляє один доступний запис. Вичерпаний пул чекає, а не багаторазово сканує спільні прапорці. Якщо за п’ять секунд запис не надійде, queue.Empty дійде до виклику; виберіть політику повторної спроби, збою або скасування застосунку для цього результату.

Блок finally повертає отриманий запис після успіху або винятку. Він не оголошує невдалу кінцеву точку здоровою. Політики карантину, заміни й охолодження потребують явного шляху, а не тихого відкидання кожного проксі, що бачить тимчасову помилку.

Видалення дублікатів однакових рядків URL запобігає повторним записам у черзі. Різні URL усе ще можуть указувати на той самий фізичний проксі або вихід; групуйте їх навмисно, якщо ексклюзивність має застосовуватися до цього спільного ресурсу. Черга координує потоки в цьому процесі, а не працівників на інших машинах.

Схожі статті