Это короткая история наивного любителя популярных технологий.
Ранее я уже писал почему на моем текущем проекте мы решили использовать — Apache Kafka, если вкратце, то цель — унификация используемых технологий в компании.
Сфера деятельности компании это ставки на спорт, зона ответственности моей команды состоит в том, чтобы принять и оцифровать происходящее на игровом поле, будь то реальное поле з зеленой травкой или серый бетон виртуального CS:GO.
Очень важно чтобы данные инцидент произошедший в игре был передан дальше по системе и коэффициенты были пересчитаны быстрее чем потенциальный Беттер поставит очередную ставку на основании новых вводных. Например, забитый гол в лиге чемпионов на 90+ минуте основного времени.
Итак, вернемся к нашим баранам.
Думаю никому не секрет, что в больших компаниях используется практика использования нескольких типов языков программирования.
Там где можно сэкономить — экономят.
Наша компания не исключение. Для обеспечения организационной части бизнеса — СРМ и интерфейсов первичного ввода данных(интерфейс судьи/статиста) мы используем PHP, для того чтобы производить сложные вычисления, используются иные технологии.
Для обмена данными между системами, наиболее принятым способом, является применение очередей.
Что для “русского” - хорошо, для “немца” — смерть.
Адаптировав эту поговорку под ИТ можно сказать иначе:
Что для компилируемых ЯП — хорошо, для скриптовых — смерть.
Kafka славится тем что может принимать большое, очень большое, количество данных в секунду.
Но, есть маленький нюанс.
Для того чтобы Kafka могла принимать это самое большое количество сообщений, нужно установить соединение, а у такой сложной системы как Kafka это не самое простое действие.
В момент соединения система должна выбрать какой именно брокер будет использован, а также какой(-ие) партиции будут задействованы для записи, все это занимает время.
В моем случае процесс установления соединения занимал 100–300мс.
Сразу же отмечу что система работала с дефолтными настройками и никакой тюнинг не производился, за неимением специалистов с глубокой экспертизой по настройке работы Apache Kafka.
Проблема: Сам по себе тайминг в 300мс для нас не являлся критическим, нас устраивает время ответа до 1 сек. Поскольку весь остальной код отрабатывает за ~100мс, то мы отлично вкладывались в установленные нормы SLA.
Несмотря на то, что сам код приложения и Apache Kafka(AWS MSK) находились в одной Availabilty Zone, а поначалу и вовсе на соседних EC-2(Kafka была в Docker’е), это никак не избавило нас от сетевых сбоев и задержек/проблем присутствующих в инфраструктуре AWS.
Мы постоянно наблюдали, несколько раз в сутки, скачки во времени установления соединения до 1500мс, что являлось для нас критическим таймингом. Мы могли бы конечно решить этот вопрос, например, с помощью — родного для PHP брокера сообщений RabbitMQ, но это же "костыльный костыль" и еще как минимум одна/две точки отказа, вторая это демон(или тулза) который бы перекладывал сообщения из одной системы очередей в другую.
Поскольку мы не хотели идти на столь отчаянный шаг, мы решили посмотреть в другую сторону. Этой стороной оказалось использование http proxy. После некоторых исследований и экспериментов мы остановились на open sourse решении от компании confluent — Kafka Rest Proxy.
Данный инструмент написан на Java. Весь секрет в том что прокси подсоединяется к кластеру Kafka, держит с ним соединение и принимает http запросы — быстро производит запись и отдает ответ содержащий метаинформацию о результате вставки, например - offset записанного сообщения.
В итоге мы получили стабильную скорость записи ~10мс, без неожиданных скачков. Естественно скорость будет зависеть от массы факторов, как например: размер сообщения, количество брокеров в вашем кластере или сотен других доступных к настройке параметров Kafka.
Вывод: шалость удалась, но пришлось использовать магию из запретной секции :)
Комментарии (8)
vgoodvin
31.08.2022 10:03+1А что делает RabbitMQ для PHP родным? Для него кстати тоже есть такой прокси cloudamqp/amqproxy.
VladVerpeta Автор
31.08.2022 11:02+1php - умеет держать persistent connection по amqp протоколу, а с Kafka - такого пока не придумали.
В целом, написал так потому что, практически все проекты о которых я слышал, используют именно RabbitMQ, в том числе туториалы для начинающих также описывают работу с очередями на базе RabbitMQ.
RabbitMQ использует протокол amqp - который также является достаточно затратным для установки соединения, но на моей практике - проблем это не вызывало.
С RabbitMQ начинаются проблемы, когда начинается работа с 10+к сообщений в секунду или же когда хочется большие сообщения пересылать(500kb+).
Djeux
31.08.2022 11:01Если память не изменяет, Slack использует Go для подобного решения. Go держит соединение с кафкой и принимает http запросы от PHP
VladVerpeta Автор
31.08.2022 11:34Действительно, есть огромный соблазн использовать самописную прокси, написанную за полчаса на Гошке, которая жрёт оперативки в 100 раз меньше, но мы пока что не имели возможности выделить времени на тестирование стабильности работы такого решения в продакшене.
Djeux
31.08.2022 12:03Можно еще
librdkafka
с https://github.com/arnaud-lb/php-rdkafka глянуть. Решает проблему поднятия соединения.VladVerpeta Автор
31.08.2022 12:13Мы её и используем)
Она отлично работает, мы ее используем в консюмерах, там где соединение устанавливается 1н раз и держится постоянно, но в режиме request/response эта либа не дает возможности держать постоянное соединение(
xeeaax
Разумно. Если критично время, то вредно под запрос устанавливать соединение.
(у нас один разработчик смог даже на REST Proxy каждый раз устанавливать соединение)
Кстати, а почему Kafka, если важно время? Она вроде сильно хуже RabbitMQ по таймингам?
VladVerpeta Автор
Иные команды в компании имеют потребность использовать Kafka и для того чтобы не раздувать зоопарк технологий - решили остановится на этой технологии.
Писал об этом в другой своей статье, линк на неё в самом начале)