Pull to refresh

Comments 41

Незаслуженно обделили Apache ActiveMQ Artemis, он во многом перспективнее RabbitMQ при функциональной совместимости решения.
спасибо, обязательно посмотрим!
это серия из 5-и статей которая сравнивает именно кролика и кафку, но мы посмотрим как можно вписать
С удовольствием почитаю. Спасибо за обзор!
Если у Артемиды AMQP 1.0 «под капотом», то о какой «функционально совместимости» (с «кроликом», как я понимаю) может идти речь?!

Что касается самой статьи, то практически всё, что в ней сказано про RabbitMQ (за исключением, возможно, «масштабируемости»), собственно, к самому «кролику» имеет весьма опосредованное отношение. Оно всё про AMQP «нулевой» серии.

А поскольку, авторы, судя по всему, в AMQP разбираются «ниочинь» (это я про оригинал), то — лично у меня — возникает «смешенное чувство» от «рассуждений» про «использует push», про «конкурирующих получателей» и т.п.
В статье было сказано про интернет вещей и протоколы STOMP, MQTT. В этом контексте и прокомментировал. В плане версии AMQP все верно, но в java приложениях его используют через JMS клиентов и в этом случае решения функционально совместимы.
Я понял. Только нужно помнить, что если «под капотом» не AMQP «нулевой» серии, то у вас нет ни exchange'ей, ни к ним «привязанных» очередей и т.п. Поэтому вся «функциональная совместимость» — в таком случае — сводится к «мы умеем слать сообщения».

… но в java приложениях его используют через JMS клиентов и в этом случае решения функционально совместимы.

Вообще-то нет. Т.к. на «движок» AMQP 0.9, 0.10 «ложится» практически любой messaging — в том числе, и AMQP 1.0. А вот наоборот — уже нет. Т.е. про все «плюшки» маршрутизации «на брокере» уже можно будет забыть.

Либо у нас сильно разное понимание «функциональной совместимости».
Спасибо что просветили! Не являюсь знатоком протоколов AMQP 0.9, 0.10 vs AMQP 1.0. Благодаря вашим замечаниям, по результатам чтения документации сложилось впечатление что главное отличие в том что AMQP 1.0 концентрируется на описании протокола и не регламентирует архитектуру брокера, exchanges и bindings. Но при этом в AMQP 1.0 возможны взаимодействия точка-точка без брокера, что может лучше подходить для mesh network в некоторых сценариях обмена IoT устройств.

За свою практику приходилось работать с Tibco EMS, Amazon SQS, Kafka, Solace(только через JMS API), Universal Messaging(Nirvana) и когда нужен сложный роутинг по контенту сообщений, то он выносился на уровень приложения либо на Apache Camel route. Бриджами баловались только в Tibco, в остальных системах без них спокойно жили. Так что без маршрутизации на брокере как-то обходились. Часть систем были банковским ПО, часть проектов распределенные «числодробилки».

На практике от сервиса очередей сообщений требуется поддержка транзакций, гарантированная доставка с какой-либо из семантик и требуемая системой пропускная способность для персистентных сообщений, еще хорошо если есть «из коробки» поддержка dead letter queue. Сложные же вещи лучше переложить на полноценный message routing engine.

С точки зрения что не получится заменить RabbitMQ на Artemis, при использований всех фич RabbitMQ вы правы. Но если же рассматривать в контексте RabbitMQ vs Kafka или Artemis vs Kafka, то Artemis может лучше подойти для IoT приложений чем RabbitMQ. Так что видимо у нас действительно разное понимание функциональности, совместимости.
Спасибо за статью, много хорошей информации.

Одно дополнение.
Когда вы имеете дело с ИИОТ то важным требованием является возможно апгрейда микросервисов с 0 остановкой (Blue/Green/Canary).
Использование потоковых инструментов типа кафки или кинесиса позволяет деплоить с существенно более простой архитектурой, поскольку поток всегда можно пере-проиграть снова в случае откатов.

Для многих «edge» сервисов мы используем стримы именно по этому поводу.
Так при использовании RabbitMQ, audit log также можно реализовать на уровне микросервиса при помощи паттерна EventSourcing. И Вы также можете «перепроиграть» события.

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

Извините за возможный офтопик. Мне нужна очередь для выполнения определенных вычислений (каждая задача относится к конкретному пользователю). Но таким образом, чтобы задачи, относящиеся к одному пользователю, не передавались на обработку одновременно. Есть ли возможность сделать это на какой-то "стандартной" очереди? Или придется делать свое решение? Кафка, судя по описанию, умеет группировать события по признаку, но мне не нравится, что может получиться ситуация, когда один воркер ничего не делает, а второй перегружен задачами.

Это нормально ложится на AMQP «нулевой» серии. Основная идея в том, что вам надо разделить «потребителей», которые производят вычисления (не важно, какого пользователя), и «потребителей», которые осуществляют диспетчеризацию задач на вычисление (для конкретного пользователя). Конечно это все сильно проще «нарисовать», но…

Логика работы «вычислителя» примерно следующая:
1. Из очереди T получаем сообщение m, без ack;
2. На основе данных из сообщения проводим вычисления;
3. Результат вычислений r отсылаем c m.replyTo;
4. Делаем ack на T и переходим к 1.

Логика работы «диспетчера» примерно такая:
1. Из очереди U получаем сообщение t, без ack;
2. Формируем сообщение m = t, m.replyTo = UR;
3. Посылаем m в T;
4. Получаем из UR сообщение r;
5. Делаем ack на U и переходим к 1.

Очередь T – одна на все. Её «слушают» все «вычислители». Кол-во «вычислителей» делать больше чем кол-во пользователей смысла не имеет, т.е. к в T всегда будет не больше сообщений чем пользователей (от каждого, только одно сообщение).

Очереди U/UR — у каждого пользователя свои. «Диспетчер» может быть один на все U/UR (условно, «сложный»), или у каждой U/UR он будет свой (условно, «простой»). Важно, что у конкретной U/UR только один конкретный «диспетчер».

Входной поток задач можно «раскладывать» по U, например, ч/з topic.
Для обмена U->T->UR достаточно и direct.
кажется, вы слегка усложняете.

в случае с кафкой можно просто взять один топик (с фиксированным количеством партишенов) и в качестве ключа для партицирования использовать user_id.
каждый partition разгребать в один поток.
все задания этого юзера гарантированно будут там и обработаются последовательно.
думаю, что в 99% процентов случаев никаких проблем с перфомансом не будет.

либо как альтернатива — брать абсолютно любой брокер, в нем одну очередь, разбирать в любое количество потоков, а перед обработкой записи пробовать брать лок в каком-то стороннем месте (mysql SELECT GET_LOCK в базе где хранится юзер или в zookeper/consul). Конкретный юзер сейчас залочен? Сделали этому эвенту postpone и попробовали чуть позже (вопрос реализации postpone зависит уже от брокера)

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


Второй вариант с постпоном для меня не работает, так как задача должна уходить на обработку сразу, как только освобождается воркер. Непонятно, как э то организовать в механике postpone и не клинически большим пинанием задачи в очередь и из очереди.

Спасибо, звучит разумно. Этакий буферизующий воркер/диспетчер получается (если один "сложный").

А можно поподробнее про нулевую и ненулевую версию? Я думал, что есть вот просто AMPQ. Каждая последующая версия чуть лучше и с большим количеством фич чем предыдущая. А сейчас оказывается, что все совсем иначе…
«Поподробнее» — это на отдельный пост дел :-)

Если «на пальцах», то AMQP 1.0 — он не «лучше/хуже»… он просто *другой*. В том смысле, что это не *обновление* AMQP 0.10 (который, по понятным причинам, практически нигде не поддерживается) — это из серии «забудьте про топор — вот вам лопата».

Понятно, что понравилось это далеко не всем… и состав AMQP Working Group сильно — скажем так — изменился очень быстро.

И что теперь использовать (если мы говорим про новый проект)? Я так понял есть депрекейтед-стандарт который используется де-факто, и новый, который никому не понравился и который не поддерживается.

Бтв отдельный пост думаю был бы очень кстати. Можно от вас его ожидать? Лично я с удовольствием прочитал бы.
И что теперь использовать (если мы говорим про новый проект)?

Честно говоря — я не знаю. С одной стороны, «нулевая» серия — мертва. Т.е. она не развивается *централизовано". Основная причина, понятно, юридическая. И то, что кто-то таки пытается что-то «допиливать» — бьет по одной из самых ценных вещей «нулевой» серии — по интероперабельности. Плюс (точнее минус), нет абсолютно никаких гарантий в плане того, что его внезапно не перестанут вообще поддерживать с какого-то момента. Хотя, в таком состоянии он уже больше пяти лет :-) Альтернатив-то нет. Подвижки к «реанимации» были… но, тот же OpenAMQ «умер» очень быстро… причины, насколько я понимаю, те же. Т.е. проблема в «области права».

С другой стороны, 1.0 вообще не про интероперабельность «ни разу». И вы *сознательно* прибиваете себя к вендору, практически, намертво.

Я так понял есть депрекейтед-стандарт который используется де-факто, и новый, который никому не понравился и который не поддерживается.

Немножко не так… AMQP *был* стандартом, т.к. его рабочая группа состояла из «инженерных титанов». Которые разрабатывали именно *стандарт*… в инженерном смысле. Сейчас это далеко не так.

Ну и 1.0 не то, что «никому не понравился»… он не понравился тем самым «титанам». Но на их место пришла пара-тройка «вендоров». Которым возможность «привязать к себе» еще и этим очень даже понравилась.

Бтв отдельный пост думаю был бы очень кстати. Можно от вас его ожидать? Лично я с удовольствием прочитал бы.

Это сильно вряд ли… в ближайшее время — по крайней мере. И я — честно говоря — слабо представляю, что вы хотите узнать из этого поста. Писать про «чем лопата отличается от топора» желания у меня не много :-(
И я — честно говоря — слабо представляю, что вы хотите узнать из этого поста. Писать про «чем лопата отличается от топора» желания у меня не много :-(

Да про все. Что за титаны, что за инженерные группы, почему новый стандарт это не стандарт, что за юридические нюансы… Для меня всё это новая информация, которую я нигде не встречал. Причем крайне важная. Потому что я вообще теперь перестал понимать, что мне использовать если я хочу очередь. Раньше я был уверен, что есть два живых конкурента, которые развиваются и делают интересные штуки, а теперь оказывается все совсем иначе…
Что за титаны …

Из известных это, например, Cisco и Novell. Из менее известных — TWIST, например.

… почему новый стандарт это не стандарт…

По факту. «Нулевая» серия описывала, емнип, General Puprose Middleware *Standard*, а AMQP 1.0 всего лишь Advanced Message Queueing *Protocol* :-)

Если чуть серьезней, то спецификации «нулевой» серии описывала MOM целиком — т.е. от wire-layer, и до семантики обработки. И, собственно, *протокол* amqp — это, хоть и существенная, но лишь часть этих спецификаций.

Реализация этих спецификаций *гарантировала* полную интероперабельность узлов такой MOM. Что, в свою очередь, означало независимость от какого-либо конкретного вендора. Т.е. все как «у взрослых».

А спецификация AMQP 1.0 — формально — вообще не описывает МОМ. Она описывает некий транспортный уровень «в вакууме». Т.е. использовать это можно только «прикрутив» к какой-либо *уже существующей* МОМ — что, собственно, мы и наблюдаем.

Интероперабельность «узлов» *возможна* только на транспортном уровне — т.к. никакого другого в спецификации просто нет. Собственно, там и на транспортном уровне, много чего нет. Помнится, я — в свое время — словил много адреналина пытаясь выяснить *что именно* теперь связывает Connection. Это точно не инженеры писали.

Ну и понятно, что в таком виде оно нужно «не только лишь всем». И если лет пять назад в AMQP Working Group оставались Huawei и INETCO, то сейчас *инженерных* компаний там не осталось *совсем*. Что — лично для меня — весьма показательно.

… что за юридические нюансы…

Права на спецификации «нулевой» серии принадлежат, емнип, OASIS. И она как-то не горит желанием выпускать их в public domain :-) Т.е. вы не можете «просто так» взять спецификацию AMQP 0.10 и на её основе сделать свой AMQP 1.0 «with blackjack and hookers» (с)

Спасибо за статью!


  1. Предположим, что у нас одна очередь и 10 получателей в RabbitMQ. Мы захотели ускорить обработку сообщений в 10 раз — вжух — увеличиваем количество получателей до 100, и сообщения обрабатываются быстрее. Насколько просто это сделать в Kafka, где у каждой партиции строго один получатель?
  2. В RabbitMQ, когда у каждой очереди много получателей, выход из строя одного из получателей не является катастрофой. А что происходит, если единственный получатель у партиции в Kafka выходит из строя? Кто обрабатывает "зависшие" в партиции данные?
Насколько это может быть просто – зависит от начальных параметров очереди.

Единица параллелизма в Kafka – это partition, и если очередь создается со слишком маленьким количеством partitions, отмасштабироваться будет затруднительно: один получатель может обрабатывать несколько partitions, а вот одна partition читаться несколькими получателями – нет.
Единица параллелизма в Kafka – это partition, и если очередь создается со слишком маленьким количеством partitions, отмасштабироваться будет затруднительно

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

Сам вендор (Confluent) предлагает максимально внимательно отнестись к этому вопросу и выпустил хорошее руководство по подбору параметра: How to choose the number of topics/partitions in a Kafka cluster
Какбы вы там ни прищуривались, а жизнь не ограничивается одними стресс-тестами.
Да. Но и без них тоже тяжело.
Единица параллелизма в Kafka – это partition

Стоит также отметить, что (наверное) все драйверы Кафки получают сообщения блоками (т.е. по N сообщений за раз) и некоторые из них предоставляют возможность параллельной обработки сообщений. Впрочем, это легко может быть реализовано и самостоятельно.

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

По второму вопросу, вроде как, в кафке все еще несколько проще. Новый/перезапущенный получатель вполне может знать место, на котором «сдох» предыдущий.
Второй вопрос решается запуском нескольких консьюмеров с одинаковым group_id и эти консьюемеры будут как один логический консьюмер. Кафка будет сама балансить партиции между консьюмерами. Если два инстанса консьюмера с одинаковым group_id и две партиции, то каждый консьюмер будет обрабатывать свою партицию, если один консьюмер упадёт, то второй будет читать из двух партиций.

Кажется у Вас опечатка в "Рис. 8. Три партиции и две группы по три получателей", там по логике должно быть "Рис. 8. Три партиции и три группы по два получателя"

Главная боль рэббита — абсолютная неготовность к кластеризации. Причина — mnesa, которая готова устроить split brain по любому чиху. Например, если сделать ноде (erlang'овой) suspend, а потом resume (чтобы проэмулировать лаг), то мы получим split brain, который либо нерешаем, либо приводит к потери информации. И любые мысли «у нас нет таких лагов» натыкаются на вопрос: у вас нет, а у вашего компьютера? Interrupt storm, баг в acpi, thermal throttling, баги в ядре — и всё, процесс радостно считает, что он один живой, а все пиры сдохли. А пиры считают так же.

В standalone режиме он вполне хорош, если не считать постоянного wtf из-за изобилия эрланговых глупостей (двустрочный логгинг, переключение между beamp/beam.smp в зависимости от числа ядер и т.д.).
Они могут направить несколько типов событий из нескольких топиков в свою очередь.… Это просто невозможно с помощью системы обмена сообщениями на основе журнала, такой как Kafka, поскольку журналы являются общими ресурсами.

В кафке консумер может читать одновременно из нескольких топиков, не вижу принципиальной разницы.

Я правильно понимаю, что обе эти системы предназначены для одностороннего обмена информацией? То есть источник сообщений может передать информацию потребителю, а потребитель не может вернуть источнику результат.

Двусторонний обмен — это два односторонних.
в rabbitmq есть механизм rpc — можно в сообщении указать «положи мне ответ в такую-то очередь»
Спасибо за перевод!
Ничего не сказано про масштабируемость кластера. Это одна из проблем Кафки. Ее невозможно масштабировать под нагрузкой, тк дополнительная репликация на новые брокеры в кластере вызовет повышенное потребление ресурсов и станет еще хуже.
То есть кластер лучше держать несколько over provisioned.
А что с RabbitMQ с масштабированием под нагрузкой?

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


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

Может кто знает для RabbitMQ есть какая-нибудь система мониторинга типа Kibana? Чтобы json логи онлайн можно было удобно фильтровать и разворачивать для просмотра?

Sign up to leave a comment.