【问题标题】:Delay start of JMS Listener (MDB) in JBoss 6.0在 JBoss 6.0 中延迟启动 JMS 侦听器 (MDB)
【发布时间】:2012-05-23 21:27:27
【问题描述】:

我们在集群环境中有多个 JBoss-Server 实例。对于后台任务,有一个可用的全局队列,用于管理在其中注册的所有作业。对于这个队列,每个节点上都有一个简单的侦听器 (MDB),用于管理传入的消息。此侦听器对单例 bean 进行手动查找(无注入)并启动预定义的方法。 到目前为止一切正常,但是单例 bean 中的方法使用了在某些情况下不可用的其他一些(无单例服务)。 例如,如果一个节点将重新启动并且队列中有剩余的消息(尚未处理),则消息将被侦听器拾取并且所有其他 bean 都为空,因此该作业会产生 NPE。 是否可以在接收消息后在 JMS-Listener 中定义延迟时间,或者是否可以在其中定义“应用程序完全部署”挂钩?由于使用了非单例,DependsOn-Annotation 不起作用。

可以将 MDB 属性“DeliveryActive”设置为 false 并在完全部署后启动 bean。是否有一种简单的工作方式以编程方式执行此操作(不在 jmx-console 中)?我找到的任何手册都会将我重定向到手动 jndi 查找。我认为必须可以为每个注释注入 Bean 并调用 startDelivery()?申请中有没有好地方做这个?

另一个提示将我带到 application.xml 中 order 属性的初始化,因为问题可能与 JBoss 部署顺序有关(某些 EJB 将比侦听器更晚可用),但似乎有一个 bug in JBoss 6.0 和升级到 6.1。不是一种选择。也许有一个演练?

希望问题能得到充分的解释,否则请询问更多信息。

提前致谢, 丹尼

附加信息:

  • JBoss 6.0.0 最终版
  • HornetQ 2.2.5 Final(已经更新,因为 JBoss 的默认版本有问题)

聆听者:

@MessageDriven(activationConfig =
    {
            @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
            @ActivationConfigProperty(propertyName = "destination", propertyValue = "/queue/SchedulerQueue")
    })
public class SchedulerQueueListener implements MessageListener {
...
@Override
public void onMessage(Message message) {
   ...
   service = (IScheduledWorkerService) new InitialContext().lookup(jndiName);
   EJobResult eJobResult = service.executeJob(message);
   ...
}

一个样本工人:

@Singleton
@LocalBinding(jndiBinding = SampleJobWorkerService.JNDI_NAME)
public class SampleJobWorkerService implements IScheduledWorkerService {

...
    @EJB(name = "SampleEJB/local")
    private ISampleEJB sampleEjb;
...
    @Override
    public EJobResult executeJob(Message message) {
    int state = sampleEjb.doSomething(message.getLongProperty(A_PROPERTY));
    }

在这种情况下,sampleEjb - 成员有时会为空

【问题讨论】:

    标签: jboss jms ejb-3.1 hornetq jboss-mdb


    【解决方案1】:
    1. 作为一种解决方法,您可以创建一个带有超时的计时器,而不是直接从 MDB 调用 EJB。因此执行会有一些延迟。

      在Timer的超时方法中,可以调用singleton EJB,以防调用其他非singleton EJB。

    2. JBoss 特定:可以在发送前尝试在消息对象中设置属性。

      msg.setLongProperty("JMS_JBOSS_SCHEDULED_DELIVERY", (current + delay));

      其他选择是_JBM_SCHED_DELIVERY

    编辑:

    对于第一部分,您可以拥有 JTA 事务,它可能跨越 JMS 和 EJB。因此可以相应地处理故障转移和其他事情。

    您还可以增加消息对象的重新传递延迟。

    <address-setting match="jms.queue.someQueue">
            <redelivery-delay>5000</redelivery-delay>
    </address-setting>
    

    【讨论】:

    • 感谢您的回答 Nayan,您第一个回答的缺点是,属于 JMS 的好处将不再起作用或必须由自己实现(故障转移、重新排队、死信队列)。 “JMS_JBOSS_SCHEDULED_DELIVERY”属性将不起作用,因为发送位置对于超时的实现来说太早了。如果一条消息将按当前时间+延迟排队,并且节点在重新启动后发生故障,则消息将被侦听器消费,并且已经达到延迟时间。
    • 第二个选项与超时或与第一个选项无关,它是一种独立的方式。您也可以在失败的情况下延迟消息的重新发送,可以参考编辑部分。
    【解决方案2】:

    我现在也有同样的麻烦。

    我建议您在单例 bean 上使用 EJB 3 startup bean annotation @Startup 来调用消息侦听器上的 startDelivery 方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-30
      • 2012-01-03
      • 2011-01-16
      • 1970-01-01
      • 1970-01-01
      • 2015-05-27
      • 1970-01-01
      • 2023-03-17
      相关资源
      最近更新 更多