.Net Core微服務入門全紀錄(六)——EventBus-事件匯流排
阿新 • • 發佈:2020-06-22
# 前言
上一篇【[.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