Разработка Фронтеры финансируется компанией Scrapinghub Ltd., имеет полностью открытый исходный код (находится на GitHub, BSD 3-clause лицензия) и модульную архитектуру. Мы стараемся чтобы и процесс разработки тоже был максимально прозрачным и открытым.
В этой статье я собираюсь рассказать о проблемах с которыми мы столкнулись при разработке Фронтеры и эксплуатации роботов на ее основе.
Устройство распределенного робота на базе Фронтеры выглядит так:
На картинке изображена конфигурация с хранилищем Apache HBase и шиной данных Apache Kafka. Процесс запускается из воркера стратегии обхода (SW), который планирует URL-ы, с которых нужно начать обход. Эти URL-ы попадают «scoring log», топик кафки (выделенный канал сообщений), потребляются воркером БД и им же планируются в топик «new batches», откуда поступают в пауки на основе Scrapy. Паук Scrapy разрешает DNS имя, поддерживает пул открытых соединений, получает контент и посылает его в топик «spider log». Откуда контент потребляется снова воркером стратегии и в зависимости от логики закодированной в стратегии обхода он планирует новые URL-ы.
Если кому-то интересно, то вот видео моего доклада о том, как мы обходили испанский интернет с помощью Фронтеры.
На текущий момент мы столкнулись с тем, что людям которые пытаются развернуть робота у себя очень тяжело дается конфигурирование распределенных компонент. К сожалению, развертывание Фронтеры на кластере предполагает понимание ее архитектуры, чтение документации, правильную настройку шины данных (message bus) и хранилища под нее. Все это очень затратно по времени и отнюдь не для начинающих. Поэтому мы хотим автоматизировать развертывание на кластере. Мы выбрали Kubernetes и Docker для достижения этих целей. Большой плюс Kubernetes в том, что он поддерживается многими облачными провайдерами (AWS, Rackspace, GCE и др.) Т.е. с помощью него можно будет развернуть Фронтеру даже не имея настроенного Kubernetes кластера.
Другая проблема в том, что Фронтера она как система водоснабжения ядерной электростанции. В ней есть потребители и производители для них очень важно контролировать такие характеристики, как скорость потока и производительность, в разных местах системы. Здесь следует напомнить, что Frontera это онлайн система. Классические роботы (Apache Nutch), напротив, работают в пакетном режиме: сначала порция планируется, затем скачивается, затем парсится и снова планируется. Одновременный парсинг и планирование не предусмотрены в таких системах. Таким образом, у нас встает проблема синхронизации скорости работы разных компонент. Довольно тяжело спроектировать робота, который обходит страницы с постоянной производительностью с большим количеством потоков, при этом сохраняет их в хранилище и планирует новые. Разнится скорость ответа веб-серверов, размер и количество страниц на сайте, количество ссылок, все это делает невозможным точную подгонку компонент по производительности. В качестве решения этой проблемы мы хотим сделать веб-интерфейс на базе Django. Он будет отображать основные параметры и если получится подсказывать какие нужно принять меры оператору робота.
Я уже упоминал о модульной архитектуре. Как и любой проект с открытым кодом мы стремимся к разнообразию технологий, которые мы поддерживаем. Поэтому сейчас у нас в Pull Request’ах готовится поддержка распределенного Redis, было уже две попытки сделать поддержку Apache Cassandra, ну и мы бы хотели поддержку RabbitMQ в качестве шины данных.
Все эти проблемы мы рассчитываем хотя бы частично решить в рамках Google Summer Of Code 2017. Если Вам что-то кажется интересным, и Вы студент, то дайте нам знать на frontera@scrapinghub.com и подайте заявку через форму GSoC. Подача заявок начинается с 20 марта и продлится до 3 апреля. Полное расписание GSoC 2017 здесь.
Конечно же, есть еще и проблемы производительности. На данный момент в Scrapinghub в пилотном режиме работает сервис по массивному скачиванию страниц на основе Фронтеры. Клиент нам предоставляет набор доменов, к которым он бы хотел получить контент, а мы их скачиваем и помещаем в S3 хранилище. Оплата за скачанный объем. В таких условиях мы стараемся качать как можно больше страниц в единицу времени. При попытке масштабировать Фронтеру до 60 спайдеров мы с толкнулись с тем, что HBase (через Thrift интерфейс) деградирует при записи в него всех найденных ссылок. Эти данные мы называем ссылочной базой, а нужна она для того, чтобы знать когда и что мы скачали, какой ответ получили и т.п. На кластере из 7 регион серверов у нас кол-во запросов доходит до 40-50K в секунду и при таких объемах время ответа сильно увеличивается. Производительность записи сильно падает. Решать такую проблему можно разными способами: например сохранять в отдельный быстрый лог, а позже его пакетными методами записывать в HBase, или же обращаться в HBase напрямую минуя Thrift, через собственный Java клиент.
Также мы постоянно работаем над улучшением надежности. Слишком большой скачанный документ или внезапные сетевые проблемы не должны приводить к остановке компонент. Тем не менее это иногда случается. Для диагностики таких случаев мы сделали обработчик сигнала ОС SIGUSR1, который сохраняет в лог текущий стек процесса. Несколько раз нам это очень сильно помогло разобраться в чем была проблема.
Мы планируем и дальше улучшать Фронтеру, и надеемся что сообщество активных разработчиков будет расти.
Комментарии (32)
square
29.03.2017 16:10Возможно перед HBase поставить фильтр Блума, чтобы поменьше его кантовать? Или там иного рода проблемы?
slavenski
29.03.2017 16:28-1Я далек от Web'а, и сейчас, наверное, моя карма уйдет в небытие =), но подскажите, правильно ли я понял, разрабатывается фреймворк, который исполняет роль поисковика?
asibiryakov
29.03.2017 16:29Этот фреймворк скачивает документы из сети. Скачанный контент может использоваться для построения поисковика.
mizhgun
29.03.2017 17:20А мне всегда виделось, что Frontera это фреймворк не для скачивания, а для построения стратегии обхода URLов, в которую при желании можно впилить любую скачивающую часть, не только Scrapy.
asibiryakov
29.03.2017 17:55Это тоже верно. Просто по мере разработки мы поняли, что стратегия обхода отдельно от хранилища и от других компонент, отвечающих за обмен данными не представляет большой пользы. В результате мы разработали эти компоненты и приняли решение, что Фронтера будет навязывать архитектуру всего робота. При этом мы старались сделать её максимально расширяемой.
mizhgun
29.03.2017 18:14Не следил за Фронтерой уж год наверное. То есть архитектурно вы как-то жестко сейчас завязаны именно на Скрапи?
asibiryakov
30.03.2017 12:21Использование Scrapy не является обязательным при построении роботов на Fronter'е. Но если Вы берете воркер стратегии, разрабатываете под него стратегию обхода, то должны будете считаться с тем, как во Fronter'е реализован менеджмент состояний, очередь и обмен данными между компонентами.
mizhgun
29.03.2017 17:52Имхо, если у людей есть четкое понимание, что такое Frontera, зачем она им надо и как ее готовить, то вряд ли подъем и настройка HBase и Kafka вызовет у них какие-то прямо проблемы. Другой вопрос, что тюнить их под задачу уже нетривиально, но это в любом случае, независимо от навыков.
asibiryakov
29.03.2017 17:56Скорее наоборот, это понимание у них не появится пока они не возьмут и не попробуют. А вот с этим у нас не все хорошо.
mizhgun
29.03.2017 18:06Так речь как раз о том, что для того, чтобы возникло само желание взять и пробовать Фронтеру, нужно иметь определенный порог знаний и опыта и соответствующий круг задач, это же не Скрапи с его массовой индийско-апворковской аудиторией.
gearbox
29.03.2017 23:00>Разнится скорость ответа веб-серверов, размер и количество страниц на сайте
Учитываете ли при работе данные с robots.txt (второй версии желательно) Если от ваших запросов сервер начинает тупить — мониторите/замеряете/корректируете частоту запросов?
Писал паука для одного из проектов, имхо — если не самая сложная то одна из по головоломности частей получилась как раз работа с robots.txt Но у меня там еще загон был — разные политики по юзер-агенту (статичный, round-robin, кастом) и юзерагент мог как учитываться так и нет при обработке robots (в зависимости от настроек)asibiryakov
30.03.2017 12:12Статья про фреймворк, а не про конкретный робот. Есть два способа обрабатывать robots.txt в рамках Fronter'ы и Scrapy. Самое простое, это использовать RobotsTxtMiddleware в Scrapy. Перед обработкой URL запрашивается robots.txt с домена, кешируется, и все запросы к домену проверяются если допустимы в рамках robots.txt домена.
Второй способ, это интегрировать обработку robots.txt в стратегию обхода, и попросту не планировать URL, которые запрещены в robots.txt.gearbox
30.03.2017 17:21allow/disallow отрабатываются тривиально, речь шла о нормальной работе с Request-rate и Visit-time. Но ответ Ваш я понял, спасибо!
roller
30.03.2017 01:15Люди, которые научатся доставать исходные данные из react-кода без выполнения js — озолотяться
fediq
30.03.2017 10:36Я так понимаю, автор имеет отношение к Scrapinghub. Скажите, а ваша Portia — она насколько стабильно работает и насколько сложный парсинг поддерживает?
Попробовал вчера hosted версию — при работе с переменным числом блоков эвристики постоянно промахиваются, и получается мусор. При попытке выгрузить "накликанный" парсер в формате Scrapy — выгружает что-то похожее на mock'овый код — модельки описаны, а алгоритм парсинга — нет.
kmike
30.03.2017 12:15Насколько знаю, внутри portia — библиотечка https://github.com/scrapy/scrapely. Ну т.е. там еще куча всего есть, но вроде дефолтное извлечение выполняется именно через scrapely. Это и есть алгоритм парсинга.
yusman
Интересный продукт, спасибо!
Подскажите, а Scrapinghub умеет работать с «динамическими» страницами с большим количеством JS? Например, ждать появления какого либо элемента страницы, прежде чем начать парсить страницу.
square
Это крайне нетривиальная задача, а тут обычный паук, вам нужен куда более «сообразительный» парсер.
gearbox
Тривиальная но крайне требовательная к ресурсам — так имхо правильнее. На фантоме пишется за вечер. Я писал.
roller
Для одного сайта. После того как вы посмотрели его глазами и нашли к чему привязаться в xpath (теги, id, вложенность). И написали скрипты именно для этого сайта. А сайтов тысячи.
gearbox
Мы похоже про разные вещи говорим.
дернули спашку, отрендерили в фантоме, слили построенный дом — дальше можно индексировать как обычную статику. Про эмуляцию действий пользователя речи не шло.
roller
Ок. Отрендерили вы DOM, а если на живом сайте скролить вниз происходит подгрузка данных. То есть на первом шаге вы не получает все данные. Если это не критично, то конечно так можно поступить.
kirill3333
В целом согласен с вами фантом не предоставляет подобного функционала и обычно делаеться это либо ожиданием появления какого то элемента либо функцией которая запускаеться после полной загрузки страницы и переодически проверяет не появились ли новые запросы в течении какого то времени и если нет то считается что сайт отренедрился
gearbox
а это уже селениум c драйвером фантома. Но тут да — под каждый сайт (движок) свои хаки. Ну или подождать сильный ИИ )
gearbox
Да, в таком юзкейсе Вы правы и это очевидно. Я говорил именно об индексации страниц, генерируемых js без действий пользователя. Их тоже немало, других простых способов решить вопрос — нет, гугль, насколько мне известно поступает также.
asibiryakov
Пока что только применительно к конкретному веб-сайту. У нас есть своя разработка https://github.com/scrapinghub/splash