MDB onMessage()在重新传递消息时保持连接

时间:2017-06-07 15:26:24

标签: jms message-driven-bean openmq

如果无法处理消息,我需要重新发送消息,例如由于某些外部端点故障。所以我使用了以下MDB配置(值得一提的是我使用openMQ(Glassfish 4.1)):

@MessageDriven(mappedName = "MyQueue",  name = "MyQueue", activationConfig = {
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "endpointExceptionRedeliveryAttempts", propertyValue = "10"),
@ActivationConfigProperty(propertyName = "endpointExceptionRedeliveryInterval", propertyValue = "30000")})

这里的onMessage()方法:

  @Override
  @TransactionAttribute(TransactionAttributeType.REQUIRED)
  public void onMessage (Message message)
  {
    try
    {
      //some processing here
    }
    catch (JMSException jmsException)
    {
      logger.log (Level.SEVERE, "Exception processing notification message", jmsException);
    }
    catch (BackingStoreException e)
    {
      // because of throwing RuntimeException, the message is going to be redelivered according to mdb configuration params(interval and attempts count)
      throw new RuntimeException ();
    }
  }

为了重新发送消息,它也可以回滚一个事务,但openMQ缺少重新发送间隔的属性,所以它不适合我:

https://github.com/javaee/openmq/issues/220

https://github.com/javaee/openmq/issues/23

https://github.com/javaee/openmq/issues/134

总而言之,重新传递工作正常,除了片刻之外:如果要重新传递消息,mdb不会释放连接并将其保存为endpointExceptionRedeliveryInterval * endpointExceptionRedeliveryAttempts,在我的情况下为5分钟。因此,导致maxPoolSize的默认值为32,32" bad"消息足以阻止mdb。

是否有办法在邮件重新发送时释放连接?

1 个答案:

答案 0 :(得分:1)

这是符合JMS规范的预期行为,我认为在某种消息处理正在进行时,可能会有某种方式释放连接对象。阅读JMS规范here及以下内容是相关的,除了" 4.3.5关闭连接":

  

如果连接的一个或多个会话的消息侦听器是   处理一个消息,在点连接关闭被调用,所有   连接的设施和它的会话必须保持可用   对那些监听器,直到他们将控制权返回给JMS提供者。

     

当调用连接关闭时,它应该在消息之前返回   处理已有序关闭。这意味着所有消息   可能已经运行的听众已经返回了所有   等待收到的回复。

我不确定你为什么要使用这么高的数字进行重试机制,10次尝试太大了,最近我看到的是3次,我想你可以尝试调整你的重试机制数,或者可能有另一个专门用于重新递送的连接。