Эшу быдлокодит
298 subscribers
128 photos
12 videos
7 files
169 links
Дневник C# разработчика.

Личка: @EshuMarabo
Гитхаб: https://github.com/vladzvx

Стек: C#, PostgreSQL
Download Telegram
Есть такой продукт для обмена данными между микросервисами - RabbitMQ, я его неоднократно упоминал в канале выше. Это - брокер сообщений, вся суть его - передача информации из входной точки (обменника) к выходным (очереди), на которые подписываются сервисы. RabbitMQ поддерживает гарантированную доставку сообщения. Даже если рухнет мироздание вся инфраструктура, когда она оживет - брокер может поднять помещенные в него сообщения и продолжить передавать их подписчикам.

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

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

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

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

В остальном RabbitMQ прекрасен: удобно и быстро настраивается из с#, нагрузку держит.

#rabbitmq
👍3
Наткнулся на неочевидную проблему при приеме данных от RabbitMQ. Когда блямкает оповещение, оно представляется неким классом, имеющим поле типа ReadonlyMemorySpan<byte>, то есть по большому счету ссылка на область памяти с указанием размера.

Ну я и складировал эти классы для последующей обработки. Поддал нагрузки при тестировании - и из кролика полезла какая-то фигня, которую я туда не передавал.

Сделал копирование байтиков в массив сразу по получении - и проблема рассосалась.

#rabbitmq
😁1
Kafka vs RabbitMQ, часть 1. Описание эксперимента.

Проводил интересный эксперимент: сравнивал между собой брокеры сообщений: Apache Kafka и RabbitMQ под нагрузкой на сообщениях разного размера. В этом посте - описание условий эксперимента, результаты - далее по тегу #kafkavsrabbitmq

Оба брокера брал as-Service, то есть администрирование берет на себя хозяин облака. Под капотом RabbitMQ as Service - 1 инстанс, под капотом Kafka as Service - кластер из 9 .

На 12 серверах раскидал клиентские сервисы: по 70 генераторов данных (Producer) и по 200 потребителей (Consumer). Producer-ы в один поток последовательно генерируют сообщение (массив случайных байт заданного размера), отправляют его в брокер и ждут заданное время до отправки следующего сообщения. Consumer-ы в один поток читают. Режим чтения в Kafka - latest, то есть топики вычитываются не сначала. Сделал центральный сервис конфигурации, куда скидываются POST-запросом настройки сервисов: адреса брокеров и текущие настройки эксперимента - размеры сообщения и задержка после успешной отправки сообщения для регулировки нагрузки. Сервисы раз в некоторое время (от 15 до 30 секунд) ходят за свежей конфигурацией, и, если она поменялась - перенастраиваются.

Данные распределяются по 120 "обменным точкам" - Exchange в RabbitMQ, Topic в Kafka. Доставляются в среднем по 3 раза, везде стоит автоматическое подтверждение получения сообщения Consumer-ом.

Со всех сервисов собирается ряд метрик:


- Сообщений отправлено
- Сообщений получено
- Байт отправлено
- Байт получено
- Время отправки сообщения
- Число ошибок при отправке
- Число ошибок при получении

Бомбил сообщениями следующих размеров:


- 150 байт
- 5Кб
- 100Кб

Для сбора и визуализации метрик использовалась связка prometheus-push-gateway, Prometheus и Graphana. Сервисам известен адрес push-gateway, они сами туда сбрасывают метрики, prometheus их вычитывает.

В общем, получил лвлап и кучу экспириенса: зверинец из 550 сервисов я ещё не пас.

#rabbitmq
#kafka
👍1
Kafka vs RabbitMQ, часть 2. Результаты измерений.

Измерялась сферическая производительность брокера в ваккуме, под конкретную задачу (под NDA).

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

Размер сообщения: 150 байт
Kafka - 3000
RabbitMQ - 5000

Размер сообщения: 5 Кб
Kafka - 1100
RabbitMQ - 3600

Размер сообщения: 100 Кб
Kafka - 580
RabbitMq - 1000

#rabbitmq
#kafka
#kafkavsrabbitmq
Kafka vs RabbitMQ, часть 3. Некоторые впечатления и наблюдения по результатам эксперимента.

1. На практике для себя подтвердил вывод из прочитанного ранее.
2. В отличие от RabbitMQ, для Kafka, даже as-Service всеравно нужен опытный, знающий человек который умеет готовить именно её.
3. При экспоненциальном росте нагрузки Kafka урезает отдачу, а RabbitMQ - прием сообщений.
4. Kafka подключает нового клиента довольно долго. При подключении потребителя в момент, когда Kafka находится в режиме приёма "цунами" сообщений, на клиента по началу вываливается целая куча сообщений, а потом поток урезается до общего уровня.
5. Расстановка метрик вообще, и Prometheus в частности - огонь. Не так много дополнительных приседаний и из нескольких дашбордов понятно происходящее в 550 микросервисах. Prometheus с push-gateway на прием очень экономичны по оперативной памяти (съедали не больше 4-5 Гб), но требовательны к CPU: съедалось на постоянной основе 30+% от 8 ядер сервера.

#rabbitmq
#kafka
#kafkavsrabbitmq
👍1
Sphagnum. Часть 5. Техобзор. Репликация и отказоустойчивость в RabbitMQ
#sphagnum@eshu_coding

RabbitMQ поддерживает создание отказоустойчивых кластеров, но есть небольшой нюанс. Сообщения в обычных очередях не передаются между инстансами. То есть мы имеем отказоустойчивый кластер из 3 кроликов. С мастера на реплики продублированы все настройки, пользователи и т.д. Приходит в RabbitMQ цунами из сообщений, мастер ест их пока не захлебнется, а потом падает. И тут на его месте возникает радостная реплика с криками "я новый мастер, я!" и начинает работу. А данные, зависшие в старом мастере - ну когда-нибудь может быть будут отработаны и переданы. Правда, есть специальные очереди, Quorum Queues, сообщения между которыми таки распространяются по репликами и в случае нештатной ситуации таки будут отработаны. По дефолту такие очереди реплицируются по трем инстансам, но можно настроить и большее количество.

Занятно организовано голосование за право быть новым мастером. Когда мастер пропадает, реплики начинают кричать "я новый мастер!", кто успел крикнуть первым - тот и становится мастером. Если голоса равны, происходит повторное голосование. Я конечно утрирую, но логика примерно такая.

Итого, из того, что мне пока хотелось бы взять для своего проекта:
1. Идея разделения данных на реплицируемые и нет - огонь, но в качестве дефолта я бы взял реплицируемые.
2. Механизм голосования довольно забавный, но тут довольно сомнительно.

#sphagnum_theory@eshu_coding
#rabbitmq
🤡1
Совершенно ни к селу ни к городу вспомнил одну особенность RabbitMQ, просто запишу здесь чтобы не забыть.

Получая сообщения из RabbitMQ получатель должен подтвердить получение - ack (получено успешно) или nack (получено, но что-то пошло не так, можно указать, акутально ли еще сообщение). Но велик соблазн запустить какой-то процесс и сообщить кролику ack или nack уже по результатам его завершения.

Пока идёт отладка - всё прекрасно. А стоит поддать нагрузки так, чтобы в неопределенном статусе оказались 50+++ сообщений - начинаются чудеса. Кролика начинает колбасить, лучшего определения тут не подберешь, например сообщение отданное в кролик может дойти до адресата. А может - не дойти:)

Нормального пути решения проблемы я не нашёл, помогало удаление очереди. Ну и профилактика.

#rabbitmq
🤔2🤣2