我目前在JBoss AS7中遇到了一个间歇性的例外,不幸的是,我还不能重现。
我们目前正在运行两个应用程序,它们基本上被设置为JMS消息的生产者/使用者。我们使用默认的HornetQ配置和一个由5个MDB组成的池。
这两个应用程序都开始正常运行,按预期发送和接收消息。但是过了一段时间,所有MDB都会被锁定(每个MDB都会收到一条消息,但没有完成处理),然后JBoss会挂起一段时间,每十分钟显示一次以下消息:
[org.jboss.ejb3.invocation] (Thread-21081 (HornetQ-client-global-threads-1636833629)) JBAS014134: EJB Invocation failed on component MyMessageListener for method public abstract void javax.jms.MessageListener.onMessage(javax.jms.Message): javax.ejb.EJBException: JBAS014516: Failed to acquire a permit within 10 MINUTES在jarvana中的JBoss代码中,如果无法获得信号量,则似乎设置了此错误:
/**
* Get an instance without identity.
* Can be used by finders,create-methods, and activation
*
* @return Context /w instance
*/
public T get() {
try {
boolean acquired = semaphore.tryAcquire(timeout, timeUnit);
if (!acquired)
throw new EJBException("Failed to acquire a permit within " + timeout + " " + timeUnit);
} catch (InterruptedException e) {
throw new EJBException("Acquire semaphore was interrupted");
}
...问题是,为什么MDB会被锁定?它们不应该超时并继续处理吗?我已经在standalone.xml文件中将超时设置为5分钟,但它们从来没有,从来没有超时过。
<session-bean>
<stateless>
<bean-instance-pool-ref pool-name="slsb-strict-max-pool"/>
</stateless>
<stateful default-access-timeout="5000" cache-ref="simple"/>
<singleton default-access-timeout="5000"/>
</session-bean>有人知道会发生什么吗?
我也非常乐意接受任何关于如何模拟这个问题或设置MDB超时的其他方法的建议。
任何帮助都将不胜感激。
耽误您时间,实在对不起。
编辑:
因此,我终于能够简单地将MessageListener发送到睡眠时间比实例获取超时更长的时间来重现问题。以下是测试代码:
<!-- standalone.xml -->
<strict-max-pool name="mdb-strict-max-pool" max-pool-size="5" instance-acquisition-timeout="30" instance-acquisition-timeout-unit="SECONDS"/>MDB:
@MessageDriven(name = "TestMDB", activationConfig = {
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/myQueue"),
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge")//,
})
public class TestMDB implements MessageListener {
private final static Logger LOGGER = Logger.getLogger(TestMDB.class
.toString());
@Resource
private MessageDrivenContext ctx;
private final static int sleepingTime = MyProperties.SLEEP_MILLISECS;
/**
* @see MessageListener#onMessage(Message)
*/
public void onMessage(Message rcvMessage) {
ObjectMessage msg = null;
Future<String> future = null;
MyResource res = null;
try {
if (rcvMessage instanceof ObjectMessage) {
msg = (ObjectMessage) rcvMessage;
res = (MyResource)msg.getObject();
LOGGER.info("Received resource: " + res);
Thread.sleep(sleepingTime);
LOGGER.info("Released resource: " + res);
} else {
LOGGER.warning("Message of wrong type: "
+ rcvMessage.getClass().getName());
}
} catch (JMSException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}发布于 2012-10-22 13:55:20
似乎这种行为是意料之中的,而且这个问题可能与应用程序有关。
以下是对这个问题的总结:
理想的解决方案将是发现为什么MDB会被锁定,但在此之前,由于应用程序已经在生产中,我们需要一个撤退计划。
我相信一种解决方案是在我们到达大黄蜂的等待超时(或者在事务超时- @ActivationConfigProperty(propertyName = "transactionTimeout",propertyValue = "30"))之后中断MDB线程,但是在JBoss AS7中似乎没有一个简单的配置(尚未)。
可悲的方式是计时MDB线程的执行,并在onMessage方法中强制中断。这可以很容易地通过ExecutorService (http://stackoverflow.com/questions/6460664/how-can-i-interrupt-method-execution-by-time)实现。
对于遇到同样问题的人,我在网上发现了一些类似的讨论:
http://bryanpendleton.blogspot.com.br/2009/05/timertask-exception-handling.html https://community.jboss.org/thread/162822
希望这能有所帮助。
希望我能发现应用程序的任何问题。
发布于 2016-10-12 02:24:20
我也遇到了这个问题,最后通过下面的命令检查JBoss的线程,我们找到了根本原因。
jstack $pid我们发现了一个线程死锁。在我们修复死锁之后,JBoss不再停止。
https://stackoverflow.com/questions/12977154
复制相似问题