Я выполнил последовательную обработку сообщений в кластере в довольно крупном масштабе - 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 для разумной синхронизации часов.