java EJBException: 无法获取池信号量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7015583/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
EJBException: Failed to acquire the pool semaphore
提问by jpredham
I'm occasionally getting the following EJB exception across several different message driven beans:
我偶尔会在几个不同的消息驱动 bean 中遇到以下 EJB 异常:
javax.ejb.EJBException: Failed to acquire the pool semaphore, strictTimeout=10000
This behavior closely corresponds to when a particular database is having issues and thereby increases the amount of time spent in the MDB's onMessage function. The messages are being delivered by an ActiveMQ broker (version 5.4.2). The prefetch on the MDBs is 2000 (20 Sessions x 100 Messages per session).
此行为与特定数据库何时出现问题密切对应,从而增加了花费在 MDB 的 onMessage 函数上的时间量。消息由 ActiveMQ 代理(版本 5.4.2)传送。MDB 上的预取为 2000(20 个会话 x 每个会话 100 个消息)。
My question is a general one. What exactly is happening here? I know that a message which has been delivered to the server running the MDB will time out after 10 seconds if there is no instance in the bean pool to handle it, however how has that message been delivered to the server in the first place? My assumption up to this point is that the MDB requests messages from the broker in the quantity of only when it no longer has any messages to process. Are they simply waiting in that server-side "bucket" for too long?
我的问题是笼统的。这里到底发生了什么?我知道,如果 bean 池中没有实例来处理它,则已传递到运行 MDB 的服务器的消息将在 10 秒后超时,但是该消息最初是如何传递到服务器的?到目前为止,我的假设是 MDB 仅在它不再有任何消息要处理时才从代理请求消息的数量。他们只是在那个服务器端“存储桶”中等待太久了吗?
Has anyone else run into this? Suggestions for tuning prefetch/semaphore timeout?
有没有其他人遇到过这个问题?调整预取/信号量超时的建议?
EDIT:Forgot to mention I'm using JBoss AS 5.1.0
编辑:忘了提及我正在使用 JBoss AS 5.1.0
回答by jpredham
After doing some research I've found a satisfactory explanation for this EJBException.
在做了一些研究之后,我找到了对此 EJBException 的令人满意的解释。
MessageDrivenBeans have an instance pool. When a batch of JMS messages is delivered to an MDB in the quantity of the prefetch each are assigned an instance from this pool and are delivered to that instance via the onMessage
function.
MessageDrivenBeans 有一个实例池。当一批 JMS 消息以预取的数量传递到 MDB 时,每个消息都会从该池中分配一个实例,并通过该onMessage
函数传递到该实例。
A little about how the pool works: In JBoss 5.1.0 the pooled beans such as MDBs and SessionBeans are configured by default through JBoss AOP, specifically a file in the deploy directory titled "ejb3-interceptors-aop.xml". This file creates interceptor bindings and default annotations for any class matching its domain. In the case of the Message Driven Bean domain, among other things a org.jboss.ejb3.annotation.Pool
annotation:
关于池如何工作的一点:在 JBoss 5.1.0 中,池化 bean(如 MDB 和 SessionBeans)默认通过 JBoss AOP 配置,特别是部署目录中名为“ejb3-interceptors-aop.xml”的文件。此文件为与其域匹配的任何类创建拦截器绑定和默认注释。在消息驱动 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>
The parameters of that annotation are described here.
此处描述了该注释的参数。
Herein lies the rub. If the message prefetch exceeds the maxSize of this pool (which it usually will for high throughput messaging applications) you will necessarily have messages that are waiting for an MDB instance. If the time from message delivery to calling onMessage exceeds the pool timeout for any message, an EJBException will be thrown.This may not be an issue for the first few iterations of the message distribution, but if you have a large prefetch and long average onMessage time, the message towards the end of the queue will begin to fail.
这就是问题所在。如果消息预取超过此池的 maxSize(对于高吞吐量消息传递应用程序通常会如此),您必然会有等待 MDB 实例的消息。如果从消息传递到调用 onMessage 的时间超过任何消息的池超时,将抛出 EJBException。对于消息分发的前几次迭代,这可能不是问题,但是如果您有大量预取和较长的平均 onMessage 时间,那么接近队列末尾的消息将开始失败。
Some quick algebra reveals that this will occurs, roughly speaking, when
一些快速代数表明,这将发生,粗略地说,当
timeout < (prefetch x onMessageTime) / maxSize
This assumes that messages are distributed instantaneously, and each onMessage takes the same time but should give you a rough estimate of whether you're way out of bounds.
这假设消息是即时分发的,并且每个 onMessage 花费相同的时间,但应该粗略估计您是否超出范围。
The solution to this problem is more subjective. Simply increasing the timeout is a naive option, because it will mask the fact that messages are sitting on your application server instead of your queue. Given that onMessage time is somewhat fixed, decreasing the prefetch is most likely a good option as is increasing the pool size, if resources allow. In tuning this I decreased timeoutin addition to decreasing prefetch substantially and increasing maxSize to keep messages on the queue for longer while maintaining my alert indicator for when onMessage times are higher than normal.
这个问题的解决方法比较主观。简单地增加超时是一个天真的选项,因为它会掩盖消息位于应用程序服务器而不是队列上的事实。鉴于 onMessage 时间在某种程度上是固定的,如果资源允许,减少预取很可能是一个不错的选择,就像增加池大小一样。在调整这一点时,除了大幅减少预取和增加 maxSize 以在队列中保留消息更长时间,同时保持我的警报指示器时,我还减少了超时时间,以便在 onMessage 时间高于正常情况下。
回答by Nilindra Fernando
What jpredham says is correct. Also plz check whether
jpredham 说的是正确的。也请检查是否
'strictMaximumSize' set to true
'strictMaximumSize' 设置为 true
which could lead to https://issues.jboss.org/browse/JBAS-1599