EJBException: не удалось получить семафор пула


Я иногда получаю следующее исключение EJB через несколько различных бобов, управляемых сообщениями:

javax.ejb.EJBException: Failed to acquire the pool semaphore, strictTimeout=10000

Это поведение близко соответствует тому, когда у конкретной базы данных возникают проблемы, и тем самым увеличивает количество времени, затраченного в функции onMessage MDB. Сообщения доставляются с помощью в частности, ActiveMQ брокер (версия 5.4.2). Предварительная выборка на МБР составляет 2000 (20 сеансов х 100 сообщений за сеанс).

Мой вопрос носит общий характер. Что именно это такое что здесь происходит? Я знаю, что сообщение, которое было доставлено на сервер, выполняющий MDB, будет тайм-аут через 10 секунд, если в пуле бобов нет экземпляра для его обработки, однако как это сообщение было доставлено на сервер в первую очередь? Мое предположение до этого момента состоит в том, что MDB запрашивает сообщения от брокера в количестве только тогда, когда у него больше нет никаких сообщений для обработки. Они просто слишком долго ждут в этом серверном "ведре"?

Есть ли кто-нибудь еще нарвешься на такое? Предложения по настройке времени ожидания предварительной выборки / семафора?

EDIT: забыл упомянуть, что я использую JBoss как 5.1.0

2 3

2 ответа:

После проведения некоторых исследований я нашел удовлетворительное объяснение этому исключению EJBException.

MessageDrivenBeans имеют пул экземпляров. Когда пакет сообщений JMS доставляется в MDB в количестве предварительной выборки, каждому назначается экземпляр из этого пула и доставляется в этот экземпляр с помощью функции onMessage.

Немного о том, как работает пул: в JBoss 5.1.0 объединенные бобы, такие как MDBs и SessionBeans, настраиваются по умолчанию через JBoss AOP, в частности, файл в каталоге развертывания под названием " ejb3-interceptors-aop.XML". Этот файл создает привязки перехватчиков и аннотации по умолчанию для любого класса, соответствующего его домену. В случае управляемого сообщением бобового домена, среди прочего, org.jboss.ejb3.annotation.Pool аннотация:

<annotation expr="class(*) AND !class(@org.jboss.ejb3.annotation.Pool)">
     @org.jboss.ejb3.annotation.Pool (value="StrictMaxPool", maxSize=15, timeout=10000)
</annotation>

Параметры этой аннотации описаныздесь .

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

Некоторая быстрая алгебра показывает, что это будет происходить, грубо говоря, когда

timeout < (prefetch x onMessageTime) / maxSize
Это предполагает, что сообщения распространяются мгновенно, и каждый onMessage занимает одинаковое время, но должен дать вам приблизительную оценку того, выходите ли вы за рамки. Решение этой проблемы более субъективно. Простое увеличение времени ожидания-наивный вариант, поскольку он будет маскировать тот факт, что сообщения находятся на сервере приложений, а не в очереди. Учитывая, что время onMessage несколько фиксировано, уменьшение предварительной выборки скорее всего, это хороший вариант, так как увеличивает размер пула, если позволяют ресурсы. При настройке этого я уменьшил таймаут в дополнение к существенному уменьшению предварительной выборки и увеличению maxSize, чтобы держать сообщения в очереди дольше, сохраняя при этом мой индикатор оповещения, когда время onMessage больше обычного.

То, что говорит jpredham, верно. Также проверьте, является ли

'strictMaximumSize' установлено в true

Что может привести к https://issues.jboss.org/browse/JBAS-1599