В OLX Group мы стремимся обслуживать клиентов на многих рынках (таких как Индия, Пакистан, Индонезия, Бразилия, Польша и Украина), предлагая наилучший опыт онлайн-объявлений. Очевидно, это приводит к ряду проблем, одна из которых: как последовательно предоставлять значимые рекомендации, например категории для посещения, учитывая, что между рынками так много различий?

Здесь на помощь приходит машинное обучение.

Предупреждение: в этой статье не проводится сравнение функций AWS Step Functions с другими механизмами обработки рабочих процессов (например, Airflow). Пожалуйста, обратитесь к этой статье для подробного сравнения нескольких из этих инструментов.

Экспериментируя с Sagemaker

Не секрет, что OLX в значительной степени работает поверх AWS, поэтому Sagemaker в настоящее время является первой остановкой, когда возникают проблемы. Часто процесс запускает экземпляр записной книжки в учетной записи разработчика и начинает тестирование комбинации моделей и гиперпараметров на подмножестве данных.

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

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

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

Предложенное решение

После экспериментов с несколькими комбинациями сервисов AWS мы пришли к следующему предложению решения:

  • Хранилище для входных, выходных и временных данных шагов: Amazon S3.
  • ETL (для получения и подготовки входных данных, а также выходных данных в правильном месте и формате): AWS Glue (Athena не может напрямую экспортировать в Parquet на момент написания этой статьи).
  • Обучение модели машинного обучения и пакетное преобразование: Amazon Sagemaker.
  • Пользовательская логика запуска с соответствующими входными параметрами: комбинация События Cloudwatch, Триггеры Glue ETL и AWS Lambda:

Несмотря на соответствие текущему набору лучших практик для бессерверных приложений в AWS, после развертывания конвейера мы быстро поняли:

  • Отслеживание того, какая работа принадлежит каждому выполнению, было болезненным (может помочь тегирование, но вам придется реализовать его самостоятельно).
  • Было сложно оценить текущее состояние (опять же, вам нужно было что-то реализовать, возможно, в DynamoDB, чтобы сохранить текущее состояние выполнения).
  • Требовались дополнительные инструменты / скрипты для оценки общего времени выполнения (поскольку есть несколько источников для проверки, таких как Sagemaker и Glue), а также для выполнения задач обратной засыпки / повторной обработки с прошлыми датами.
  • Координация между обучением и преобразованием была сложной, поскольку логика запуска была распределена между триггерами Glue ETL, событиями Cloudwatch и двумя лямбда-выражениями.

Эти проблемы в конечном итоге повредили опыту тех, кому нужно взаимодействовать с ним, поскольку устранение неполадок при неудачных запусках было болезненным по сравнению с другими платформами, такими как Airflow.

Чтобы решить проблемы, описанные выше, мы решили попробовать Step Functions.

Знакомство с AWS Step Functions

Проще говоря, AWS Step Functions - это универсальный инструмент для управления рабочими процессами. Более полное определение можно найти на их странице сервиса AWS.

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

Окончательная схема решения выглядит намного проще, поскольку AWS Step Functions координирует последовательность выполнения, а логика запуска перемещена в одно место:

Извлеченные уроки / подводные камни Step Functions

  1. Создайте запускающую лямбда-функцию.

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

2. Придерживайтесь встроенных интеграций AWS Step Functions.

Причина: Интеграция служб избавит вас от написания лямбда-выражений для запуска задания Glue ETL или учебного задания Sagemaker и предоставит вам полный контроль с консоли Step Functions или API (например, StopExecution будет остановить любой синхронный шаг, например arn:aws:states:::glue.startJobRun.sync).

3. Используйте Lambda для интерполяции и форматирования строк.

Причина: вы можете столкнуться со сценарием, как и мы, в котором вам нужно объединить входные параметры в одну строку (например, s3://my-bucket/model/market). К сожалению, на сегодняшний день вы не можете сделать это только с помощью ASL, поскольку он не поддерживает смешивание выражений JsonPath со строками (эта информация нигде явно не документирована, но я получил ее после разговора с AWS Support). Чтобы преодолеть это, вы можете написать очень глупую лямбда-функцию, которая сделает это за вас и вернет ее к следующим шагам.

Пример:

Код лямбда-функции:

ResultPath и JsonPath - ваши лучшие друзья.

Причина: Step Functions по умолчанию отправляет выходные данные предыдущего состояния в качестве входных данных для следующего состояния. Хотя в большинстве случаев это разумное поведение, часто вы хотите получить доступ к входным аргументам на промежуточном этапе, что невозможно. Чтобы преодолеть это, вы можете инкапсулировать результаты, полученные за один шаг, с помощью параметра ResultPath.

Пример:

Для получения дополнительной информации: https://docs.aws.amazon.com/step-functions/latest/dg/concepts-input-output-filtering.html

Заключение

AWS Step Functions оказались подходящими для варианта использования конвейера данных, поскольку он включает длительные этапы. Это очень удобный способ преодолеть ограничение по времени выполнения лямбда (а также дешевле оплачивать переходы между состояниями, чем «длительная» лямбда-функция). Хотя это и не является обязательным требованием, это помогло нам преодолеть разумное количество недостатков бессерверного конвейера данных в AWS. В этом нет никакого волшебства: вам все равно придется реализовать любую необходимую гибкость (например, повторная обработка с прошлой даты или пропуск части потока), поскольку она предназначена для покрытия общих сценариев использования рабочего процесса.

дальнейшее чтение

Спецификация государственного языка Amazon: https://states-language.net/spec.html

Вдохновение: https://github.com/aws-samples/aws-etl-orchestrator и https://epsagon.com/blog/hitchhikers-guide-to-aws-step-functions/