spring cloud bus原理總結


1、spring cloud bus

  spring cloud是按照spring的配置對一系列微服務框架的集成,spring cloud bus是其中一個微服務框架,用於實現微服務之間的通信。
  spring cloud bus整合 java的事件處理機制和消息中間件消息的發送和接受,主要由發送端、接收端和事件組成。針對不同的業務需求,可以設置不同的事件,發送端發送事件,接收端接受相應的事件,並進行相應的處理。

2、spring cloud bus實戰

  網上關於spring cloud bus的demo相當多,此處就不贅述了。

3、原理

  spring cloud bus整合了java的事件處理機制和消息中間件,所以下面就從這兩個方面來說明spring cloud bus的原理。

 

 

 

 

 

 

 

 

 

 

 

 

如圖所示,作如下解釋:

(1)完整流程:發送端(endpoint)構造事件event,將其publish到context上下文中(spring cloud bus有一個父上下文,bootstrap),然后將事件發送到channel中(json串message),接收端從channel中獲取到message,將message轉為事件event(轉換過程這一塊沒有深究),然后將event事件publish到context上下文中,最后接收端(Listener)收到event,調用服務進行處理。整個流程中,只有發送/接收端從context上下文中取事件和發送事件是需要我們在代碼中明確寫出來的,其它部分都由框架封裝完成。

(2)先大致描述了一下流程,關於封裝的部分流程,我們基本上可以在BusAutoConfiguration.class中找到,下面的代碼都是這個類中的代碼

  @EventListener(classes = RemoteApplicationEvent.class)
    public void acceptLocal(RemoteApplicationEvent event) {
        if (this.serviceMatcher.isFromSelf(event)
                && !(event instanceof AckRemoteApplicationEvent)) {
            this.cloudBusOutboundChannel.send(MessageBuilder.withPayload(event).build());
        }
    }

這是封裝了java事件處理機制,當收到RemoteApplicationEvent時,如果這個event是從這個服務發出的,而且不是ack事件,那么就會把這個事件發送到channel中。

  @StreamListener(SpringCloudBusClient.INPUT)
    public void acceptRemote(RemoteApplicationEvent event) {
        if (event instanceof AckRemoteApplicationEvent) {
            if (this.bus.getTrace().isEnabled() && !this.serviceMatcher.isFromSelf(event)
                    && this.applicationEventPublisher != null) {
                this.applicationEventPublisher.publishEvent(event);
            }
            // If it's an ACK we are finished processing at this point
            return;
        }
        if (this.serviceMatcher.isForSelf(event)
                && this.applicationEventPublisher != null) {
            if (!this.serviceMatcher.isFromSelf(event)) {
                this.applicationEventPublisher.publishEvent(event);
            }
            if (this.bus.getAck().isEnabled()) {
                AckRemoteApplicationEvent ack = new AckRemoteApplicationEvent(this,
                        this.serviceMatcher.getServiceId(),
                        this.bus.getAck().getDestinationService(),
                        event.getDestinationService(), event.getId(), event.getClass());
                this.cloudBusOutboundChannel
                        .send(MessageBuilder.withPayload(ack).build());
                this.applicationEventPublisher.publishEvent(ack);
            }
        }
        if (this.bus.getTrace().isEnabled() && this.applicationEventPublisher != null) {
            // We are set to register sent events so publish it for local consumption,
            // irrespective of the origin
            this.applicationEventPublisher.publishEvent(new SentApplicationEvent(this,
                    event.getOriginService(), event.getDestinationService(),
                    event.getId(), event.getClass()));
        }
    }

@StreamListener這個標簽有興趣的可以去了解一下。這個方法就是從channel中取出事件進行處理的過程(message轉事件部分需要自行了解,我沒有深入研究),根據事件的類型、發送方和接收方來處理這個事件:如果是ack事件,發送到context上下文中;如果自己是接收端且不是發送端,就會將事件發送到context上下文。

(3)消息中間件可以采用rabbitmq、kafka之類的

(4)說兩個比較有意思的問題

  1)自定義事件時,我們需要添加無參構造方法:目的在於,在message轉事件時,會調用這個無參構造方法,具體情況可以去參考源碼看看

  2)自定義事件時,事件的參數需要用final修飾,這個一直沒有找到合理的解釋,有興趣可以去研究研究

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM