Allgemeng Iwwersiicht vun der Servicearchitektur fir Erscheinungsbewäertung baséiert op neuralen Netzwierker

Allgemeng Iwwersiicht vun der Servicearchitektur fir Erscheinungsbewäertung baséiert op neuralen Netzwierker

Element

Hallo!

В данной статье я поделюсь опытом построения микросервисной архитектуры для проекта, использующего нейронные сети.

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

Genéisst Lies!

Пару слов о задаче и ее решении

Основная идея – на основе фото дать оценку привлекательности человека по десятибалльной шкале.

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

Сейчас же мы верхнеуровнево пройдемся по пайплайну оценки, а упор сделаем на взаимодействие микросервисов в контексте общей архитектуры проекта. 

При работе над пайплайном оценки привлекательности, задача была декомпозирована на следующие составляющие:

  1. Выделение лиц на фото
  2. Оценка каждого из лиц
  3. Рендер результата

Первое решается силами предобученной MTCNN. Для второго была обучена сверточная нейросеть на PyTorch, в качестве backbone был использован ResNet 34 – из баланса «качество / скорость инференса на CPU»

Allgemeng Iwwersiicht vun der Servicearchitektur fir Erscheinungsbewäertung baséiert op neuralen Netzwierker

Функциональная диаграмма пайплайна оценки

Анализ требований к архитектуре проекта

В жизненном цикле ML проекта этапы работы над архитектурой и автоматизацией развертывания модели, зачастую, одни из самых затратных по времени и ресурсам.

Allgemeng Iwwersiicht vun der Servicearchitektur fir Erscheinungsbewäertung baséiert op neuralen Netzwierker

Жизненный цикл ML проекта

Данный проект не исключение – было принято решение обернуть пайплайн оценки в онлайн-сервис, для этого требовалось погрузиться в архитектуру. Были обозначены следующие базовые требования:

  1. Единое хранилище логов – все сервисы должны писать логи в одно место, их должно быть удобно анализировать
  2. Возможность горизонтального масштабирования сервиса оценки — как наиболее вероятного Bottleneck
  3. На оценку каждого изображения должно быть выделено одинаковое кол-во ресурсов процессора — во избежание выбросов в распределении времени на инференс
  4. Быстрое (пере)развертывание как конкретных сервисов, так и стэка в целом
  5. Возможность, при необходимости, использовать в разных сервисах общие объекты

Architektur

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

Для того, чтобы избавиться от лишней головной боли, в качестве фронтенда был выбран Telegram API.

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

Allgemeng Iwwersiicht vun der Servicearchitektur fir Erscheinungsbewäertung baséiert op neuralen Netzwierker

Структурная диаграмма готовой архитектуры

Поговорим подробнее о каждом из компонентов диаграммы, обозначим их Single Responsibility в процессе оценки изображения.

Микросервис «attrai-telegram-bot»

Данный микросервис инкапсулирует все взаимодействия с Telegram API. Можно выделить 2 основных сценария – работа с пользовательским изображением и работа с результатом пайплайна оценки. Разберем оба сценария в общем виде.

При получении пользовательского сообщения с изображением:

  1. Производится фильтрация, состоящая из следующих проверок:
    • Наличия оптимального размера изображения
    • Количества изображений пользователя, уже находящихся в очереди
  2. При прохождении первичной фильтрации изображение сохраняется в docker volume
  3. В очередь “to_estimate” продьюсится таска, в которой, в том числе, фигурирует путь до изображения, лежащего в нашем volume
  4. Если вышеперечисленные этапы пройдены успешно – пользователь получит сообщение с примерным временем обработки изображения, которое рассчитывается на основе количества тасков в очереди. В случае ошибки пользователь будет явным образом об этом оповещен – путем отправки сообщения с информацией о том, что могло пойти не так.

Также, данный микросервис, как celery worker, слушает очередь «after_estimate», которая предназначается для тасков, прошедших через пайплайн оценки.

При получении новой таски из “after_estimate”:

  1. Если изображение обработано успешно – отправляем результат пользователю, если нет – оповещаем об ошибке
  2. Удаляем изображение, являющееся результатом пайплайна оценки

Микросервис оценки «attrai-estimator»

Данный микросервис является celery worker и инкапсулирует в себе всё, что связано с пайплайном оценки изображения. Алгоритм работы тут один – разберем его.

При получении новой таски из “to_estimate”:

  1. Прогоняем изображение через пайплайн оценки:
    1. Загружаем изображение в память
    2. Приводим изображение к нужному размеру
    3. Находим все лица (MTCNN)
    4. Оцениваем все лица (оборачиваем найденные в прошлом пункте лица в батч и инференсим ResNet34)
    5. Рендерим итоговое изображением
      1. Отрисоваем bounding boxes
      2. Отрисовываем оценки
  2. Удаляем пользовательское (исходное) изображение
  3. Сохраняем выход с пайплайна оценки
  4. Кладем таску в очередь “after_estimate”, которую слушает разобранный выше микросервис “attrai-telegram-bot”

Graylog (+ mongoDB + Elasticsearch)

graulog — это решение для централизованного управления логами. В данном проекте, он использовался по своему прямому назначению.

Выбор пал именно на него, а не на привычный всем ELK стэк, по причине удобства работы с ним из под Python. Все, что необходимо сделать для логирования в Graylog, это добавить GELFTCPHandler из пакета graypy к остальным root logger handlers нашего python-микросервиса.

Я, как человек, который до этого работал только с ELK стэком, в целом, получил позитивный опыт во время работы с Graylog. Единственное, что удручает – превосходство по фичам Kibana над веб-интерфейсом Graylog.

Kanéngchen MQ

Kanéngchen MQ — это брокер сообщений на основе протокола AMQP.

В данном проекте он использовался как наиболее стабильный и проверенный временем брокер для Celery и работал в durable режиме.

Redis

Redis — это NoSQL СУБД, работающая со структурами данных типа «ключ — значение»

Иногда возникает необходимость использовать в разных python-микросервисах общие объекты, реализующие какие-либо структуры данных.

Например, в Redis хранится hashmap вида «telegram_user_id => количество активных тасок в очереди», что позволяет ограничить количество запросов от одного пользователя определенным значением и, тем самым, предотвратить DoS-атаки.

Формализуем процесс успешной обработки изображения

  1. Пользователь отправляет изображение в Telegram бота
  2. «attrai-telegram-bot» получает сообщение от Telegram API и разбирает его
  3. Таск с изображением добавляется в асинхронную очередь «to_estimate»
  4. Пользователь получает сообщение с планируемым временем оценки
  5. «attrai-estimator» берет таск из очереди «to_estimate», прогоняет через пайплайн оценки и продьюсит таск в очередь «after_estimate»
  6. «attrai-telegram-bot», слушающий очередь «after_estimate», отправляет результат пользователю

DevOps

Наконец, после обзора архитектуры, можно перейти к не менее интересной части — DevOps

Docker Schwärm

 

Allgemeng Iwwersiicht vun der Servicearchitektur fir Erscheinungsbewäertung baséiert op neuralen Netzwierker

Docker Schwärm  — система кластеризации, функционал которой реализован внутри Docker Engine и доступен из коробки.

При помощи «роя», все ноды нашего кластера можно разделить на 2 типа – worker и manager. На машинах первого типа разворачиваются группы контейнеров (стэки), машины второго типа отвечают за скалирование, балансировку и другие классные фичи. Менеджеры по умолчанию являются и воркерами.

Allgemeng Iwwersiicht vun der Servicearchitektur fir Erscheinungsbewäertung baséiert op neuralen Netzwierker

Кластер с одним leader manager и тремя worker

Минимально возможный размер кластера – 1 нода, единственная машина будет одновременно выступать как leader manager и worker. Исходя из размера проекта и минимальных требований к отказоустойчивости, было принято решение использовать именно этот подход.

Забегая вперед, скажу, что с момента первой production-поставки, которая была в середине июня, проблем, связанных с данной организацией кластера, не было (но это не значит, что подобная организация хоть сколько-нибудь допустима в любых средне-крупных проектах, на которые накладываются требования по отказоустойчивости).

Docker Stack

В режиме «роя» за развертывание стэков (наборов docker services) отвечает docker stack

Он поддерживает docker-compose конфиги, позволяя дополнительно использовать deploy параметры.  

Например, при помощи данных параметров были ограничены ресурсы на каждый из инстансов микросервиса оценки (выделяем на N инстансов N ядер, в самом микросервисе ограничиваем кол-во ядер, используемое PyTorch`ем, одним)

attrai_estimator:
  image: 'erqups/attrai_estimator:1.2'
  deploy:
    replicas: 4
    resources:
      limits:
        cpus: '4'
    restart_policy:
      condition: on-failure
      …

Важно отметить, что Redis, RabbitMQ и Graylog — stateful сервисы и масштабировать их так же просто, как «attrai-estimator», не получится

Предвещая вопрос — почему не Kubernetes?

Кажется, что использование Kubernetes в проектах маленького и среднего размера – оверхед, весь необходимый функционал можно получить от Docker Swarm, который довольно user friendly для оркестратора контейнеров, а также имеет низкий порог вхождения.

Infrastruktur

Развертывалось это все на VDS со следующими характеристиками:

  • CPU: 4 ядра Intel® Xeon® Gold 5120 CPU @ 2.20GHz
  • RAM: 8 GB
  • SSD: 160GB

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

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

Allgemeng Iwwersiicht vun der Servicearchitektur fir Erscheinungsbewäertung baséiert op neuralen Netzwierker
Allgemeng Iwwersiicht vun der Servicearchitektur fir Erscheinungsbewäertung baséiert op neuralen Netzwierker

Еще немного графики

Количество уникальных пользователей и запросов на оценку, с момента деплоя, в зависимости от дня

Allgemeng Iwwersiicht vun der Servicearchitektur fir Erscheinungsbewäertung baséiert op neuralen Netzwierker

Распределение времени инференса пайплайна оценки

Allgemeng Iwwersiicht vun der Servicearchitektur fir Erscheinungsbewäertung baséiert op neuralen Netzwierker

Conclusiounen

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

Думаю, проекты маленького и среднего размеров, использующие в своем процессе реалтайм инференс нейронных сетей на CPU, успешно могут перенять практики, описанные в данной статье.

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

Потыкать бота можно в Telegram — @AttraiBot, работать будет, как минимум, до конца осени 2020 года. Напомню — никакие пользовательские данные не хранятся — ни исходные изображения, ни результаты пайплайна оценки — все сносится после обработки.

Source: will.com

Setzt e Commentaire