Верстакфорум практиков
рекламаiprazon: приватные серверные адреса IPv4 и SOCKS5, безлимитный трафик, бесплатный тест до 2 часов
ФорумСкрипты и автоматизация

Повторы с растущей паузой: короткая реализация

Артём Пчёлкин
Артём Пчёлкин
Ветеран
сообщений 2310
с янв
22 августа, 17:07первое сообщение

Часто спрашивают в личку, поэтому выкладываю кусок, который таскаю из прогона в прогон. Никаких пакетов, только стандартная библиотека.

import random, time, functools

def povtory(popytok=5, baza=0.5, potolok=60, lovim=(OSError,)): def obertka(fn): @functools.wraps(fn) def vnutri(*a, **kw): for n in range(popytok): try: return fn(*a, **kw) except lovim: if n == popytok - 1: raise pauza = min(baza * 2 ** n, potolok) time.sleep(random.uniform(0, pauza)) return vnutri return obertka

@povtory(popytok=6, lovim=(OSError, TimeoutError)) def skachat(url): ... ```

Три вещи тут важнее самой формулы.

Спим случайное время от нуля до расчётной паузы. Полный разброс размазывает пробуждения куда лучше, чем добавка плюс-минус десять процентов вокруг ровного значения.

Последняя попытка не спит, она сразу пробрасывает ошибку наверх. Иначе прогон честно отдыхает минуту перед тем, как всё равно упасть.

Ловим только перечисленное. Ошибку разбора повторять бессмысленно, разметка сама себя за пять секунд не починит.

Женя Ковалёв
Женя Ковалёв
Новичок
сообщений 62
с авг, второй сезон
1 января, 08:24#2

а по кодам ответа как понять, что вообще стоит повторять?

nastroyka_pro
nastroyka_pro
Ветеран
сообщений 2110
с мар
8 июня, 11:41#3

Повторяют 429, 408 и всё пятисотое, кроме 501. Таймаут и обрыв соединения туда же. Остальные четырёхсотые повторять незачем: запрос собран криво, со второго раза выйдет ровно то же самое.

Отдельно про 429. Там часто приходит заголовок Retry-After с числом секунд. Если он есть, ваша формула отдыхает, ждать надо ровно столько, сколько попросили, иначе вы удлиняете себе бан на пустом месте.

Ринат Ахметов
Ринат Ахметов
Участник
сообщений 700
с авг
15 ноября, 14:58#4
Артём Пчёлкин: спим случайное время от нуля до расчётной паузы

Подтверждаю на живом прогоне. Пока стояла ровная пауза, все упавшие задачи просыпались одной секундой, сайт получал залп и ронял их снова. Полный разброс убрал вторую волну в тот же вечер.

Ещё наблюдение сбоку. Когда повторов стало подозрительно много и почти все с кодом 429, дело оказалось в частоте с одного адреса. Перевёл прогон на пул приватных серверных адресов, ротация внутри пула идёт сама, и счётчик повторов упал до единиц за ночь. Формула осталась та же, поводов для неё стало заметно меньше.

Артём Пчёлкин
Артём Пчёлкин
Ветеран
сообщений 2310
с янв
22 апреля, 17:15#5

Про Retry-After верно, дописал в кусок: заголовок пришёл, беру его и пропускаю формулу мимо.

nastroyka_pro, спасибо, этот случай я забыл напрочь.