Обеспечение последовательной обработки сообщений JMS в кластере OC4J - PullRequest
4 голосов
/ 11 сентября 2009

У нас есть приложение, которое обрабатывает сообщение JMS с использованием бина, управляемого сообщениями. Это приложение развернуто на сервере приложений OC4J. (10.1.3)

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

Проблема связана с обработкой сообщений JMS в этом кластере. Мы должны убедиться, что во всем кластере OC4J одновременно обрабатывается только одно сообщение. Это необходимо, поскольку сообщения должны обрабатываться в хронологическом порядке.

Вам известен параметр конфигурации, который будет управлять обработкой сообщений в кластере OC4J?

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

Ответы [ 3 ]

5 голосов
/ 11 сентября 2009

Я выполнил последовательную обработку сообщений в кластере в довольно крупном масштабе - 1,5 миллиона + сообщение / день, используя комбинацию шаблона Конкурирующие потребители и шаблона аренды.

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

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

Это сработало для нас, и процесс жил в производстве около 4 лет, прежде чем был заменен из-за слияния компании.

Edit:

Я объясню это решение более подробно здесь: http://coders -log.blogspot.com / 2008/12 / Favorites-projects-series-installment-2.html

Edit:

Хорошо, понял. Вы уже выполняете обработку на нужном уровне, но поскольку вы развертываетесь в кластере, вам необходимо убедиться, что только один экземпляр вашего MDB активно извлекает сообщения из очереди. Кроме того, вам нужно самое простое работоспособное решение.

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

Итак, позвольте мне предложить это. В тот момент, когда ваш MDB регистрируется для получения сообщений из очереди, он должен проверить распределенную блокировку и посмотреть, сможет ли она ее получить. Первый MDB, который захватит блокировку, выигрывает, и только он регистрируется для получения сообщений. Итак, теперь у вас есть сериализация. Какую форму должен принять этот замок? Есть много возможностей. Ну как на счет этого. Если у вас есть доступ к базе данных, ее транзакционная блокировка уже обеспечивает то, что вам нужно. Создайте таблицу с одной строкой. В строке указан идентификатор сервера, который в данный момент удерживает блокировку, и время истечения. Это аренда сервера. У каждого сервера должен быть способ генерировать свой уникальный идентификатор, например, имя сервера и идентификатор потока.

Если сервер может получить доступ к обновлению для строки, и срок аренды истек, он должен получить его. Иначе это сдается. Если он захватывает аренду, ему нужно обновить строку со временем в ближайшем будущем, например, около пяти минут, и зафиксировать обновление. Активный сервер должен обновить аренду до истечения срока его действия. Я рекомендую обновлять его, когда остается половина времени, поэтому каждые 2-1 / 2 минуты, если срок аренды истекает через пять. С этим у вас теперь есть отказоустойчивость. Если активный MDB умирает, другой MDB (и только один) вступит во владение.

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

Итак, активный MDB и неактивные MDB должны периодически что-то делать. Вы можете сделать так, чтобы они создали отдельный поток для этого. Многие поставщики подсистемы приложений не будут рады, если вы сделаете это, но добавление одного потока не представляет особой проблемы, тем более что он проводит большую часть времени в спящем режиме. Другой вариант - включить механизм таймера, который предоставляют многие движки, и периодически вызывать ваш MDB для проверки аренды.

Да, и между прочим - убедитесь, что администраторы сервера используют NTP для разумной синхронизации часов.

0 голосов
/ 11 сентября 2009

Я согласен со Стивендиком: может быть, вы не в курсе дизайна. Что касается идентификатора последовательности или аналогичных подходов, я предлагаю вам ознакомиться с архитектурами обмена сообщениями с помощью корпоративных шаблонов интеграции: проектирование, создание и развертывание решений для обмена сообщениями (автор Gregor Hohpe y Bobby Woolf). Это отличная книга, множество полезных шаблонов ... Я уверен, что там хорошо описаны силы и проблема, с которой вы столкнулись.

0 голосов
/ 11 сентября 2009

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

Используете ли вы реализацию JMS по умолчанию с OC4J или другую?

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

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

...