Общий обзор архитектуры сервиса для оценки внешности на основе нейронных сетей

Общий обзор архитектуры сервиса для оценки внешности на основе нейронных сетей

Вступление

Привет!

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

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

Приятного чтения!

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

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

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

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

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

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

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

Общий обзор архитектуры сервиса для оценки внешности на основе нейронных сетей

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

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

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

Общий обзор архитектуры сервиса для оценки внешности на основе нейронных сетей

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

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

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

Архитектура

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

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

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

Общий обзор архитектуры сервиса для оценки внешности на основе нейронных сетей

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

Поговорим подробнее о каждом из компонентов диаграммы, обозначим их 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)

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

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

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

RabbitMQ

RabbitMQ — это брокер сообщений на основе протокола 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 Swarm

 

Общий обзор архитектуры сервиса для оценки внешности на основе нейронных сетей

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

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

Общий обзор архитектуры сервиса для оценки внешности на основе нейронных сетей

Кластер с одним 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 для оркестратора контейнеров, а также имеет низкий порог вхождения.

Инфраструктура

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

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

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

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

Общий обзор архитектуры сервиса для оценки внешности на основе нейронных сетей
Общий обзор архитектуры сервиса для оценки внешности на основе нейронных сетей

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

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

Общий обзор архитектуры сервиса для оценки внешности на основе нейронных сетей

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

Общий обзор архитектуры сервиса для оценки внешности на основе нейронных сетей

Выводы

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

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

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

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

Источник: habr.com