我偶尔会在几个不同的消息驱动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
2条答案
按热度按时间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
注解:该注解的参数被描述为here。
这就是问题所在。如果消息预取超过该池的maxSize(对于高吞吐量消息传递应用程序,通常会这样),则您将必然有等待MDB示例的消息。**如果从消息传递到调用onMessage的时间超过任何消息的池超时,则会抛出EJBException。**对于消息分发的前几次迭代,这可能不是问题,但如果您有很大的预取和很长的平均onMessage时间,则队列末尾的消息将开始失败。
一些快速的代数表明,粗略地说,当
这假设消息是即时分发的,每个onMessage花费相同的时间,但应该给予一个粗略的估计,判断是否越界。
这个问题的解决方法比较主观。简单地增加超时是一个幼稚的选择,因为它将掩盖消息位于应用服务器而不是队列上的事实。假设onMessage时间在某种程度上是固定的,如果资源允许,减少预取可能是一个很好的选择,因为增加池大小也是如此。在调优这个过程中,除了大幅减少预取和增加maxSize以使消息在队列中停留更长时间,同时在onMessage时间高于正常值时保持警报指示器之外,我还减少了超时时间。
insrf1ej2#
贾普汉姆说的没错。请检查是否
“strictMaximumSize”设置为true
这可能导致https://issues.jboss.org/browse/JBAS-1599