簡體   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