Вернуться в блог

Стабильность крупномасштабного сбора данных: проблемы, которые проявляются только после масштабирования

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

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

Сначала классифицируйте ошибки, чтобы повторные попытки имели смысл

Ошибки при сборе данных неизбежны. Важно различать их типы: сетевые колебания и сбросы соединения можно повторять сразу; временное ограничение скорости требует backoff перед новой попыткой; если изменение структуры страницы приводит к пустому результату парсинга, даже десять тысяч повторов не помогут — случай нужно записать и поднять предупреждение; если цель не существует, задачу можно отметить выполненной; если среда или сетевой выход не запускается, следует переключиться на другой и попробовать снова.

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

Повторные попытки напрямую связаны с дедупликацией. Одна задача может выполняться несколько раз, поэтому каждой задаче нужен стабильный уникальный идентификатор — например, значение после нормализации URL — а запись в базу должна быть идемпотентной по этому идентификатору. Иначе больше повторов означает больше загрязнённых данных.

Ограничение скорости и параллельность — разные вещи

Увеличение параллельности не гарантирует роста пропускной способности. Одновременно действуют три ограничения: сколько выдерживает целевой сайт до срабатывания rate limiting и снижения общей пропускной способности, память и CPU локальной машины, а также способность одной среды или сессии выполнять несколько задач одновременно.

Более стабильный подход — начать с низкой параллельности и постепенно увеличивать нагрузку, одновременно отслеживая успешность и время ответа, чтобы найти точку, где показатели заметно ухудшаются. Ограничение скорости — отдельный механизм: оно задаёт темп доступа к одной цели и не равно глобальной параллельности. Если партия распределяет задачи по нескольким сайтам, каждому сайту нужен собственный темп.

Возобновление зависит от постоянного хранения состояния

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

Хранить очередь только в памяти — очень распространённая реализация, которая кажется рабочей. Как только процесс падает, все ожидающие задачи исчезают и учёт перестаёт сходиться.

Обрабатывайте сбои прокси и сетевых выходов отдельно

Блокировка выхода целевым сайтом, отключение прокси или нестабильность регионального узла в большом масштабе происходят постоянно. Это не исключения, а нормальные условия работы. Считайте выходы заменяемыми ресурсами: при ошибке сначала определите, ограничивает ли цель скорость или выход недоступен; в первом случае используйте backoff, во втором смените выход и повторите попытку. Также фиксируйте процент сбоев каждого выхода и исключайте группы, которые явно деградируют.

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

Проверка согласованности данных

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

Эти проверки не обязательно делать сложными. Достаточно выборки по партиям, но кто-то должен просматривать результаты. В большом масштабе неправильные данные могут быть проблемнее, чем отсутствие данных.

Какие метрики отслеживать

Не нужно собирать слишком много метрик. Достаточно нескольких, отражающих состояние системы.

  • Процент успешных выполнений и распределение типов ошибок, чтобы видеть, какие проблемы растут
  • Длина очереди и среднее время ожидания; постоянно растущий backlog означает несоответствие между входящим потоком и возможностями обработки
  • Число активных сред и связанных процессов; длительный рост в одном направлении часто указывает на утечку при освобождении ресурсов
  • Объём результата за единицу времени, чтобы понять, не подавляет ли rate limiting пропускную способность
  • Процент сбоев выходов, чтобы решить, нужно ли заменить группу узлов

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

Вынесите слой среды отдельно

Все эти вопросы приводят к одному выводу: слой среды нужно управлять независимо от скриптов. Пул сред требует централизованного планирования, а не распределения сред по отдельным скриптам; освобождение ресурсов требует состояния, которое можно запросить, а не попыток каждого скрипта самостоятельно восстановиться; повтор с другой средой или другим выходом работает только тогда, когда среды можно планировать независимо.

Скрипты отвечают за логику, а слой среды — за ресурсы и идентичность. В такой архитектуре PurpleMark выполняет именно эту роль, предоставляя ресурсы сред, которые можно создавать пакетами, привязывать к независимым сетевым выходам и проверять их состояние.

Границы соответствия требованиям

Возможность масштабирования не означает, что данные можно собирать как угодно. Соблюдайте правила robots и условия использования целевого сайта, не собирайте персональную информацию, не обходите технические меры защиты и контролируйте частоту запросов, чтобы не нарушать нормальную работу сервиса. Стабильность — технический вопрос; разрешённость сбора — другой. Оба условия должны выполняться.