jboss EJB异常:无法获取池信号量

gab6jxml  于 2023-10-20  发布在  其他
关注(0)|答案(2)|浏览(112)

我偶尔会在几个不同的消息驱动bean中遇到以下EJB异常:

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

此行为与特定数据库出现问题时密切相关,因此会增加MDB的onMessage函数所花费的时间。消息由ActiveMQ代理(版本5.4.2)交付。MDB上的预取为2000(20个会话x每个会话100条消息)。
我的问题是一般性的。这到底是怎么回事我知道,如果bean池中没有示例来处理消息,那么已经发送到运行MDB的服务器的消息将在10秒后超时,但是该消息首先是如何发送到服务器的呢?到目前为止,我的假设是MDB仅在不再有任何消息要处理时才从代理请求消息。他们只是在服务器端的“桶”中等待太久了吗?
还有其他人遇到过吗对预取/信号量超时的优化建议?

**编辑:**忘了说我正在使用JBoss AS 5.1.0

jljoyd4f

jljoyd4f1#

在做了一些研究之后,我找到了一个令人满意的解释。
MessageDrivenBean有一个示例池。当一批JMS消息以预取的数量被传递到MDB时,每个消息都会从这个池中分配一个示例,并通过onMessage函数传递到该示例。
关于游泳池的工作原理:在JBoss 5.1.0中,池化bean(如MDB和SessionBean)默认通过JBoss AOP进行配置,特别是部署目录中名为“ejb3-interceptors-aop.xml”的文件。这个文件为任何匹配其域的类创建拦截器绑定和默认注解。在Message Driven Bean域的情况下,除其他外,还有一个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>

该注解的参数被描述为here
这就是问题所在。如果消息预取超过该池的maxSize(对于高吞吐量消息传递应用程序,通常会这样),则您将必然有等待MDB示例的消息。**如果从消息传递到调用onMessage的时间超过任何消息的池超时,则会抛出EJBException。**对于消息分发的前几次迭代,这可能不是问题,但如果您有很大的预取和很长的平均onMessage时间,则队列末尾的消息将开始失败。
一些快速的代数表明,粗略地说,当

timeout < (prefetch x onMessageTime) / maxSize

这假设消息是即时分发的,每个onMessage花费相同的时间,但应该给予一个粗略的估计,判断是否越界。
这个问题的解决方法比较主观。简单地增加超时是一个幼稚的选择,因为它将掩盖消息位于应用服务器而不是队列上的事实。假设onMessage时间在某种程度上是固定的,如果资源允许,减少预取可能是一个很好的选择,因为增加池大小也是如此。在调优这个过程中,除了大幅减少预取和增加maxSize以使消息在队列中停留更长时间,同时在onMessage时间高于正常值时保持警报指示器之外,我还减少了超时时间。

insrf1ej

insrf1ej2#

贾普汉姆说的没错。请检查是否
“strictMaximumSize”设置为true
这可能导致https://issues.jboss.org/browse/JBAS-1599

相关问题