Некоторое время назад вместе с небольшой командой программистов мы начали разработку довольно интересного с технической точки зрения аналитического проекта.
Его основной целью была обработка данных, полученных с различных веб-страниц.
Необходимо было эти данные обработать в удобную форму и затем проанализировать собранную статистику.
Пока у нас не было большого количества всевозможных данных, у нас не возникало нестандартных задач и все решения были достаточно простыми.
Но проект рос, и объем собираемой информации, хотя и не очень быстро поначалу, все же увеличивался.
Кодовая база также выросла.
И через некоторое время мы осознали очень печальный факт — из-за всяких костылей и быстрых исправлений мы нарушили практически все возможные принципы проектирования.
И если поначалу организация кода была не так важна, то со временем стало понятно, что без хорошего рефакторинга далеко не уедешь.
После обсуждения и размышлений было решено, что для наших целей архитектура парсинга Интернета должна быть в первую очередь сервис-ориентированной (SOA).
Далее мы отталкивались от этого подхода и выделили три основные части будущей системы, отвечающие за следующие задачи:
- Получение содержимого страницы, данных от различных сервисов через API, данных из структурированных файлов.
- Структурирование полученной информации
- Анализ статистики и создание рекомендаций
Далее встал вопрос о том, как эти сервисы будут взаимодействовать друг с другом.
При определении общего механизма было решено использовать концепцию конвейерной обработки.
Достаточно понятный и простой подход, когда нужно последовательно обрабатывать любую информацию, передавая ее с одного узла на другой.
В качестве коммуникационной шины был выбран механизм организации массового обслуживания на базе RabbitMQ.
Итак, мы определились с основной архитектурной моделью.
Оно оказалось довольно простым, понятным и вполне расширяемым.
Далее я опишу, из чего состоит каждый сервис и что позволяет их масштабировать.
Сервисные компоненты и технологии
Давайте немного поговорим о технологиях, которые используются внутри каждого отдельного сервиса.В этой статье я в основном опишу, как работает служба Fetch. Однако другие сервисы имеют аналогичную архитектуру.
Ниже я опишу общие моменты, а точнее основные составляющие.
Всего их четыре.
Первый — модуль обработки данных, содержащий всю основную логику работы с данными.
Это набор работников, выполняющих задачи.
И клиенты, которые создают эти задачи.
Здесь Gearman используется в качестве сервера задач и, соответственно, его API. Сами работники и клиенты — это отдельные процессы, которые контролируются с помощью Supervisord. Следующий компонент — хранилище результатов.
Это база данных в MongoDB. По сути, данные извлекаются с веб-страниц или через различные API, которые возвращают JSON. А MongoDB весьма удобна для хранения такого рода информации.
Кроме того, может измениться структура результатов, появиться новые метрики и т. д. И в этом случае мы легко можем внести изменения в структуру документа.
И, наконец, третий компонент системы — очереди.
Есть два типа очередей.
Первые занимаются тем, что служат для передачи запросов к сервисам от других сервисов или от внешних клиентов (не путать с клиентами Gearman).
Такие очереди называются очередями запросов.
В случае с ранее упомянутой службой поиска контента (Fetch Service) строка JSON отправляется в очередь этого типа.
Он содержит URL нужной страницы или параметры для запроса к стороннему API. Второй тип очередей — очереди уведомлений.
В очередь такого типа сервисы помещают информацию об обработанных запросах и результат можно получить из хранилища.
Таким образом реализуется асинхронное выполнение запросов на получение, обработку и анализ данных.
В качестве брокера сообщений был выбран RabbitMQ. Это хорошее решение, оно прекрасно работает, хотя и с некоторыми проблемами.
Однако он слишком сложен для такой системы, поэтому, возможно, лучше заменить его чем-то более простым.
Коммуникация
Итак, связь обеспечивается посредством очередей и это очевидный и удобный способ соединения разных сервисов друг с другом.Далее я опишу процесс общения более подробно.
Есть два типа общения.
Внутри системы, между сервисами.
И между конечным клиентом и всей системой в целом.
Например, службе синтаксического анализа требуются новые данные.
Он отправляет запрос в очередь для Fetch Service, а затем продолжает заниматься своими делами — запросы выполняются асинхронно.
После того как служба Fetch получит запрос из очереди, она выполнит необходимые действия для получения данных из нужного источника (веб-страницы, файла, API) и размещения их в хранилище (MongoDB).
А затем отправит уведомление о завершении операции, которое, в свою очередь, будет получено службой синтаксического анализа для обработки свежих данных.
Служба получения
И напоследок расскажу еще немного о сервисе, отвечающем за получение исходных данных из внешних источников.Эта основная часть системы является первым этапом конвейера обработки данных.
На него возлагается ответственность за решение следующих задач:
- Получение данных из внешнего источника
- Обработка исключений и ошибок на этом этапе (например, обработка HTTP-ответов)
- Предоставление основной информации о полученных данных (заголовки, статистика изменения файлов и т.д.)
И сервис-ориентированный подход в этом случае очень удобен.
Мы просто говорим: «Дайте мне эти данные» и получаем желаемое.
Кроме того, такой подход позволяет создавать различных работников для получения информации из конкретных источников, не заставляя клиентов думать о том, откуда именно будет поступать материал для обработки.
Вы можете использовать разные API с разными форматами и протоколами.
Вся логика получения целевых данных изолирована на этом уровне.
В свою очередь, поверх этого сервиса можно построить другие, реализующие более конкретную логику, такую как сканирование сайтов, синтаксический анализ, агрегирование и т. д. Но нет необходимости каждый раз беспокоиться о сетевых взаимодействиях и обработке множества ситуаций.
Пожалуй, я закончу здесь.
Конечно, есть много других аспектов разработки таких систем.
Но главное помнить — всегда в первую очередь думать об архитектуре и использовать принцип единой ответственности.
Изолируйте компоненты системы и соединяйте их простым и понятным способом.
И вы получите результат, который легко масштабировать, легко контролировать и очень просто использовать в дальнейшем.
Теги: #design #parsing #php #rabbitmq #mongodb #gearman #workers #php #Системный анализ и проектирование
-
Я Пишу Текст В Freetype 2 И Opengl.
19 Oct, 24 -
Кластерный Анализ Для Всех
19 Oct, 24 -
Подкаст Appleinsider [01]
19 Oct, 24 -
Wired Uk С Индивидуальными Обложками
19 Oct, 24 -
Modx - Поиск В Админке Или Doc Finder 1.6
19 Oct, 24 -
Идея Сервиса: Open Source Total
19 Oct, 24