Как "скопировать" сообщение JMS в 2 места назначения?

У меня есть требование, чтобы одно JMS-сообщение, отправленное клиентом, было доставлено надежно (ровно один раз) в две системы. Эти 2 системы не поддерживают HA, поэтому я предложил следующее:

  1. создать единую очередь, куда клиент отправляет сообщения

  2. установить две "промежуточные" очереди

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

client-> JMSDQ-> DuplicatorMDB-> Q1-> MDB-> System1
                           \ -> Q2-> MDB-> System2

Есть ли такая функциональность? Как правильно сбалансировать систему, чтобы она оставалась стабильной, если одна или обе бэкэнд-системы не работают?

Сервер приложений - WebLogic 10.

Я не могу использовать темы для этого, потому что в кластере темы будут вызывать слишком много дублирования сообщений. Если у нас есть 2 экземпляра, то с темами это будет выглядеть так:

 
client-> Тема ->MDB1@server1->System1
           | \->MDB2@server1->System2 
           \---->MDB1@server2->System1 
            \--->MDB2@server2->System2 

Таким образом, каждое сообщение будет доставлено дважды в System1 и дважды в System2, и если в кластере будет 8 серверов, каждое сообщение будет доставлено 8 раз. Это то, чего я действительно хотел бы избежать...

Наконец-то у меня появилось время для тестирования, и вот что я заметил: 2 узла в кластере. 2 JMS-сервера: jms1 на узле1, jms2 на узле2. Распределенная тема дт. MDB с надежной подпиской и jms-client-id=durableSubscriber. Запустил систему: 0 сообщений, mdb@node1 работает, mdb@node2 пытается периодически подключаться, но не может, потому что "Идентификатор клиента, durableSubscriber, используется". Как и ожидалось.

Отправлено 100 сообщений: jms1@dt messages current = 0, общее количество сообщений = 100, текущее число потребителей = 1 Я вижу, что node1 обработал 100 сообщений.
jms2 @ dt сообщений current = 100, сообщений Total = 100, потребителей ток = 1, т.е. в теме ожидают "дубликаты" сообщений.

Отправлено еще 100 сообщений, 100 обработано на узле 1, 200 ожидающих на узле 2.

Перезагруженный узел 1, mdb@node2 переподключился к dt и начал обрабатывать "ожидающие" сообщения. 200 сообщений было обработано на узле 2.

После того, как узел 1 запущен, mdb@node1 не может подключиться к dt, в то время как mdb @ node2 подключен.

jms1 @ dt сообщений current = 0, общее количество сообщений = 0, ток потребителей = 0
jms2 @ dt сообщений текущий = 0, сообщений всего = 200, потребителей тока = 1

Отправив еще 100 сообщений, я вижу, что все 100 сообщений обрабатываются на узле 2 и отбрасываются на узле 1.

jms1 @ dt сообщений current = 0, всего сообщений = 100, ток потребителей = 0
jms2 @ dt сообщений current = 0, всего сообщений = 300, ток потребителей = 1

Теперь я перезагружаю node2, mdb@node1 переподключается к dt. После перезагрузки mdb @ node2 повторно подключается к dt, а mdb @ node1 отключается от dt.

jms1 @ dt сообщений текущий = 0, сообщений всего = 100, текущих потребителей = 1
jms2 @ dt сообщений current = 0, общее количество сообщений = 0, ток потребителей = 1

Я отправляю 100 сообщений, все они обрабатываются на узле 2 и хранятся в теме на узле 1:

jms1 @ dt сообщений текущий = 100, сообщений всего = 200, потребителей тока = 1
jms2 @ dt сообщений current = 0, общее количество сообщений = 0, ток потребителей = 1

Затем я закрываю node2 и вижу 100 "ожидающих сообщений", обрабатываемых на node1 после повторного подключения mdb @ node1 к теме.

Итак, результат: я отправил 400 сообщений, 700 были обработаны MDB, из которых 300 были дубликатами.

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

Это может быть ошибка или особенность реализации weblogic JMS.

3 ответа

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

Детали конфигурации.

Обновление: если вы сталкиваетесь с проблемами в кластерной среде, я бы удостоверился, что все настроено правильно (вот руководство по кластеризации тем JMS). Это определенно звучит странно, что Weblogic потерпел бы такой ужас при кластеризации. Если это не сработает, вы можете заглянуть в Стороннюю очередь сообщений, такую ​​как RabbitMQ, которая поддерживает JMS и точно не будет иметь этой проблемы.

Это тот тип поведения, который должна реализовывать реализация ESB. С точки зрения затрат на обработку не было бы большой разницы, но может быть полезно разделить проблемы между "слесарным делом" и кодом приложения.

Как это происходит, реализация WebSphere JMS имеет поддержку для установки посредников, отвечающих таким требованиям. Я не знаю, есть ли что-то похожее в WebLogic, или их вариант для вас - ESB, но я бы порекомендовал изучить эти возможности. В настоящее время у вас есть простое требование, и ваш код, безусловно, достаточен, однако довольно легко представить, как несколько незначительных дополнительных требований (мы могли бы просто преобразовать это поле из долларов в фунты, прежде чем мы передадим в это место назначения, могли бы мы не отправлять сообщения с это содержание к этому месту назначения...) и вот! Вы пишете свой собственный ESB.

[...] Таким образом, каждое сообщение будет доставлено дважды в System1 и дважды в System2, и если в кластере будет 8 серверов, каждое сообщение будет доставлено 8 раз. Это то, чего я действительно хотел бы избежать...

Это верно для недлительных подписок, но не для долговременных. Для обеспечения надежности все MDB имеют один и тот же идентификатор соединения и идентификатор подписки (основанный на имени MDB по умолчанию), поэтому только один MDB сможет прикреплять и получать сообщения одновременно. Первый MDB попытается подключиться, остальные обнаружат конфликт и потерпят неудачу, но продолжат повторную попытку. Таким образом, использование долгосрочной подписки на темы должно помочь.

Другие вопросы по тегам