Распределенное сканирование и ограничение скорости / управление потоком
Я запускаю нишевый продукт поиска, который работает с веб-сканером. Текущий сканер - это отдельный (PHP Laravel) работник, который сканирует URL-адреса и помещает результаты в механизм Elastic Search. Система постоянно сканирует найденные URL с интервалом в X миллисекунд.
Это хорошо мне помогло, но с появлением новых крупных клиентов сканер достигнет предела. Мне нужно перестроить систему на распределенный сканер, чтобы ускорить сканирование. Проблема заключается в сочетании спецификаций ниже.
Система должна придерживаться следующих 2 правил:
- несколько рабочих (проблемы параллелизма)
- переменная ставка-лимит на клиента. Я должен быть уверен, что система не сканирует клиент X чаще, чем один раз каждые X миллисекунд.
Что я пробовал:
Я попытался поместить URL-адреса в таблицу MySQL и позволить рабочим запросить URL-адрес для сканирования на основе меток времени last_crawled_at в таблице клиентов и URL-адресов. Но MySQL не любит нескольких одновременных рабочих, и я получаю всевозможные тупики.
Я попытался вставить URL в движок Redis. Я получил такую работу, но только со скриптом Lua, который проверяет и устанавливает истекающий ключ для каждого обслуживаемого клиента. Это все похоже на хакерство.
Я думал о заполнении обычной очереди, но это нарушит правило № 2, так как я не могу быть на 100% уверен, что работники смогут обрабатывать очередь в режиме реального времени.
Кто-нибудь может объяснить мне, как большие мальчики делают это? Как несколько процессов могут запросить большой / массивный список URL-адресов на основе нескольких критериев (например, ограничение скорости клиента) и убедиться, что мы выдаем URL-адрес только одному работнику?
В идеале нам не понадобится другая база данных, кроме Elastic со всеми доступными / найденными URL, но я не думаю, что это возможно?
1 ответ
Взгляните на StormCrawler, это распределенный веб-сканер с модулем Elasticsearch. Он легко настраивается и обеспечивает вежливость, уважая robots.txt и имея по умолчанию один поток на хост или домен.