Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/email/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JBoss AS7在MDB锁定后挂起_Java_Jboss_Message Driven Bean - Fatal编程技术网

Java JBoss AS7在MDB锁定后挂起

Java JBoss AS7在MDB锁定后挂起,java,jboss,message-driven-bean,Java,Jboss,Message Driven Bean,我目前在JBossAS7中遇到了一个间歇性异常,不幸的是,我还不能重现 我们目前正在运行两个应用程序,它们基本上被设置为JMS消息的生产者/消费者。我们使用默认的HornetQ配置和5个MDB池 两个应用程序都开始正常工作,按预期发送和接收消息。但过了一段时间,所有MDB都被锁定(它们各自都收到一条消息,但没有完成处理),JBoss在这之后会挂起一段时间,每隔十分钟显示一条消息: [org.jboss.ejb3.invocation] (Thread-21081 (HornetQ-client-

我目前在JBossAS7中遇到了一个间歇性异常,不幸的是,我还不能重现

我们目前正在运行两个应用程序,它们基本上被设置为JMS消息的生产者/消费者。我们使用默认的HornetQ配置和5个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”)/,
})
公共类TestMDB实现MessageListener{
私有最终静态记录器=Logger.getLogger(TestMDB.class
.toString());
@资源
私有消息驱动文本ctx;
private final static int sleepingTime=MyProperties.SLEEP\u毫秒;
/**
*@see MessageListener#onMessage(Message)
*/
消息上的公共无效(消息rcvMessage){
ObjectMessage msg=null;
Future=null;
MyResource res=null;
试一试{
if(rcvMessage instanceof ObjectMessage){
msg=(ObjectMessage)rcvMessage;
res=(MyResource)msg.getObject();
LOGGER.info(“收到的资源:+res”);
Thread.sleep(sleepingTime);
LOGGER.info(“发布的资源:+res”);
}否则{
记录器。警告(“类型错误的消息:”
+rcvMessage.getClass().getName());
}
}捕获(JME){
抛出新的运行时异常(e);
}捕捉(中断异常e){
抛出新的运行时异常(e);
}
}
}

这种行为似乎是意料之中的,问题可能与应用程序有关

以下是问题的摘要:

  • 我们有一个MDB实例
  • MDB从队列Q1接收消息
  • 我们向队列Q1发送消息
  • MDB试图处理它,但由于我们模拟了一个比实例获取超时时间更长的过程,HornetQ超时,我们得到了异常:“未能在X分钟内获取许可证”
  • 不幸的是,MDB将继续处理,并且仅在睡眠时间之后释放
  • 如果我们在MDB发布之前停止JBoss,应用程序将继续处理,因为消息是持久的,并且它知道我们没有完成MDB#onMessage方法
  • 但是由于我们还没有确定应用程序的问题,锁再次发生,我们得到一个异常循环 理想的解决方案是发现MDB被锁定的原因,但在此之前,由于应用程序已经投入生产,我们需要一个后备计划

    我相信一个解决方案是在我们到达Hornet的等待超时(或者在事务超时时-@ActivationConfigProperty(propertyName=“transactionTimeout”,propertyValue=“30”))后中断MDB线程,但在JBoss AS7中似乎还没有一个简单的配置(目前)

    令人悲哀的方法是计时MDB线程的执行,并在onMessage方法中强制中断。这可以通过Executor服务轻松实现(http://stackoverflow.com/questions/6460664/how-can-i-interrupt-method-execution-by-time)

    对于遇到同样问题的人,我在网上找到了一些类似的讨论:

    https://community.jboss.org/thread/162822

    希望这有帮助


    希望我能检测出应用程序有什么问题。

    我也遇到了这个问题,通过下面的命令检查JBoss的线程,我们最终找到了根本原因

    jstack $pid
    
    我们发现了一个线程死锁。我们修复了死锁后,JBoss再也没有停止。

    JBoss上的相关帖子(未解决),
    jstack $pid