1. 程式人生 > >.Net Core微服務入門全紀錄(六)——EventBus-事件匯流排

.Net Core微服務入門全紀錄(六)——EventBus-事件匯流排

# 前言 上一篇【[.Net Core微服務入門全紀錄(五)——Ocelot-API閘道器(下)](https://www.cnblogs.com/xhznl/p/13132255.html)】中已經完成了Ocelot + Consul的搭建,這一篇簡單說一下EventBus。 # EventBus-事件匯流排 - 首先,什麼是事件匯流排呢? 貼一段引用: > 事件匯流排是對觀察者(釋出-訂閱)模式的一種實現。它是一種集中式事件處理機制,允許不同的元件之間進行彼此通訊而又不需要相互依賴,達到一種解耦的目的。 如果沒有接觸過EventBus,可能不太好理解。其實EventBus在客戶端開發中應用非常廣泛(android,ios,web前端等),用於多個元件(或者介面)之間的相互通訊,懂的人都懂。。。 - 那麼,我們為什麼要用EventBus呢? 就拿當前的專案舉例,我們有一個訂單服務,一個產品服務。客戶端有一個下單功能,當用戶下單時,呼叫訂單服務的下單介面,那麼下單介面需要呼叫產品服務的減庫存介面,這涉及到服務與服務之間的呼叫。那麼服務之間又怎麼呼叫呢?直接RESTAPI?或者效率更高的gRPC?可能這兩者各有各的使用場景,但是他們都存在一個服務之間的耦合問題,或者難以做到非同步呼叫。 試想一下:假設我們下單時呼叫訂單服務,訂單服務需要呼叫產品服務,產品服務又要呼叫物流服務,物流服務再去呼叫xx服務 等等。。。如果每個服務處理時間需要2s,不使用非同步的話,那這種體驗可想而知。 如果使用EventBus的話,那麼訂單服務只需要向EventBus發一個“下單事件”就可以了。產品服務會訂閱“下單事件”,當產品服務收到下單事件時,自己去減庫存就好了。這樣就避免了兩個服務之間直接呼叫的耦合性,並且真正做到了非同步呼叫。 既然涉及到多個服務之間的非同步呼叫,那麼就不得不提分散式事務。分散式事務並不是微服務獨有的問題,而是所有的分散式系統都會存在的問題。 關於分散式事務,可以查一下“CAP原則”和“BASE理論”瞭解更多。當今的分散式系統更多的會追求事務的最終一致性。 下面使用國人開發的優秀專案“CAP”,來演示一下EventBus的基本使用。之所以使用“CAP”是因為它既能解決分散式系統的最終一致性,同時又是一個EventBus,它具備EventBus的所有功能! 作者介紹:https://www.cnblogs.com/savorboard/p/cap.html # CAP使用 - 環境準備 在Docker中準備一下需要的環境,首先是資料庫,資料庫我使用PostgreSQL,用別的也行。CAP支援:SqlServer,MySql,PostgreSql,MongoDB。 關於在Docker中執行PostgreSQL可以看我的另一篇部落格:https://www.cnblogs.com/xhznl/p/13155054.html 然後是MQ,這裡我使用RabbitMQ,Kafka也可以。 Docker執行RabbitMQ: ``` docker pull rabbitmq:management docker run -d -p 15672:15672 -p 5672:5672 --name rabbitmq rabbitmq:management ``` 預設使用者:guest,密碼:guest 環境準備就完成了,Docker就是這麼方便。。。 - 程式碼修改: 為了模擬以上業務,需要修改大量程式碼,下面程式碼如有遺漏的直接去github找。 NuGet安裝: ``` Microsoft.EntityFrameworkCore Microsoft.EntityFrameworkCore.Tools Npgsql.EntityFrameworkCore.PostgreSQL ``` ![](https://img2020.cnblogs.com/blog/610959/202006/610959-20200618143010210-1425656768.png) CAP相關: ``` DotNetCore.CAP DotNetCore.CAP.RabbitMQ DotNetCore.CAP.PostgreSql ``` ![](https://img2020.cnblogs.com/blog/610959/202006/610959-20200618164131893-1707181881.png) Order.API/Controllers/OrdersController.cs增加下單介面: ``` [Route("[controller]")] [ApiController] public class OrdersController : ControllerBase { private readonly ILogger