All checks were successful
CI Trade-In / changes (pull_request) Successful in 9s
CI / changes (pull_request) Successful in 9s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 3m5s
ipify-проба отвечает на «узел жив вообще», а сбор Авито с 02.08 (#2637) ходит через сайдкар браузером: camoufox стартует С ЭТИМ прокси, потом навигация. Это разные свойства узла, и до сих пор они писались в ОДИН счётчик: боевой /fetch репортил mark_health(ok=False), а следующая (≤30 мин) успешная ipify-проба делала consecutive_fails=0 + enabled=true. Дешёвая проба стирала вердикт дорогого тракта — узел, мёртвый для браузера, выходил из карантина каждые полчаса и снова забирал прогон. Разведено тем же приёмом, что #2711 (scrape_runs.ban_kind) — поле РЯДОМ, а не новое значение существующего флага. Миграция 228: browser_fail_streak / browser_unfit_since / browser_check_at. Успешная ipify их не трогает, провал браузерной пробы не трогает enabled/consecutive_fails. Проба: POST /fetch (одна навигация) на robots.txt Авито через сайдкар с прокси узла в теле. /fetch, а не /fetch-json — последний сначала грузит главную площадки. source= 'generic', чтобы не забирать лок боевого инстанса и не релончить его. Такт решён замером на проде: одна браузерная проба = 8.3с и один запуск camoufox, боевая нагрузка сайдкара = ~1000 /fetch и ~190 запусков camoufox в сутки. Каждым прогоном healthcheck по 4 узлам это +192 запуска (удвоение), поэтому такт 360 мин: +16 запусков (+8%). Неподтверждённый провал такт не двигает — второе подтверждение приходит на следующем прогоне (~30 мин), не через 6 часов. Пометка НЕ выводит узел из пула (пул 4 узла, #2638): acquire отдаёт его последним (ORDER BY) и громко логирует, если пригодных не осталось. Путь обратно — успешная браузерная проба (browser_refit). Отказ, принадлежащий сайдкару или площадке, узлу не засчитывается — иначе одна упавшая общая зависимость пометила бы весь пул (#2686). Refs #2723
66 lines
5.5 KiB
PL/PgSQL
66 lines
5.5 KiB
PL/PgSQL
-- 228_scrape_proxies_browser_health.sql
|
||
-- Здоровье узла ОТДЕЛЬНО для браузерного тракта (#2723).
|
||
--
|
||
-- WHY:
|
||
-- `run_proxy_healthcheck` гоняет через узел обычный httpx-GET к ipify. Боевой сбор
|
||
-- Авито с 02.08 (#2637) ходит через сайдкар браузером: camoufox стартует С ЭТИМ
|
||
-- прокси (geoip-lookup на launch), потом навигация. Это разные свойства узла:
|
||
-- крошечный GET проходит там, где launch/навигация падает (`browser unavailable
|
||
-- (proxy may be down)` — все 90 записанных обрывов сбора именно такие).
|
||
--
|
||
-- Хуже того, оба свойства писались в ОДИН счётчик: боевой /fetch репортит
|
||
-- mark_health(ok=False) → consecutive_fails++, но следующая (≤30 мин) успешная
|
||
-- ipify-проба делает consecutive_fails=0 + enabled=true. Дешёвая проба СТИРАЛА
|
||
-- вердикт дорогого тракта, и узел, мёртвый для браузера, вечно возвращался в
|
||
-- выдачу. Это ровно ошибка #2686 (схлопывание двух диагнозов в один флаг) в
|
||
-- другом месте; разводим её тем же приёмом, что #2711 (`scrape_runs.ban_kind`) —
|
||
-- поле РЯДОМ, а не новое значение существующего флага.
|
||
--
|
||
-- WHAT (три колонки, ни одна не участвует в enabled/consecutive_fails):
|
||
-- browser_fail_streak — подряд-провалы ИМЕННО браузерной пробы, и только те, что
|
||
-- атрибутируются узлу (сайдкар лежит / страница пустая —
|
||
-- не считаются, см. proxy_pool._classify_browser_probe).
|
||
-- Успешная ipify-проба его НЕ обнуляет — в этом весь смысл.
|
||
-- browser_unfit_since — момент, когда streak дошёл до порога. NOT NULL = «жив для
|
||
-- HTTP, непригоден для браузера». acquire() такой узел НЕ
|
||
-- исключает (голодание хуже — #2600/#2638, пул 4 узла), а
|
||
-- отправляет в КОНЕЦ очереди выдачи: его возьмут, только
|
||
-- если свободных пригодных нет.
|
||
-- browser_check_at — когда браузерную пробу гоняли последний раз. Такт у неё
|
||
-- свой, редкий (BROWSER_PROBE_MINUTES): она стоит запуска
|
||
-- camoufox (~8с замерено на проде), ipify — миллисекунды.
|
||
--
|
||
-- IDEMPOTENCY / SAFETY:
|
||
-- ADD COLUMN IF NOT EXISTS × 3, аддитивно, без backfill'а: NULL/0 = «браузерную
|
||
-- пробу ещё не гоняли», ровно то состояние, в котором пул и находится. Ни одна
|
||
-- существующая выборка не меняет результат (все три колонки новые). Повторный
|
||
-- прогон — no-op (auto-apply strict на деплое это требует).
|
||
--
|
||
-- Dependencies: 157_scrape_proxies.sql
|
||
|
||
BEGIN;
|
||
|
||
ALTER TABLE scrape_proxies
|
||
ADD COLUMN IF NOT EXISTS browser_fail_streak integer NOT NULL DEFAULT 0,
|
||
ADD COLUMN IF NOT EXISTS browser_unfit_since timestamptz,
|
||
ADD COLUMN IF NOT EXISTS browser_check_at timestamptz;
|
||
|
||
COMMENT ON COLUMN scrape_proxies.browser_fail_streak IS
|
||
'Подряд-провалы браузерной пробы (сайдкар + camoufox через ЭТОТ узел), '
|
||
'атрибутированные узлу. НЕ обнуляется успешной ipify-пробой — иначе дешёвая '
|
||
'проба стирает вердикт дорогого тракта (#2723). Обнуляется успешной браузерной '
|
||
'пробой. Порог → browser_unfit_since, см. proxy_pool.BROWSER_UNFIT_THRESHOLD.';
|
||
|
||
COMMENT ON COLUMN scrape_proxies.browser_unfit_since IS
|
||
'NOT NULL = узел жив для обычного HTTP, но браузерный тракт через него не '
|
||
'работает (#2723). Это НЕ enabled=false: узел остаётся в пуле и обслуживает '
|
||
'curl-путь, а acquire() лишь отдаёт его последним. Полное выключение по-прежнему '
|
||
'значит «узел мёртв целиком» (серия транспортных сбоев) либо решение оператора.';
|
||
|
||
COMMENT ON COLUMN scrape_proxies.browser_check_at IS
|
||
'Последняя браузерная проба. Такт свой, редкий (proxy_pool.BROWSER_PROBE_MINUTES): '
|
||
'одна такая проба = запуск camoufox (~8с на проде), против миллисекунд у ipify. '
|
||
'На неподтверждённом провале НЕ обновляется — чтобы следующий же цикл '
|
||
'healthcheck подтвердил/опроверг отказ, а не ждал полный такт.';
|
||
|
||
COMMIT;
|