發布-訂閱模型
Bus的事件推送由三個角色構成:
- 事件對象:Bus中定義的一個事件類,通常是一個Pojo對象,包含了消費者需要的信息
- 事件發布:Bus作為生產者,將事件對象通過廣播的形式發布出去
- 事件監聽:由消費者主動監聽Bus的事件發布動作,當獲取到事件對象后會調用處理方法進行消費
自定義事件
自定義事件對象
Bus的所有事件對象都繼承自ApplicationEvent或者RemoteApplicationEvent,我們可以仿照bus-refresh功能定義的事件類RefreshRemoteApplicationEvent中的寫法,定義一個MyEvent類
public class MyEvent extends RemoteApplicationEvent {
public MyEvent() {
}
public MyEvent(Object body, String originService, String destinationService) {
super(body, originService, destinationService);
}
}
其中第一個參數可以自定義一個POJO類,大家可以根據自己的需求隨意添加屬性,但是要保證這個類實現了序列化/反序列化接口(implements Serializable)。
配置自定義對象
在創建了MyEvent之后,我們需要將它加載到Bus的上下文中,這里可以通過@Configuration和@RemoteApplicationEventScan注解將MyEvent加載進來
@Configuration
@RemoteApplicationEventScan(basePackageClasses = MyEvent.class)
public class BusExtConfiguration {
}
監聽事件
我們要在服務節點添加事件監聽器,用來監聽服務發布動作,這一步可以通過@EventListener方法級別的注解來實現(可以參考RefreshEventListener類),接收的參數就是第一步中創建的EventBody,Bus會幫我們將消息反序列化為Java類。也可以通過繼承ApplicationListener接口來實現,示例如下:
@Component
public class MyEventListener implements ApplicationListener<MyEvent> {
@Override
public void onApplicationEvent(MyEvent event) {
logger.info("Received MyCustomRemoteEvent - message: ");
}
}
發布事件
萬事俱備之后,我們只需要一個發布事件的地方了(在消息生產者處實現),我們可以創建一個簡單的Controller,然后對外提供一個POST方法,比如:
@PostMapping("/bus/publish/myevent")
public boolean publishMyEvent(@RequestBody EventBody body) {
MyEvent event = new MyEvent(body, applicationContext.getId(), "");
try {
// 可以注入ApplicationEventPublisher來發送event
eventPublisher.publishEvent(event);
// 也可以直接使用
// applicationContext.publishEvent(event)
return true;
} catch (Exception e) {
log.error("failed in publishing event", e);
}
return false;
}
我們有兩種方式發送event,一種是通過依賴注入ApplicationEventPublisher的實例來發送,現有的bus-refresh功能也是使用這種方式。另一種是直接通過ApplicationContext來發送,由於前面我們通過@RemoteApplicationEventScan注解已經將MyEvent注冊為Bus的一個事件,這樣ApplicationContext會把MyEvent當做一個Bus總線事件,而不是在Context范圍內發布一個Regular Event。
應用場景
通過上面的方式我們可以將自定義事件廣播到所有監聽該事件的節點,讓所有消費者觸發事件響應。消息廣播的使用場景非常多,我們隨便舉兩個實際應用中的例子:
- 清空緩存:通知所有服務監聽者清空某項業務的本地緩存信息,我們也可以在自定義的消息體中加業務屬性,事件監聽邏輯可以根據這些屬性來定點清除某個特定業務對象的緩存
- 數據同步:子系統依賴實時的數據庫記錄變動觸發相應的業務邏輯,我們這里就可以將數據庫的binlog抓取出來,通過廣播功能同步到所有監聽器,起到數據同步的作用
小結
這一節我們學習了Bus中自定義事件的實現方式,到這里Bus章節就算告一段落了,下一章我們將去學習微服務架構中的一個重要模塊-網關層Gateway。
學習Tips:有的時候看圖文教程和視頻會感覺知識很好理解,但是一上手寫程序就要各種求助百度。沒有下手練習的話,所有學習都是紙上談兵,尤其對於實戰技術來說。只要搞懂不要動手的只有一個場景,那就是面試前的知識突擊。所以大家一定要多動手,把每個小Demo都自己去實現一遍,我們的課程項目也給大家留了很大的操作空間,同學們可以把每一章學到的內容應用在更多的模塊中。