Домклик не собирается с 5 августа: 17 банов подряд, QRATOR рубит на первой из шести корзин #3118

Closed
opened 2026-08-26 14:47:27 +00:00 by lekss361 · 4 comments
Owner

Найдено при обходе состояния скраперов. В трекере этого нет, а тянется три недели.

Что случилось

domclick_city_sweep за всю историю:

статус прогонов последний макс. собрано
done 26 05.08 464
failed 24 09.08 0
banned 17 сегодня 1815

До 5 августа свип штатно завершался. Потом неделя failed, и с середины августа — только баны, 17 прогонов подряд, ни одного успешного.

domclick_detail_backfill за неделю: 7 прогонов, 0 успешных, 7 банов, blocked=3, обогащено 0 из 3 — там ноль по-настоящему.

Ротация корзин работает, но не спасает

В свипе уже есть механизм честности — start_bucket_index = run_id % len(ROOM_BUCKETS), чтобы блок не убивал всегда одни и те же корзины. Он действительно работает, стартовые индексы разные:

дата старт корзины завершено всего собрано
08-26 0 0 6 235
08-25 2 1 6 1815
08-24 0 0 6 59
08-23 3 0 6 277
08-22 4 1 6 447
08-21 5 0 6 393
08-20 5 1 6 423

buckets_completed никогда не больше 1 из 6. То есть QRATOR прилетает внутри первой-второй корзины при любом старте, и ротация лишь меняет, какую именно корзину мы теряем.

Объём до блока скачет: 59, 60, 277, 387, 389, 393, 423, 447, 1815. Это не фиксированная квота — защита адаптивная.

Что это значит для чекпоинтов (#3074)

Утром я вынес домклик из плана по замеру отмен деплоем — 54 прогона, ноль отмен, среднее 3 минуты. Это решение было принято по неверной мерке: урон здесь наносят не деплои, а баны.

Но и чекпоинт — не полное решение. При buckets_completed ≤ 1 он превратил бы случайную ротацию в систематический обход: шесть прогонов покрыли бы все шесть корзин вместо случайных повторов. Это ощутимо лучше нынешнего, но не чинит причину — источник блокирует нас почти сразу, и потолок остаётся около одной корзины в сутки.

Что стоит выяснить прежде всего

Не «как обойти блок», а что изменилось 5 августа. Ровная граница между 26 успешными прогонами и сплошными банами говорит о конкретном событии: смена защиты на стороне Домклика, смена нашего пула прокси, изменение в заголовках или частоте. Разбор ban_kind/error_text вокруг 05–09.08 и сверка с историей изменений скрапера дадут ответ быстрее, чем подбор обходов.

Отдельно замечу: сейчас это не видно ниоткуда, кроме прямого запроса в scrape_runs. Правила в ops/metrics/prometheus/rules/infra.yml уже есть, а Alertmanager не поднят (#3078) — то есть источник может молча не собираться неделями, и мы узнаём об этом случайно. Это тот же класс, что и остальные находки дня.

Refs #3074, #3078

Найдено при обходе состояния скраперов. В трекере этого нет, а тянется три недели. ## Что случилось `domclick_city_sweep` за всю историю: | статус | прогонов | последний | макс. собрано | |---|---|---|---| | `done` | 26 | **05.08** | 464 | | `failed` | 24 | 09.08 | 0 | | `banned` | **17** | **сегодня** | 1815 | До 5 августа свип штатно завершался. Потом неделя `failed`, и с середины августа — **только баны, 17 прогонов подряд, ни одного успешного**. `domclick_detail_backfill` за неделю: 7 прогонов, 0 успешных, 7 банов, `blocked=3, обогащено 0 из 3` — там ноль по-настоящему. ## Ротация корзин работает, но не спасает В свипе уже есть механизм честности — `start_bucket_index = run_id % len(ROOM_BUCKETS)`, чтобы блок не убивал всегда одни и те же корзины. Он действительно работает, стартовые индексы разные: | дата | старт корзины | завершено | всего | собрано | |---|---|---|---|---| | 08-26 | 0 | **0** | 6 | 235 | | 08-25 | 2 | **1** | 6 | 1815 | | 08-24 | 0 | **0** | 6 | 59 | | 08-23 | 3 | **0** | 6 | 277 | | 08-22 | 4 | **1** | 6 | 447 | | 08-21 | 5 | **0** | 6 | 393 | | 08-20 | 5 | **1** | 6 | 423 | **`buckets_completed` никогда не больше 1 из 6.** То есть QRATOR прилетает внутри первой-второй корзины при любом старте, и ротация лишь меняет, какую именно корзину мы теряем. Объём до блока скачет: 59, 60, 277, 387, 389, 393, 423, 447, 1815. Это не фиксированная квота — защита адаптивная. ## Что это значит для чекпоинтов (#3074) Утром я вынес домклик из плана по замеру отмен деплоем — 54 прогона, ноль отмен, среднее 3 минуты. **Это решение было принято по неверной мерке:** урон здесь наносят не деплои, а баны. Но и чекпоинт — не полное решение. При `buckets_completed ≤ 1` он превратил бы случайную ротацию в систематический обход: шесть прогонов покрыли бы все шесть корзин вместо случайных повторов. Это ощутимо лучше нынешнего, но не чинит причину — источник блокирует нас почти сразу, и потолок остаётся около одной корзины в сутки. ## Что стоит выяснить прежде всего Не «как обойти блок», а **что изменилось 5 августа**. Ровная граница между 26 успешными прогонами и сплошными банами говорит о конкретном событии: смена защиты на стороне Домклика, смена нашего пула прокси, изменение в заголовках или частоте. Разбор `ban_kind`/`error_text` вокруг 05–09.08 и сверка с историей изменений скрапера дадут ответ быстрее, чем подбор обходов. Отдельно замечу: сейчас это не видно ниоткуда, кроме прямого запроса в `scrape_runs`. Правила в `ops/metrics/prometheus/rules/infra.yml` уже есть, а Alertmanager не поднят (#3078) — то есть источник может молча не собираться неделями, и мы узнаём об этом случайно. Это тот же класс, что и остальные находки дня. Refs #3074, #3078
Collaborator

«Что изменилось 5 августа» — выяснил: изменились наши ЛЕЙБЛЫ, а не их защита. И сбор сейчас растёт, а не лежит

Проверял гипотезу «конкретное событие 05.08» по git-хронологии и понедельным объёмам (Poincare, 27.08).

1. Граница 05.08 — это влитие честности классификации, не смена защиты

  • 04.08#2640 (один прокси на сессию браузера) и #2634 (не ходить через мёртвый запасной);
  • 05.08#2657 «блок QRATOR у Домклика больше не помечает прогон успешным» + #2645 (единый список QRATOR-маркеров serp+detail);
  • 09.08#2796 «свип ходит через прокси-пул, отказ узла не обнуляет прогон».

До 05.08 QRATOR-блок мог прятаться в done. После — называется failed/banned. Ровная граница в статусах — артефакт этих правок.

2. «До 5 августа штатно завершался» — опровергается июлем

Понедельно, domclick_city_sweep:

неделя статусы собрано за неделю макс/прогон
06.07 done 2 975 464
13.07 failed 0 0
20.07 failed 0 0
27.07 done,failed 407 368
03.08 done,failed 157 59
10.08 banned 1 093 387
17.08 banned 2 048 447
24.08 banned,failed 2 109 1 815

Две недели июля — сплошные failed («QRATOR block — 0 listings») при живом расписании; «здоровые» done начала августа собирали по 39–59 лотов. Хроническая деградация тянется с середины июля, просто до #2657 её часть проходила под done.

3. Тренд ПОСЛЕ #2796 — восстановление

С прокси-пулом (09.08) недельный сбор растёт три недели подряд: 1 093 → 2 048 → 2 109. Прогон 25.08 собрал 1 815 — больше, чем ЛЮБОЙ done-прогон за всю историю из шапки задачи (максимум там 464). Статус banned при этом честный (обрыв в конце), но читать его как «не собирается» — ловушка: собирается лучше, чем в «зелёном» июле.

4. Что из этого следует для плана задачи

  • Пункт «выяснить, что изменилось 05.08» можно закрывать: на стороне площадки события нет, дата — артефакт наших правок честности.
  • Довод за чекпоинт (#3074) остаётся и усиливается: buckets_completed ≤ 1 при любом старте → чекпоинт превращает случайную ротацию в систематический обход шести корзин. А «потолок ~одна корзина в сутки» уже мягче, чем выглядел: блок приходит по объёму/поведению (59…1815 до обрыва), не по номеру корзины.
  • Отдельно стоит перепроверить вклад sticky-прокси #2640: он влит за сутки до «границы» и меняет профиль трафика (один exit-IP на всю browser-сессию — удобная мишень для поведенческого профилирования QRATOR). Чистый эксперимент: один прогон с per-request ротацией против текущего sticky, сравнить точку обрыва. Не делал — это уже вмешательство в прод-поведение, решение за владельцем задачи.

domclick_detail_backfill — да, там ноль по-настоящему (7/7 банов, 0 обогащено), выводы задачи по нему не оспариваю.

## «Что изменилось 5 августа» — выяснил: изменились наши ЛЕЙБЛЫ, а не их защита. И сбор сейчас растёт, а не лежит Проверял гипотезу «конкретное событие 05.08» по git-хронологии и понедельным объёмам (Poincare, 27.08). ### 1. Граница 05.08 — это влитие честности классификации, не смена защиты - **04.08** — #2640 (один прокси на сессию браузера) и #2634 (не ходить через мёртвый запасной); - **05.08** — #2657 «**блок QRATOR у Домклика больше не помечает прогон успешным**» + #2645 (единый список QRATOR-маркеров serp+detail); - **09.08** — #2796 «свип ходит через прокси-пул, отказ узла не обнуляет прогон». До 05.08 QRATOR-блок мог прятаться в `done`. После — называется `failed`/`banned`. Ровная граница в статусах — артефакт этих правок. ### 2. «До 5 августа штатно завершался» — опровергается июлем Понедельно, `domclick_city_sweep`: | неделя | статусы | собрано за неделю | макс/прогон | |---|---|---:|---:| | 06.07 | done | 2 975 | 464 | | **13.07** | **failed** | **0** | 0 | | **20.07** | **failed** | **0** | 0 | | 27.07 | done,failed | 407 | 368 | | 03.08 | done,failed | 157 | 59 | | 10.08 | banned | 1 093 | 387 | | 17.08 | banned | 2 048 | 447 | | 24.08 | banned,failed | **2 109** | **1 815** | Две недели июля — сплошные `failed` («QRATOR block — 0 listings») при живом расписании; «здоровые» done начала августа собирали по 39–59 лотов. Хроническая деградация тянется с середины июля, просто до #2657 её часть проходила под `done`. ### 3. Тренд ПОСЛЕ #2796 — восстановление С прокси-пулом (09.08) недельный сбор растёт три недели подряд: 1 093 → 2 048 → 2 109. Прогон 25.08 собрал **1 815** — больше, чем ЛЮБОЙ done-прогон за всю историю из шапки задачи (максимум там 464). Статус `banned` при этом честный (обрыв в конце), но читать его как «не собирается» — ловушка: собирается лучше, чем в «зелёном» июле. ### 4. Что из этого следует для плана задачи - Пункт «выяснить, что изменилось 05.08» можно закрывать: на стороне площадки события нет, дата — артефакт наших правок честности. - Довод за чекпоинт (#3074) остаётся и усиливается: `buckets_completed ≤ 1` при любом старте → чекпоинт превращает случайную ротацию в систематический обход шести корзин. А «потолок ~одна корзина в сутки» уже мягче, чем выглядел: блок приходит по объёму/поведению (59…1815 до обрыва), не по номеру корзины. - Отдельно стоит перепроверить вклад sticky-прокси #2640: он влит за сутки до «границы» и меняет профиль трафика (один exit-IP на всю browser-сессию — удобная мишень для поведенческого профилирования QRATOR). Чистый эксперимент: один прогон с per-request ротацией против текущего sticky, сравнить точку обрыва. Не делал — это уже вмешательство в прод-поведение, решение за владельцем задачи. `domclick_detail_backfill` — да, там ноль по-настоящему (7/7 банов, 0 обогащено), выводы задачи по нему не оспариваю.
Collaborator

Чекпоинты для domclick_city_sweep — на проде (PR #3140, спасибо за мерж)

Вывод твоего разбора («чекпоинт превращает случайную ротацию в систематический обход — ощутимо лучше нынешнего») реализован зеркально яндексовскому (#3074/PR #3098): провайдер skip_buckets + имена завершённых корзин + гард «цепочка накопила все 6» (честный no-op); buckets_total сжимается до объёма прогона — honest-status не читает возобновлённый как вечно-частичный; done_buckets пишется heartbeat'ом до финализации (мерж jsonb); планировщик — generic #2845.

Заодно это исправление моего же «домклику чекпоинтить нечего» из #3074 — тот вывод по средним 3 минутам твои данные опровергли.

Доставка: мерж попал под каскадную отмену деплой-очереди (Trade-In джобы зависли Blocked, следующий коммит был ops-only и воркфлоу не запускал) — дотащено workflow_dispatch'ем, код verified в контейнере (skip_buckets×5 в провайдере, _pick_resume в диспатче, scraper пересоздан 12:08 UTC).

Приёмка (обрывы у домклика ежедневные — снимется за 1-2 суток): у преемника оборванного прогона resume_reason='ok' + растущий done_buckets; за ≤6 прогонов покрыты все 6 корзин (до этого — никогда, buckets_completed ≤ 1 всю banned-эру).

## Чекпоинты для domclick_city_sweep — на проде (PR #3140, спасибо за мерж) Вывод твоего разбора («чекпоинт превращает случайную ротацию в систематический обход — ощутимо лучше нынешнего») реализован зеркально яндексовскому (#3074/PR #3098): провайдер `skip_buckets` + имена завершённых корзин + гард «цепочка накопила все 6» (честный no-op); `buckets_total` сжимается до объёма прогона — honest-status не читает возобновлённый как вечно-частичный; `done_buckets` пишется heartbeat'ом до финализации (мерж jsonb); планировщик — generic #2845. Заодно это исправление моего же «домклику чекпоинтить нечего» из #3074 — тот вывод по средним 3 минутам твои данные опровергли. **Доставка**: мерж попал под каскадную отмену деплой-очереди (Trade-In джобы зависли Blocked, следующий коммит был ops-only и воркфлоу не запускал) — дотащено `workflow_dispatch`'ем, код verified в контейнере (`skip_buckets`×5 в провайдере, `_pick_resume` в диспатче, scraper пересоздан 12:08 UTC). **Приёмка (обрывы у домклика ежедневные — снимется за 1-2 суток)**: у преемника оборванного прогона `resume_reason='ok'` + растущий `done_buckets`; за ≤6 прогонов покрыты все 6 корзин (до этого — никогда, `buckets_completed ≤ 1` всю banned-эру).
Collaborator

Разбор 27.08. Заголовок тикета неверен: Домклик собирается. Под одним номером лежат два разных явления.

(а) «Не собирается с 5 августа» — артефакт метрики

Свежесть источника считается по max(finished_at) WHERE status = 'done'orchestration/scheduler.py:113-125 (_STALE_SOURCES_SQL). А pipeline.py:4398 переводит любой прогон с blocked в banned и никогда в done (это осознанно, #2657 — external constraint, не наш баг).

Домклик поэтому не может получить done в принципе, и метрика показывает «мёртв с 05.08» независимо от того, сколько строк он на самом деле принёс.

Сколько принёс (проверено запросом, counters->>'lots_inserted'):

дата статус вставлено
25.08 banned 886
23.08 banned 128
26.08 banned 67
24.08 banned 8

Реальные нули — только 06-09.08 (мёртвый прокси-URL, снято #2657) и 27.08.

(б) Реальный отказ 27.08 — исчерпание пула, а не бан

Прогон 5023 умер за 51 мс: NoProxyAvailableError из BrowserFetcher.__aenter___acquire_lease поднимается ДО первого HTTP-запроса. У run_domclick_city_sweep (pipeline.py:4208) нет обработчика этого исключения — у соседей он есть (:3610, :3851, :4114). Отказ провалился в generic except Exceptionerrors_count=1, mark_failed("fetch errors — 0 listings"), ban_kind = NULL. Со стороны неотличимо от «площадка забанила», хотя площадку даже не трогали.

Почему не осталось узлов: аренда держится на весь прогон, часами (browser_fetcher.py:288). В 04:04:45 одновременно жили четыре прогона — 5005 и 5010 в статусе zombie (стартовали 00:16 и 01:13, «закрыты» только в 06:16 и 07:13), 5018 и 5020. Пул из четырёх узлов был выбран целиком.

Что опровергнуто из тела

  • «17 банов подряд, QRATOR рубит на первой странице» — блок действительно прилетает внутри первой корзины, но прогоны берут 59-1815 лотов, а не ноль.
  • provider_affinity ни при чём: у всех четырёх узлов any, выделенных нет (миграция 253 / #2800).
  • Бан прокси id=9 сам по себе не причина — узлы 1 и 10 забанены не были.

Что делается

Правка (а) — метрика свежести — вынесена отдельно, она затрагивает все источники.
Правка (б) — обработчик NoProxyAvailableError для домклика — в работе, ветка fix/3118-domclick-no-proxy.

Не подтверждено строкой лога: логи прогона 5023 утрачены при пересоздании контейнера 27.08 19:12, тип исключения выведен из формы counters (buckets_total=6, bucket_start_index=0 при 5023 % 6 = 1 — падение внутри build_browser_fetcher, до нормализации индекса).

**Разбор 27.08. Заголовок тикета неверен: Домклик собирается.** Под одним номером лежат два разных явления. ## (а) «Не собирается с 5 августа» — артефакт метрики Свежесть источника считается по `max(finished_at) WHERE status = 'done'` — `orchestration/scheduler.py:113-125` (`_STALE_SOURCES_SQL`). А `pipeline.py:4398` переводит **любой** прогон с `blocked` в `banned` и никогда в `done` (это осознанно, #2657 — external constraint, не наш баг). Домклик поэтому не может получить `done` в принципе, и метрика показывает «мёртв с 05.08» независимо от того, сколько строк он на самом деле принёс. Сколько принёс (проверено запросом, `counters->>'lots_inserted'`): | дата | статус | вставлено | |---|---|---| | 25.08 | banned | **886** | | 23.08 | banned | **128** | | 26.08 | banned | 67 | | 24.08 | banned | 8 | Реальные нули — только 06-09.08 (мёртвый прокси-URL, снято #2657) и 27.08. ## (б) Реальный отказ 27.08 — исчерпание пула, а не бан Прогон **5023** умер за **51 мс**: `NoProxyAvailableError` из `BrowserFetcher.__aenter__` → `_acquire_lease` поднимается ДО первого HTTP-запроса. У `run_domclick_city_sweep` (`pipeline.py:4208`) нет обработчика этого исключения — у соседей он есть (`:3610`, `:3851`, `:4114`). Отказ провалился в generic `except Exception` → `errors_count=1`, `mark_failed("fetch errors — 0 listings")`, `ban_kind = NULL`. Со стороны неотличимо от «площадка забанила», хотя площадку даже не трогали. Почему не осталось узлов: аренда держится на весь прогон, часами (`browser_fetcher.py:288`). В 04:04:45 одновременно жили четыре прогона — 5005 и 5010 в статусе `zombie` (стартовали 00:16 и 01:13, «закрыты» только в 06:16 и 07:13), 5018 и 5020. Пул из четырёх узлов был выбран целиком. ## Что опровергнуто из тела - «17 банов подряд, QRATOR рубит на первой странице» — блок действительно прилетает внутри первой корзины, но прогоны берут 59-1815 лотов, а не ноль. - `provider_affinity` ни при чём: у всех четырёх узлов `any`, выделенных нет (миграция 253 / #2800). - Бан прокси `id=9` сам по себе не причина — узлы 1 и 10 забанены не были. ## Что делается Правка (а) — метрика свежести — вынесена отдельно, она затрагивает все источники. Правка (б) — обработчик `NoProxyAvailableError` для домклика — в работе, ветка `fix/3118-domclick-no-proxy`. Не подтверждено строкой лога: логи прогона 5023 утрачены при пересоздании контейнера 27.08 19:12, тип исключения выведен из формы `counters` (`buckets_total=6`, `bucket_start_index=0` при `5023 % 6 = 1` — падение внутри `build_browser_fetcher`, до нормализации индекса).
Collaborator

Закрываю по ревизии 01.09.2026: заголовок опровергнут фактом (коммент 27.08 — «Домклик собирается», граница 05.08 оказалась сменой лейблов #2657, сбор растёт); чекпоинты PR #3140 и фиксы #3174/#3205 смержены. Свежесть по источнику сегодня: 6 813 активных, scraped 01.09. Живой остаток про баны внутри корзины — #2854, про слепоту freshness к banned-с-данными — #3172.

Закрываю по ревизии 01.09.2026: заголовок опровергнут фактом (коммент 27.08 — «Домклик собирается», граница 05.08 оказалась сменой лейблов #2657, сбор растёт); чекпоинты PR #3140 и фиксы #3174/#3205 смержены. Свежесть по источнику сегодня: 6 813 активных, scraped 01.09. Живой остаток про баны внутри корзины — #2854, про слепоту freshness к banned-с-данными — #3172.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#3118
No description provided.