【问题标题】:Message Driven Beans and Retry with exponential back off消息驱动 Bean 和指数回退重试
【发布时间】:2016-01-19 13:40:23
【问题描述】:

我有一个要求,如果我从消息驱动的 bean 调用的服务(Restful 服务)已关闭或不返回成功,我需要将消息回滚回队列,等待一段时间(以指数方式)然后再次读取消息从队列中尝试连接到服务。

我正在尝试什么:

在OnMessage 方法中,如果我收到来自调用Restful 服务的服务的异常,我将使用messageDrivenContext.setRollBackOnly() 回滚,我可以执行Thread.sleep(RETRY_WAIT_TIME) 之类的操作;

但我如何确保RETRY_WAIT_TIME 呈指数级增长?

可能我需要维护 bean 的状态,但是谁能建议我如何做到这一点?

【问题讨论】:

  • 我将首先调查您正在使用的任何消息队列的配置选项,看看它是否没有此类特定的重新传递设置。我会让你的生活变得轻松,而不是要求间隔是指数的。如果您偏离标准,您将进入自己的领域,而不是使用 MDB,而是使用手动构建的消息客户端。
  • 在 Java EE 环境中使用Thread.sleep() 是一种红鲱鱼,并且被规范严格禁止。

标签: jakarta-ee jms message-driven-bean


【解决方案1】:

有多种方法可以实现这一点,具体取决于您的设置。如果所有消息都将调用相同的服务,您可以在 MDB 上下文中定义一个全局限制参数,该参数定义让 MDB 休眠的时间。您可以使用基本的指数延迟,例如:

final int throttleTime = 60;  //Assume we delay 60 sec before retry
int throttle = 1;

private int getThrottle(){
  throttle = throttleTime * throttle;
  return throttle;
}

private void resetThrottle(){
  throttle = 1;
}

public void onMessage(Message message){
  try{
     service.invoke();
  } catch (InvocationException e) {
    try{
      Thread.sleep(getThrottle()*1000);
      onMessage(message);
    } catch (InterruptedException e) {
      logger.error(e.getMessage());
    }
  } finally {    
    resetThrottle();
  }
}       

注意,当 MDB 向容器抛出异常时,一些应用服务器已经逐渐增加了读取消息的重试时间。同样,一些排队系统允许配置让消息在队列中的某个时间出现。检查您的基础设施规范对该主题的描述。

【讨论】:

  • 感谢 Filip 的回复。是的,在我的情况下,所有消息都会调用相同的服务,并且我已经在 websphere 中配置了 10 个 MDB 实例。请告诉我在哪里设置全局限制参数以及如何实现指数级延迟...
猜你喜欢
  • 2016-03-31
  • 2014-03-18
  • 2011-07-15
  • 2012-02-27
  • 1970-01-01
  • 1970-01-01
  • 2017-06-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多