Привет, меня зовут Павел Савельев, я руководитель отдела автоматизации бизнес-процессов в Lamoda. Мы работаем с очень разными задачами, и стараемся подобрать для каждой наиболее удобный инструментарий. Соответственно, мы используем разные языки — в наших системах можно встретить и Java, и Go, и немного Kotlin под андроид. При этом значительная часть разработки ведется на PHP, на нем написаны более двух десятков сервисов, которые автоматизируют не только работу с заказами, но и операционные процессы широкой сети доставки, колл-центров в трёх странах и собственной фотостудии, а также предоставление всего этого в виде услуг нашим B2B-партнерам. Эти сервисы поддерживают и развивают 5 команд разработки нашего отдела.
По мере развития как самих сервисов, так и инфраструктуры вокруг них, в этих системах все чаще возникают похожие задачи, такие как логирование в общую CLS (Centralized Logging System), тестирование файлового хранилища, сбор метрик для Prometheus и другие. Мы стараемся стандартизировать способы решения таких задач и использовать для разных систем общие компоненты.
Так так такой процесс происходит у нас регулярно, мы составили гайдлайн, который позволяет провести его наиболее безболезненно — об этом я постараюсь сделать доклад на одной из ближайших конференций.
Более двух десятков наших PHP-библиотек мы выложили в публичный доступ на GitHub. И планируем выкладывать и дальше. Зачем? Ну, мы вложили много ресурсов и (хочется верить) сделали хорошо. И мы хитро надеемся, что другие разработчики будут использовать наши библиотеки, помогать их допиливать и развивать дальше, вместо того, чтобы тратить время на написание своих аналогов с нуля. В этой статье я хочу кратко рассказать про семь библиотек, разработанных для решения частых для e-commerce задач — я буду рад, если они пригодятся и вам, а еще больше обрадуюсь их совместному развитию :)
Как и другие компании России, мы обязаны полностью соответствовать требованиям ФЗ-54, одним из которых является онлайн-фискализация. Все заказы, предоплачиваемые на сайте lamoda.ru, обязательно фискализируются: на них формируются онлайн-чеки, которые отправляются покупателям. Наш сервис фискализации работает по API с системой АТОЛ Онлайн, и первая в нашем списке библиотека — полноценный клиент для этого сервиса. Помимо самой библиотеки мы выложили также бандл, при помощи которого можно легко подключить ее к любым проектам на базе фреймворка Symfony. Сама же библиотека может быть встроена в любой другой PHP-фреймворк: Laravel, Yii и др. — достаточно написать лишь “обертку” для библиотеки.
Для обработки предоплатных платежей мы активно взаимодействуем с сервисом Payture. У этого сервиса есть несколько программных интерфейсов. Мы используем вариант Payture InPay и написали собственный API-клиент для него. Библиотека позволяет манипулировать несколькими терминалами, поддерживает стандартное логирование PSR-3. Также есть возможность использовать преднастроенный клиент Guzzle — это позволяет легко организовать тестирование с помощью Guzzle Mock Handler.
Наш бандл к библиотеке предоставляет семантическую конфигурацию терминалов и позволяет удобно сконфигурировать настройки клиента (пока только таймауты) для разных операций по API.
Один из важнейших проектов 2019 года в нашей компании — поддержка государственной маркировки товаров. В рамках этого проекта на все товары определенных категорий будут наноситься специальные уникальные коды — в формате GS1 Datamatrix. Эти коды позволят любому покупателю проверить подлинность товаров, их происхождение и историю. Для того, чтобы внутренние системы Lamoda могли работать с этими штрихкодами, мы разработали библиотеку для правильного парсинга кодов GS1.
В ближайшее время мы также планируем выложить исходные коды разработанных нами клиентов для взаимодействия с Информационной Системой Маркировки и Прослеживаемости (ИС МП).
У нас есть более сотни микросервисов, которые выполняют множество отдельных операций: проверяют статусы платежей или новые файлы в хранилищах, отправляют управляющие команды в кассы, скачивают и обрабатывают фотографии с внешних сервисов. Практически все эти операции выполняются в фоновом режиме, и для управления ими отлично подходит паттерн шина команд. Для реализации шины в PHP-системах мы выбрали готовое решение — открытую библиотеку Tactician.
Однако, возникла проблема: наши фоновые команды часто взаимодействуют с внешними сервисами, которые имеют ограничение на количество операций в n секунд. А в Tactician отсутствует возможность управлять количеством исполняемых команд в определенное окно времени. Поэтому мы разработали дополнительный middleware — библиотеку Tactician rate limit. С ее помощью можно добавить новый слой обработки, который отслеживает количество выполняемых в шине команд согласно выбранной стратегии rate limiting. Стратегии подключаемы, из коробки доступны стратегии из библиотеки stiphle.
Также в открытом доступе есть наш Symfony bundle к библиотеке.
Наши микросервисы генерируют технические и бизнес-метрики, которые потом собираются через Prometheus Operator со всего кластера k8s. Для управления всем этим мы написали библиотеку, которая обрабатывает пользовательские метрики по сценарию «собери-сохрани-покажи». При этом библиотека поддерживает режимы работы, в которых можно опустить один из пунктов сценария, чтобы увеличить эффективность. Например, для быстрых вычислимых метрик может выполняться упрощенный сценарий «собери-покажи». А работа с медленными бизнес-метриками может частично переводиться в фон, при этом разбиваясь на два этапа: «собери-сохрани» + «собери (из хранилища) — покажи».
В библиотеке есть необходимые уровни абстракции как для написания своих генераторов метрик, так и для написания хранилищ. Из коробки есть абстрактный адаптер для Doctrine, который можно настроить на entity для сохранения данных в БД.
В качестве форматов рендера метрик в данный момент поддерживаются prometheus и telegraf httpjson.
В комплекте к библиотеке идет Symfony bundle, который предоставляет семантическую конфигурацию источников метрик, хранилищ и роутинга метрик. Также в нем есть команды-хелперы для отладки и сохранения метрик из источников (например, для расчета метрик по cron).
Для автоматизации тестирования мы используем фреймворк Codeception, который позволяет нам писать тесты различных уровней и имеет достаточно обширную библиотеку стандартных модулей. Подробнее о наших подходах к разработке тестов мы писали недавно в отдельной статье и рассказывали на конференции PHP Russia. У Codeception есть готовые модули для взаимодействия с FTP и локальной файловой системой FileSystem, но в наших тестах есть потребность работы с бОльшим количеством файловых систем. Как минимум, мы используем еще AWS S3 и Webdav. Кроме того, со всеми файловыми системами хотелось бы взаимодействовать по одному API (это же всё файловые системы :)).
К счастью, существует открытая библиотека FlySystem, которая предоставляет единый программный интерфейс для работы с разными файловыми системами. Так что нам потребовалось только объединить два инструмента — что мы и сделали, написав обертку над FlySystem в виде модуля Codeception-flysystem. Сейчас он поддерживает SFTP, S3 и Webdav. Достаточно один раз сконфигурировать настройки для подключения к нужной файловой системе в yml-конфиге тестов, и после этого можно работать со всеми файловыми системами по одинаковому набору методов: записать файл, скопировать файл, почистить директорию и т.д. Модуль уже включён в страницу дополнений и рекомендаций от Codeception: codeception.com/addons.
В отделе автоматизации бизнес-процессов существуют системы, которые работают в режиме multi tenant (многоарендности). Для обеспечения их работы необходимо уметь работать с переменными окружения — определять, какую именно переменную использовать в текущий момент времени.
Наша библиотека предоставляет несколько стратегий для работы с переменными окружения в multi tenant режиме. Основываясь на параметрах, переданных на этапе инициализации, библиотека определяет, к какой именно переменной окружения следует обратиться в текущем запросе.
Это лишь первая часть библиотек. Внутри у нас есть ещё с десяток — они ждут очереди, когда мы их немного «причешем» и выложим в общий доступ. Меня мотивирует понимание, что эти библиотеки могут быть полезны кому-то ещё. Я радуюсь комментариям и звёздочкам на гитхабе, и надеюсь дальше развивать библиотеки вместе с другими разработчиками. Ведь с АТОЛ и Payture работают многие российские e-commerce проекты. Для Datamatrix, помимо описанного в статье парсера кодов, у нас есть еще пара клиентов, которые мы уже используем внутри — эти библиотеки первые в очереди на GitHub.
Стараемся не забывать и про остальные языки — мы уже выложили первую библиотеку на Go (про нее подробнее писали тут на Хабре) и готовим другие. Stay tuned!
По мере развития как самих сервисов, так и инфраструктуры вокруг них, в этих системах все чаще возникают похожие задачи, такие как логирование в общую CLS (Centralized Logging System), тестирование файлового хранилища, сбор метрик для Prometheus и другие. Мы стараемся стандартизировать способы решения таких задач и использовать для разных систем общие компоненты.
Когда одна из команд сталкивается с адаптацией или интеграцией нового сервиса/инструмента, который может стать общим для всех, мы инициируем разработку библиотеки в этой команде. А впоследствии готовый компонент подготавливается для будущего переиспользования и выкладывается в общий доступ.
Так так такой процесс происходит у нас регулярно, мы составили гайдлайн, который позволяет провести его наиболее безболезненно — об этом я постараюсь сделать доклад на одной из ближайших конференций.
Более двух десятков наших PHP-библиотек мы выложили в публичный доступ на GitHub. И планируем выкладывать и дальше. Зачем? Ну, мы вложили много ресурсов и (хочется верить) сделали хорошо. И мы хитро надеемся, что другие разработчики будут использовать наши библиотеки, помогать их допиливать и развивать дальше, вместо того, чтобы тратить время на написание своих аналогов с нуля. В этой статье я хочу кратко рассказать про семь библиотек, разработанных для решения частых для e-commerce задач — я буду рад, если они пригодятся и вам, а еще больше обрадуюсь их совместному развитию :)
1. Онлайн-фискализация: клиент для АТОЛ Онлайн
Как и другие компании России, мы обязаны полностью соответствовать требованиям ФЗ-54, одним из которых является онлайн-фискализация. Все заказы, предоплачиваемые на сайте lamoda.ru, обязательно фискализируются: на них формируются онлайн-чеки, которые отправляются покупателям. Наш сервис фискализации работает по API с системой АТОЛ Онлайн, и первая в нашем списке библиотека — полноценный клиент для этого сервиса. Помимо самой библиотеки мы выложили также бандл, при помощи которого можно легко подключить ее к любым проектам на базе фреймворка Symfony. Сама же библиотека может быть встроена в любой другой PHP-фреймворк: Laravel, Yii и др. — достаточно написать лишь “обертку” для библиотеки.
2. Предоплатные платежи: взаимодействие с Payture
Для обработки предоплатных платежей мы активно взаимодействуем с сервисом Payture. У этого сервиса есть несколько программных интерфейсов. Мы используем вариант Payture InPay и написали собственный API-клиент для него. Библиотека позволяет манипулировать несколькими терминалами, поддерживает стандартное логирование PSR-3. Также есть возможность использовать преднастроенный клиент Guzzle — это позволяет легко организовать тестирование с помощью Guzzle Mock Handler.
Наш бандл к библиотеке предоставляет семантическую конфигурацию терминалов и позволяет удобно сконфигурировать настройки клиента (пока только таймауты) для разных операций по API.
3. Маркировка товаров: парсер кодов GS1 Datamatrix
Один из важнейших проектов 2019 года в нашей компании — поддержка государственной маркировки товаров. В рамках этого проекта на все товары определенных категорий будут наноситься специальные уникальные коды — в формате GS1 Datamatrix. Эти коды позволят любому покупателю проверить подлинность товаров, их происхождение и историю. Для того, чтобы внутренние системы Lamoda могли работать с этими штрихкодами, мы разработали библиотеку для правильного парсинга кодов GS1.
В ближайшее время мы также планируем выложить исходные коды разработанных нами клиентов для взаимодействия с Информационной Системой Маркировки и Прослеживаемости (ИС МП).
4. Управление микросервисами: middleware для шины команд Tactician
У нас есть более сотни микросервисов, которые выполняют множество отдельных операций: проверяют статусы платежей или новые файлы в хранилищах, отправляют управляющие команды в кассы, скачивают и обрабатывают фотографии с внешних сервисов. Практически все эти операции выполняются в фоновом режиме, и для управления ими отлично подходит паттерн шина команд. Для реализации шины в PHP-системах мы выбрали готовое решение — открытую библиотеку Tactician.
Однако, возникла проблема: наши фоновые команды часто взаимодействуют с внешними сервисами, которые имеют ограничение на количество операций в n секунд. А в Tactician отсутствует возможность управлять количеством исполняемых команд в определенное окно времени. Поэтому мы разработали дополнительный middleware — библиотеку Tactician rate limit. С ее помощью можно добавить новый слой обработки, который отслеживает количество выполняемых в шине команд согласно выбранной стратегии rate limiting. Стратегии подключаемы, из коробки доступны стратегии из библиотеки stiphle.
Также в открытом доступе есть наш Symfony bundle к библиотеке.
5. Сбор и рендеринг метрик для Prometheus
Наши микросервисы генерируют технические и бизнес-метрики, которые потом собираются через Prometheus Operator со всего кластера k8s. Для управления всем этим мы написали библиотеку, которая обрабатывает пользовательские метрики по сценарию «собери-сохрани-покажи». При этом библиотека поддерживает режимы работы, в которых можно опустить один из пунктов сценария, чтобы увеличить эффективность. Например, для быстрых вычислимых метрик может выполняться упрощенный сценарий «собери-покажи». А работа с медленными бизнес-метриками может частично переводиться в фон, при этом разбиваясь на два этапа: «собери-сохрани» + «собери (из хранилища) — покажи».
В библиотеке есть необходимые уровни абстракции как для написания своих генераторов метрик, так и для написания хранилищ. Из коробки есть абстрактный адаптер для Doctrine, который можно настроить на entity для сохранения данных в БД.
В качестве форматов рендера метрик в данный момент поддерживаются prometheus и telegraf httpjson.
В комплекте к библиотеке идет Symfony bundle, который предоставляет семантическую конфигурацию источников метрик, хранилищ и роутинга метрик. Также в нем есть команды-хелперы для отладки и сохранения метрик из источников (например, для расчета метрик по cron).
6. Тестирование файлового хранилища: работа с разными файловыми системами
Для автоматизации тестирования мы используем фреймворк Codeception, который позволяет нам писать тесты различных уровней и имеет достаточно обширную библиотеку стандартных модулей. Подробнее о наших подходах к разработке тестов мы писали недавно в отдельной статье и рассказывали на конференции PHP Russia. У Codeception есть готовые модули для взаимодействия с FTP и локальной файловой системой FileSystem, но в наших тестах есть потребность работы с бОльшим количеством файловых систем. Как минимум, мы используем еще AWS S3 и Webdav. Кроме того, со всеми файловыми системами хотелось бы взаимодействовать по одному API (это же всё файловые системы :)).
К счастью, существует открытая библиотека FlySystem, которая предоставляет единый программный интерфейс для работы с разными файловыми системами. Так что нам потребовалось только объединить два инструмента — что мы и сделали, написав обертку над FlySystem в виде модуля Codeception-flysystem. Сейчас он поддерживает SFTP, S3 и Webdav. Достаточно один раз сконфигурировать настройки для подключения к нужной файловой системе в yml-конфиге тестов, и после этого можно работать со всеми файловыми системами по одинаковому набору методов: записать файл, скопировать файл, почистить директорию и т.д. Модуль уже включён в страницу дополнений и рекомендаций от Codeception: codeception.com/addons.
7. Работа с переменными окружения в multi tenant режиме
В отделе автоматизации бизнес-процессов существуют системы, которые работают в режиме multi tenant (многоарендности). Для обеспечения их работы необходимо уметь работать с переменными окружения — определять, какую именно переменную использовать в текущий момент времени.
Наша библиотека предоставляет несколько стратегий для работы с переменными окружения в multi tenant режиме. Основываясь на параметрах, переданных на этапе инициализации, библиотека определяет, к какой именно переменной окружения следует обратиться в текущем запросе.
Продолжение следует
Это лишь первая часть библиотек. Внутри у нас есть ещё с десяток — они ждут очереди, когда мы их немного «причешем» и выложим в общий доступ. Меня мотивирует понимание, что эти библиотеки могут быть полезны кому-то ещё. Я радуюсь комментариям и звёздочкам на гитхабе, и надеюсь дальше развивать библиотеки вместе с другими разработчиками. Ведь с АТОЛ и Payture работают многие российские e-commerce проекты. Для Datamatrix, помимо описанного в статье парсера кодов, у нас есть еще пара клиентов, которые мы уже используем внутри — эти библиотеки первые в очереди на GitHub.
Стараемся не забывать и про остальные языки — мы уже выложили первую библиотеку на Go (про нее подробнее писали тут на Хабре) и готовим другие. Stay tuned!