繁体   English   中英

发送方如何知道接收方在使用 Spring 引导的 JMS 中不可用?

[英]How do the Sender know that the Receiver isn't available in JMS using Spring Boot?

我有一个 Spring 启动应用程序,有 2 个微服务,这些微服务使用 JMS 和 ActiveMq 进行异步通信。 因此,Sender (ms1) 向 Receiver (ms2) 发送消息,Sender 会将消息放入队列,如果 Receiver 不可用,则消息将保留在队列中,直到 Receiver 可用。

我想问您,Sender 怎么知道 Receiver 是否可用? 我想知道,因为我想使用 Hystrix,如果接收器可用,发件人将显示如下消息:“交易成功完成”,但如果接收器不可用,发件人将显示其他消息:类似这个,“接收器服务当前不可用。消息被添加到队列中,当它可用时将被发送到接收器”。

此代码来自发件人服务:

    @HystrixCommand(fallbackMethod="sendMessageToProducerFail")
    private ResponseEntity sendMessageToProducer(String jsonStr) {
        jmsTemplate.convertAndSend(queue, jsonStr);
        return new ResponseEntity("Transaction successfully completed!", HttpStatus.CREATED);
    }

    private ResponseEntity sendMessageToProducerFail(String jsonStr) {
//        "The Receiver service isn't currently availble, the message is added to the queue..."
    }

没有简单的方法可以实现这一目标。 确定消费者是否起床会带来一些设计选择。 此外,您的问题没有现成的解决方案。 您可以使用心跳的概念来通知生产者有关消费者 state 的信息。

+----------+               +-------------+              +--------+
|          |<--Heartbeat---|             |---Message--->|        |
| Producer |               | AMQP Server |              |Consumer|
|          |----Message--->|             |<--Heartbeat--|        |  
+----------+               +-------------+              +--------+

你的设置看起来有点像这样,在这个生产者中( ms1 )将向 AMQP 服务器发送消息,并将使用来自消费者的 Heartbeat 事件,以确定消费者是否还活着。 当同一主题有多个生产者/消费者时,这将变得更加棘手。

一旦你有多个消费者,就会在同一个主题/队列上发送多个心跳。 您需要确定其中哪一个还活着,您还需要考虑消费者的下降/上升。

每个心跳都可以在生成时具有时间戳,以便您可以在更细粒度的级别上做出消费者存活的决定。 下一个问题是何时发送心跳? 当您使用 Spring 启动时,您将无法灵活地在消息侦听器之外发送心跳。 如果您正在使用MessageListener接口,请执行以下操作。

创建心跳发布器 class

@Component
class HeartBeatPublisher {
   public void registerMessageListener( String listenerName,
                                        String topicOrQueueName,
                                        Long intervals) {
   // store this detail in a map 
   // do lazy init of threads to send heartbeat 
   }
}

您的消息监听器 class 想要

@Component
class MyMessageListener implements MessageListener {
   @Autowired HeartBitPublisher heartBeatPublisher;
   @PostConstruct
   public void init(){
      // 30 seconds interval
      heartBeatPublisher.registerMessageListener("MyMessageListener", 
                                                 "MyMessageListener",
                                                 30*1000 );
   }
   void onMessage(Message message){
     // consume message here
   }
}

如果您不使用MessageListener仍然可以发送心跳,在这种情况下,我建议为每个组件添加一个侦听器。

@Component
class MyMessageListener{
   @Autowired HeartBeatPublisher heartBeatPublisher;
   @PostConstruct
   public void init(){
     // 30 seconds interval
     heartBeatPublisher.registerMessageListener("MyMessageListener", 
                                                "MyMessageListener",
                                                30*1000 );
   }

   @RabbitListener(queues="myQueue")
   public void onMessage(Object message) {
    // Consume message
   }
}  

在生产者方面,您需要添加一个侦听器以使用心跳检查哪些消费者处于活动状态。 一旦您知道哪些消费者处于活动状态,您就可以使用它来限制消息发布。

@Component
class HeartBeatListener {
  private List<String> queues;
   @PostConstruct 
   public void init(){
      // initialize queue and consumer status to inactive
      // at certain intervals checks for missing heartbeat 
      // if you find heartbeats are not being sent that means either 
      // that consumer has died or there's a delay in heart bit 
      // publish in that case mark that consumer/topic/queue inactive
   }
  
   @RabbitListener(queues="myQueue-HeartBeat")
   public void onMessage(Object message) {
     // update consumer status 
     // Record heart beat for a given consumer/topic
   }
}  

您可以使用ConsulZookeeperEtcd将一些工作转移到这些系统上,而不是执行所有这些操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM