jpr*_*ham 3 java jboss activemq-classic java-ee ejb-3.0
我偶尔会在几个不同的消息驱动bean中获得以下EJB异常:
javax.ejb.EJBException: Failed to acquire the pool semaphore, strictTimeout=10000
Run Code Online (Sandbox Code Playgroud)
此行为与特定数据库出现问题时密切对应,从而增加了在MDB的onMessage函数中花费的时间.这些消息由ActiveMQ代理(版本5.4.2)提供.MDB上的预取是2000(每个会话20个会话x 100个消息).
我的问题很普遍.到底发生了什么?我知道,如果bean池中没有实例来处理它,那么传递给运行MDB的服务器的消息将在10秒后超时,但是该消息首先如何传递给服务器?到目前为止,我的假设是MDB仅在不再有任何要处理的消息时才会请求来自代理的消息.他们只是在服务器端"桶"等待太久了吗?
有没有其他人遇到这个?调整预取/信号量超时的建议?
编辑:忘了提到我正在使用JBoss AS 5.1.0
jpr*_*ham 10
在做了一些研究后,我发现了这个EJBException的令人满意的解释.
MessageDrivenBeans有一个实例池.当一批JMS消息以预取的数量传递到MDB时,每个JMS消息都会从该池中分配一个实例,并通过该onMessage函数传递给该实例.
关于池如何工作的一点:在JBoss 5.1.0中,默认情况下通过JBoss AOP配置诸如MDB和SessionBeans之类的池,特别是部署目录中标题为"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>
Run Code Online (Sandbox Code Playgroud)
此处描述了该注释的参数.
这就是摩擦.如果消息预取超过此池的maxSize(通常用于高吞吐量消息传递应用程序),则必须具有等待MDB实例的消息.如果从消息传递到调用onMessage的时间超过任何消息的池超时,则将抛出EJBException.对于消息分发的前几次迭代,这可能不是问题,但如果您有大量预取和长平均onMessage时间,则队列末尾的消息将开始失败.
一些快速代数揭示了这种情况,大致说来就会发生
timeout < (prefetch x onMessageTime) / maxSize
Run Code Online (Sandbox Code Playgroud)
这假定消息是即时分发的,并且每个onMessage需要相同的时间,但应该粗略估计您是否超出界限.
这个问题的解决方案更主观.简单地增加超时是一个简单的选择,因为它将掩盖消息位于应用程序服务器而不是队列上的事实.鉴于onMessage时间有些固定,如果资源允许,减少预取很可能是一个很好的选择,因为增加池大小.在调整时,除了大幅减少预取之外,我还减少了超时,并增加了maxSize以使队列中的消息保持更长时间,同时在onMessage时间高于正常时保持警报指示.
| 归档时间: |
|
| 查看次数: |
9952 次 |
| 最近记录: |