Pull to refresh

Comments 57

Как-то маловато про NATS написано. Раз вы его выбрали, и, что более важно, он подошёл лучше, чем Кролик и Redis, хотелось бы более подробной информации о нём. Просто, к слову, я лично о нём до этого момента не слышал. И если он действительно настолько хорош, то возможно утащим себе в прод его.
У нас нет задачи продвигать NATS :)

Вот здесь можно какие-то впечатления прочитать:
https://news.ycombinator.com/item?id=11284489
Кстати, сколько там у Apache систем MQ? Четыре или уже больше?

ActiveMQ, QPID (Java и C++), Kafka, и как минимум два развития ActiveMQ — Apollo и Artemis.


Ну правда, два последних не совсем независимые проекты — скорее всего, выживет один из них, и заменит ActiveMQ.

>> По результатам наблюдения в течение 2 месяцев NATS не потерял ни одного сообщения.
Или вы не знаете о том что что-то потеряли)) Не могли бы вы рассказать о том что вы делаете в случае выхода из строя нескольких микросервисов(ситуация когда умер и получатели и отправители), спасет ли ваше логирование? Как реализован мерж после сплитбрейна? Какую пропускную способность получили?
Спасибо за комментарий. Мы логируем время отправки и время окончания обработки каждого сообщения получателем, и в мониторинге висит триггер, если время окончания обработки все еще не заполнено через 10 минут после отправки.

Некоторые сообщения мы можем безболезненно терять — например, push-уведомление на телефон с количеством новых задач. Обычно, через несколько минут будет новое такое сообщение, старое перестанет быть актуальным.

Ситуация, когда умер хотя бы один сервис — исключительная. Это бывает при maintenance, минут 5-10 может. В крайнем случае — ночь может полежать (но всегда есть резерв). Конечно, 100% гарантия невозможна и между at-least-once / at-most-once delivery мы явно сделали выбор в пользу последнего. Нам важно, что мы не ожидаем сюрпризов от выбранного механизма MQ.

Как я понимаю, каждый сервер кластера знает обо всех остальных и публикует темы (topic), на которые он подписан. Нет единого центра управления, никто не считается главным узлом, поэтому и split brain в классическом понимании (2 главных узла) невозможен. Полный peer-to-peer.

Пропускную способность в production не измеряли, нам достаточно, что слой MQ незаметен и latency между разными физическими машинами в районе 1ms. Когда будет время, соберем статистику, напишем отдельно.
Спасибо за ответ. Хотел бы еще уточнить:

>> Полный peer-to-peer.
То есть у вас нет вероятности того, что кластер разделится на N подсетей? Допустим где-то маршрутизатор умер. И либо умерло все либо все живое?

И вот интересный вопрос — сложность в настройке и поддержке, ну допустим по сравнению с кроликом сильно различается?

P.S.

>> Ситуация, когда умер хотя бы один сервис — исключительная
Вот прям везет вам, что никогда оборудование не умирает)
Вот прям везет вам, что никогда оборудование не умирает)
Ух, если бы только оборудование. У нас сервера используются на Azure и Soft Layer. И вот на Soft Layer довольно часто (чаще, чем раз в месяц) проблемы подобного рода, как правило «Emergency Maintenance». И в эти моменты может связь между серверами пропасть (сплит брейн), могут просто перезагрузить виртуалку. И т.п.
Хорошо, если у вас относительно стейтлес сервисы, когда важно, чтоб хоть один жил, но если это база данных, к примеру, то выход из строя большинства нод из кворума весьма печальные последствия имеет =\
>> То есть у вас нет вероятности того, что кластер разделится на N подсетей? Допустим где-то маршрутизатор умер. И либо умерло все либо все живое?

У нас полный набор всех сервисов в 2 независимых дата-центрах (и некоторые еще в третьем). Если упал маршрутизатор в одном, считаем, что упал весь дата-центр.

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

>> И вот интересный вопрос — сложность в настройке и поддержке, ну допустим по сравнению с кроликом сильно различается?

Не можем подсказать — опыта его администрирования и использования в production у нас нет.

>> Вот прям везет вам, что никогда оборудование не умирает)

Умирает, просто мы считаем это штатной ситуацией.
Окей. Тогда если у вас будут какие-то statefull-сервисы и упадет один из DC, то потом миграция данных из одного в другой может быть жуткой болью.

Отсутствие данных используемых в сравнении MQ не дает уверенности в честности тестов.
Так, NATS не гарантирует доставку, за доставку с гарантией отвечает NATS Streaming.
Есть ощущение, что тесты производительности используют NATS, вместо NATS Streaming.

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

Согласен. Мы сделали выбор в пользу производительности, пожертвовав условной гарантией доставки.
Ну тогда возможно уместнее было бы сравнивать производительность не NATS vs. RabbitMQ, Kafka, ZeroMQ или «очередь на СУБД», а NATS vs. «in-memory очередь за лоад-балансером»? Отмечу, что реализация in-memory очереди есть в стандартных библиотеках большинства ЯП.
Компоненты могут быть написаны на разных ЯП. В стандартных in-memory очередях обычно нет логики сетевого переподключения к другому адресату, когда текущий адресат умер.

Про производительность соглашусь с VlastV — вопрос к автору тестов. Мы же искали не самое производительное решение, а «good enough» для наших задач.
По-моему, имеет место некоторая путаница в показаниях.

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

Ага, ну наверное выбрали какую-то мега отказоустойчивую очередь, которая не теряет сообщения и с гарантией доставляет их до клиента.

Мы сделали выбор в пользу производительности, пожертвовав условной гарантией доставки.

Хм… ну ладно, наверное отказоустойчивость все-таки была не самым главным критерием. Производительность важнее. Ок, возьмем in-memory очередь: максимальная производительность, нулевой оверхед…

Мы же искали не самое производительное решение, а «good enough» для наших задач.

Вот тут я уже реально запутался… Производительность теперь не главное, все должно быть «good enough». Почему NATS «good enough»? Почему вы сравнивали его с решениями из других классов (например, Kafka), но не сравнивали с решениями из примерно того же класса, например с Redis?
По отказоустойчивости у нас было два требования:

1) автоматическое переключение маршрутизации на резервный сервис в случае умирания основного (или лучше — прозрачная поддержка пула consumers по каждому topic с маршрутизацией round-robin и автоматическим исключением из пула в случае умирания сервиса);

2) минимизация человеческого фактора при конфигурировании и расширении кластера.

C Redis сравнивали, об этом написано в посте, мы сочли, что он проигрывает NATS по второму критерию.

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

Вы мешаете в одну кучу отказоустойчивость кластера и гарантии доставки сообщения. Есть вполне отказоустойчивые схемы организации MQ, но не гарантирующие доставки. Отказоустойчивость тут означает лишь, что пока есть кворум в кластере, он будет принимать и отдавать сообщения. Но это не гарантирует, что каждое сообщение будет доставлено и, тем более, корректно обработано адресатом.

>> В Kafka данные делятся по разделам (partition) и чтобы соблюдать порядок доставки каждый получатель сообщений читает данные ровно из одного раздела

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

>> Это может приводить к блокировке очереди в случае, когда получатель по каким-либо причинам обрабатывает сообщения медленнее обычного.

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

а теперь реальные проблемы кафки если использовать как очередь запросов:

если у вас одну партицию разгребает за читателем пул потоков, то непонятно как комитить оффсет, то есть пришли сообщения mes1, mes2, mes3, раскинулись по 3 потокам, потоки выполнили их в порядке mes3, mes2, mes1.
Не дождавшись mes1 нельзя комитить mes3, иначе если мы сразу закомитим mes3, не дожидаясь mes1 и упадем, то mes1 повторно уже не вычитается.
Но и если ждем mes1 и произошло падение, то потом все этих три сообщения обработаются повторно, даже уже выполнившийся mes3.

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

Не знаю каким боком автор мерил производительность, но у меня в похожей ситуации и размере сообщений получалось из кафки 400k+ messages / second, а дальше упиралось в мой код.

Поэтому пока это смотрится: а смотрите что мы на Go сумели написать, Go сейчас модный, так что вы должны выбрать нас.
Спасибо за комментарий, очень ценно услышать опыт реального использования kafka.

>> каждая партиция независима, о какой блокировке всей очереди идет речь?

вы правы, речь именно о блокировке одной partition, спасибо.

>> Поэтому пока это смотрится: а смотрите что мы на Go сумели написать, Go сейчас модный, так что вы должны выбрать нас.

Хуже того, они вначале на ruby написали (еще более модный), работало медленно, переписали на Go. :)
если у вас одну партицию разгребает за читателем пул потоков, то непонятно как комитить оффсет

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

нельзя сделать читателей больше чем количество партиций, 1 партиция — 1 читатель.
архитектурное ограничение для ускорения работы, так как broker делает sendfile между файловым дескриптором и дескриптором на сокет. вернее создать можно, но читать реально будет только по количеству партиций, остальные будут стоять в очереди пока какая-либо партиция не освободится

>> Каждый из них будет читать 1 сообщение, обрабатывать, коммитить, потом читать следующее.

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

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

нельзя не привязывать читателя, подключение нового читателя обычно проходит по схеме:
1) подключился новый читатель в группу
2) бросилось всем читателям в группе сообщение что сейчас будет ребалансинг, притормозите работу
3) разослалась инфа о том кто какую партицию теперь будет обрабатывать

то есть вычитать не из той которая к тебе привязана нельзя, а процесс перепривязки достаточно долгий.
поэтому обычно читатель работает с 1+ партициями,

при вашей схеме держа:
M серверов по N потоков, P — количество партиций

каждый поток имеет своего читателя,

M*N > P — мы хоть и имеем несколько потоков которые курят, но зато каждый поток получает упорядоченные данные и нормально может комитить офсет.

M*N < P — тут в один поток влетает перемешенные данные из 2х партиций, при желании можно организовать доп логику и тоже работать, просто нужно будет проверять с какой партиции пришло сообщение и отправлять commit offset не общий, а именно в эту партицию

если же за 1 читателем находится пул потоков, то тут уже мешанина и async обработка неупорядоченная. проблему выше описал

p.s. чтобы было понятно: кафка отправляет подтверждение не на отдельное сообщение, а offset в пределах очереди, как бы говоря «все что было до этого оффсета я обработала»
Вы написали много правильных вещей, я прокомментирую то, что непосредственно относится к предложенному мной варианту.

если же за 1 читателем находится пул потоков, то тут уже мешанина и async обработка неупорядоченная. проблему выше описал

Поэтому так и не надо делать.

M*N > P — мы хоть и имеем несколько потоков которые курят, но зато каждый поток получает упорядоченные данные и нормально может комитить офсет.

Нет особого смысла держать консьюмеров больше, чем количество партишонов в топике.

M*N < P — тут в один поток влетает перемешенные данные из 2х партиций, при желании можно организовать доп логику и тоже работать, просто нужно будет проверять с какой партиции пришло сообщение и отправлять commit offset не общий, а именно в эту партицию

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

Если придерживаться ваших обозначений, то я всегда использую схему M*N <= P, и никаких проблем с коммитом оффсетов для каждого консьюмера нет.
для вашего случая как уже сразу писалось нужно держать достаточно большое количество партиций, чтобы при необходимости масштабирования всем хватило работы. а устанавливать 100+ партиций не всегда оправдано из-за накладных расходов.

вот только я не пойму схему работы на версиях до 0.9 включительно:

1) когда вы делаете poll вам вернулся map с различных партиций или пачка сообщений даже из одной,
2) если обрабатывать последовательно даже одним потоком и в самом конце делать commit, то все равно остается вопрос что делать если обработали несколько, а потом упали, оффсет незакомиченный, а данные обработаны

согласен что на 0.10 данной проблемы нету так как можно прочитать ровно 1 сообщение, до 0.9 включительно нужно городить костыли и по мере обработки сообщения вызывать не просто commitSync()/commitAsync() (которые закомитят максимальный офсет из того что вам вернули по poll), а вариант с указанием где и что комитим

void commitSync(Map<TopicPartition, OffsetAndMetadata> offsets);


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

тут именно вопрос чтобы исключить двойную обработку отдельных сообщений
комитить в конце обработки блока не проблема и на 0.9, но иногда это не вариант =\
1) когда вы делаете poll вам вернулся map с различных партиций или пачка сообщений

Причем вместе с каждым сообщением есть еще его оффсет в рамках данного партишона. Т.е. и номер партишона, и оффсет известны для каждого сообщения.

2) если обрабатывать последовательно даже одним потоком и в самом конце делать commit, то все равно остается вопрос что делать если обработали несколько, а потом упали, оффсет незакомиченный, а данные обработаны

Все правильно, делать коммит после обработки всей пачки небезопасно. Поэтому надо коммитить оффсет после обработки каждого отдельного сообщения. Еще раз повторюсь, вся необходимая для этого информация, а именно, номер партишона и оффсет этого конкретного сообщения — доступна.
я согласен что есть =)

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

>> нельзя сделать читателей больше чем количество партиций, 1 партиция — 1 читатель.

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

простейший пример:
1) имеем топик на 10 партиций
2) 20 читателей с одной consumer group

вопрос:
сколько читателей будет одновременно работать?
10 будут читать, другие 10 будут висеть в воздухе ожидая пока кто-то из тех 10 отвалится.

до тех пор пока вы продолжаете использовать «то я всегда использую схему M*N <= P» все действительно можно разрулить, вот только я и начал разговор с того что

>> в общем представление партиции как упорядоченный лог накладывает свои ограничения, а держать 100500 партиций в пределах топика тоже не хочется, так как это дополнительные накладные расходы.

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

то есть используя схему M*N <= P мы можем получить что все вычитали, сидят курят, а один читатель продолжает пыхтеть из-за неравномерности распределения сообщений по партициям. и никто из его группы ему помочь не может. (хотя признаю что на такое только раз или два нарывался)
Предполагаю, что когда вы искали очереди и наткнулись на NATS который написан на Go, должны были бы наткнуться и на NSQ, который тоже написан на Go. Смотрели ли вы в сторону NSQ и если да, то почему отказались от него?
NATS и NSQ выглядят похоже. Мы не глубоко изучали NSQ, но там вроде 2 процесса в каждом узле вместо одного (сложнее администрировать) + у NATS есть возможность добавить message persistence, если понадобится (надстройка NATS Streaming).

@Pyrus в NSQ 1 процесс nsqd, если нужен cluster, то два nsqd и nsqlookupd, второй выполняет роль service discovery.
В NSQ гарантия доставки из коробки.


@dos мы в одном из проектов выбрали NSQ, выбирали так же между NATS и NSQ. Выбор сделан пальцем в небо...


В NATS подкупает Request-Reply если он необходим, хоть его и можно реализовать в NSQ.


В NSQ так же можно организовать сообщение, канал и/или подписчика с выключенной гарантией доставки.

Спасибо. Нам нужен кластер, из общих соображений решили, что N процессов могут сбойнуть с меньшей вероятностью, чем 2N.

NATS — at most once delivery.
NSQ — at least once delivery.

В случае at least once нужно самому бороться с повторными доставками.

В NATS понравилась фича принудительное отключение «slow consumer» ради защиты кластера. Это и отсутствие гарантии доставки мотивирует писать надежных consumers.

NSQ имеет встроенный механизм повторной отправки сообщения. Так же можно самостоятельно переотправить сообщение в очередь.

«бороться с повторными доставками» — я имел в виду адресат должен самостоятельно отслеживать и (чаще всего) игнорировать, когда ему доставили сообщение повторно.

А вы попробовали? А то у вас же написано...


Кроме того, для управления кластером Kafka требуется отдельный сервис (zookeeper), что опять же усложняет обслуживание и нагружает devops.

При том что зукипер практически не требует администрирования.

Тоже использую NATS, т.к. потеря данных при доставке это событие с малой вероятностью, то восстановление доставки возложил на сторонний сервис который анализирует журнал работы, и изучает ключевые точки, если сообщение не прошло какую то из-точек, то происходит переотправка сообщения на этот этап.

Пара ссылок для сравнения брокеров: раз, два
За табличку спасибо, но вот в упор не вижу, где там
Видно, что запись на диск в 15 раз медленнее отправки по сети.
Сравниваем latency:

Send 1K bytes over 1 Gbps network 10,000 ns
Read 4K randomly from SSD* 150,000 ns

Тут, конечно, указана цифра для чтения с SSD, но запись вряд ли будет быстрее.
Спасибо за замечание. Согласен, сформулировано не вполне корректно.

Есть 3 главных показателя скорости внешнего носителя: throughput, latency и IOPS. Когда передаешь много маленьких сообщений, latency выходит на первый план по степени влияния на общую производительность системы.

Из таблички: latency передачи пакета данных по сети: 0.01мс, что позволяет (теоретический предел) передать 100 000 сообщений в секунду.

У SSD latency 0.15мс, и теоретический предел будет 1c / 0.15мс = 6 700 сообщений в секунду. У HDD latency выше и к-во сообщений в секунду будет еще меньше.

Конечно, на фактическую производительность влияет много факторов. Например, если сообщений в MQ мало, все они большого размера и передаются не на сервер в соседней стойке, а на другой континент — то throughput может оказаться важнее.

Вот тут есть сравнение latency для разных MQ:

http://bravenewgeek.com/benchmarking-message-queue-latency/

Из интересных наблюдений:

— у NATS и Redis лучшие значения показателя latency (стабильно меньше 1мс), но он растет при увеличении размера сообщения

— у RabbitMQ и Kafka показатель latency начинает быстро расти в районе 99,0-99,9 перцентилей даже при маленьких сообщениях

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


Совершенно неверно. Пока сообщение не будет сохранено на диск, отправитель не получит об этом информацию, соответственно не зафиксирует со своей стороны что сообщение ушло. Получатель может использовать manual acknowledge mode, и сообщать что менеджеру очередей, что сообщение получил после того как зафиксирует у себя. И, в крайнем случае, используются распределенные транзакции.

Гарантия есть, но надо уметь её готовить.
Опередили, хотел написать тоже самое. Могу только добавить что в большинстве случаев отправитель который работает с acknowledge — СУБД которая надёжно сохраняет состояние и вся система становится с гарантированной доставкой. Т.е. нужен надёжный источник, иначе ни при какой конфигурации система не может считаться надёжной.
А рассматривали ли вы вариант NanoMsg? Они вроде позиционируют себя как серьезное переосмысление ZeroMQ.
Даже использовали, нареканий нет. Субъективно, API немного проще 0MQ, производительность сравнимая с 0MQ. Но надо самим писать логику service discovery. Да и автор nanomsg перестал поддерживать проект. В github есть коммиты сообщества, конечно, но последние 3 мес (с января 2017) ни одного. Решили не рисковать.
«Ведь если упадет отправитель в момент передачи сообщения или упадет сам процесс очереди до записи на диск, то сообщение пропадет. Получается, очередь только создает иллюзию гарантии доставки, а сообщения по-прежнему могут теряться.»
Не совсем так.
В случае записи на диск после восстановления можно обнаружить, то некоторое сообщение пропало и откатить или повторить операцию, которая его породила. То есть запись на диск — часть транзакции, а передачу по сети транзакционной сделать сложнее.
Вы отмели RabbitMQ как продукт из-за измерений 2012 года? Сейчас ситуация кардинально поменялась, как минимум в мажорной версии продукта, а еще не правда то что RMQ сложен в конфигурировании. Очень важно как вы работаете с очередями, а не то как сконфигурирован HA Mirror Queueing.

Категорически не согласен со статьей. Нам тоже нужна была высокопроизводительная durable очередь (от 3 тыс сообщений в секунду) и вот мои выводы:


Про гарантию доставки и in-memory queues.


Этого недостаточно. Микросервисная архитектура для раскрытия всего своего потенциала требует сохранения работоспособности системы при отказе любой машины. Это позволяет хоститься на облаках с не очень надежными машинами, позволяет CD без даунтайма, позволяет A/B тестирование и т.д.


Теперь рассмотрим REST сервис, который должен гарантировать доставку. Классический протокол выглядит так:


  • клиент посылает запрос
  • сервер обрабатывает запрос, сохраняет и коммитит результат, и только потом возвращает 200 OK.
  • если сервер вернул не 200 или не вернул ответ, клиент перепосылает запрос. В этом случае у нас будут дубликаты (решается наличием уникального id запроса и базы этих id на стороне сервера), но запрос никогда не будет потерян

Если мы используем in-memory очереди, то возникает две проблемы:


  1. Если в любой момент времени сообщение хранится в памяти только одной машины, то при отказе этой машины мы теряем сообщение
  2. если мы используем кластер in-memory, то отказ одной машины проблемой не станет, НО усложняется деплоймент собственно кластера очереди сообщений (надо переводить ноду в readonly, дождаться окончания репликации, и только потом делать рестарт) И что делать, если очередь переполнится? Места на диске, как правило, значительно больше, чем в памяти.

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


Про RabbitMQ.


RabbitMQ тянет несколько тысяч запросов в секунду с одной ноды и работает хорошо, НО если объединить ноды в кластер, то мы наблюдали очень нестабильную работу под нагрузкой — кластер "разваливается" и не чинится автоматически. Также при падении одной из нод сама она в кластер не возвращается.


Про Kafka.


Стандартный кластер из трех нод на aws m3 тянет 20000 сообщений на запись или на чтение. Нормально переживает падение и возврат в кластер своих нод. Позволяет делать выбор между быстродействием и прочими свойствами очередей — гарантированным порядком сообщений, наличием повторов при отказе получателя и т.п.


В целом ТС как-то странно понимает гарантию доставки.

если сервер вернул не 200 или не вернул ответ, клиент перепосылает запрос. В этом случае у нас будут дубликаты (решается наличием уникального id запроса и базы этих id на стороне сервера)

В конфигурации, когда запрос обслуживает пул идентичных сервисов на разных машинах, для избегания дубликатов нужно синхронизировать все уникальные id запросов между ними. Это усложнение логики, еще одна сетевая задержка, дополнительная обработка ошибок (а если эта синхронизация сбойнула?), итд.

Наверное, это явно не следовало из текста, стоит сказать, что durability не являлось критичным свойством для выбора очереди. И в итоге мы выбрали решение, у которого этого свойства нет.
Раз уже нагрузка на Devops для вас существенный фактор, почему не рассматриваете SaaS очереди, например эту: https://www.iron.io/platform/ironmq/
Предполагаем, что latency будет высокой — миллисекунды или десятки миллисекунд.

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

Если есть реальный опыт с ней, было бы интересно почитать впечатления.

Вопрос: как вы отслеживаете появление новых каналов для запуска подписчиков?

У нас фиксированное число каналов и для каждого всегда есть несколько живых подписчиков. Мы всегда отправляем сообщения в конкретный канал.

хабр пишет, что материал снят с публикации

Sign up to leave a comment.

Articles

Change theme settings