一、spring cloud busjava
spring cloud是按照spring的配置對一系列微服務框架的集成,spring cloud bus是其中一個微服務框架,用於實現微服務之間的通訊。
spring cloud bus整合 java的事件處理機制和消息中間件消息的發送和接受,主要由發送端、接收端和事件組成。針對不一樣的業務需求,能夠設置不一樣的事件,發送端發送事件,接收端接受相應的事件,並進行相應的處理。spring
二、spring cloud bus實戰json
網上關於spring cloud bus的demo至關多,此處就不贅述了。bootstrap
三、原理app
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上下文中取事件和發送事件是須要咱們在代碼中明確寫出來的,其它部分都由框架封裝完成。ui
(2)先大體描述了一下流程,關於封裝的部分流程,咱們基本上能夠在BusAutoConfiguration.class中找到,下面的代碼都是這個類中的代碼this
@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中。spa
@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修飾,這個一直沒有找到合理的解釋,有興趣能夠去研究研究