CAP介紹: CAP是一個用來解決微服務或者分散式系統中分散式事務問題的一個開源項目解決方案。可以解決跨伺服器的數據一致性問題。一個簡單的列子,如:訂單系統創建訂單後需要通知郵件通知用戶下單成功,解決方案有下麵幾種: 1:創建訂單時同步調用郵件發送,郵件發送失敗則整個訂單創建失敗,這樣保證了一致性, ...
CAP介紹:
CAP是一個用來解決微服務或者分散式系統中分散式事務問題的一個開源項目解決方案。可以解決跨伺服器的數據一致性問題。一個簡單的列子,如:訂單系統創建訂單後需要通知郵件通知用戶下單成功,解決方案有下麵幾種:
1:創建訂單時同步調用郵件發送,郵件發送失敗則整個訂單創建失敗,這樣保證了一致性,但性能和可用性有非常大的問題。或者不管郵件發送狀態,失敗了就算了,這樣用戶就可能收不到通知郵件了。
2:創建訂單時通過消息隊列推送一個訂單創建成功的事件,另外創建一個服務來監聽消費此事件,並執行郵件發送的功能。這種方案存在往消息隊列推送數據失敗的可能,存在和方案1一樣的問題。
3:創建訂單時同時往一個叫“訂單創建成功”的事件表中插入相關數據,兩者在同一事務中。 另外創建一個服務定時查詢此表,發現有待處理的數據時,執行郵件發送,成功後把此數據刪除或更新為已處理。此方案保證了最終一致性和可用性,但得定時掃描,性能和及時性有問題。
4:創建訂單時同時往一個叫“訂單創建成功”的事件表中插入相關數據,兩者在同一事務中。並且通過消息隊列推送此消息,如果推送失敗,則定時掃描“訂單創建成功”表將失敗的數據重新推送。另外創建一個服務來監聽消費此事件,這種方案集成了方案1和方案2的優點,即保證了最終一致性,也保證了可用性。
從上面來看最優的方案顯示是方案4,我們這次的主角CAP也正是採用了此種方案來實現的,我們這裡介紹的方案4還是比較簡單的,CAP的實現要更加的嚴謹、更加強大,我們不需要建過程表,也不需要處理消息隊列的問題,底層很多的細節都不需要我們考慮,只管用就好了。CAP資料庫存儲支持:Sql Server,MySql,PostgreSql,MongoDB。消息隊列支持:RabbitMQ,Kafka,Azure Service Bus等。
各多CAP的介紹可以參考官網,詳細的CAP理論可以參考其它文章。 官網 http://cap.dotnetcore.xyz/ ,開源地址:https://github.com/dotnetcore/CAP ,作者blog https://www.cnblogs.com/savorboard/
快速開始
CAP2.6是2019-8-29發佈的,目前官網上的文檔快速開始已經無法使用,因為裡面用了 Savorboard.CAP.InMemoryMessageQueue 組件,該組件還是2.51,不支持最新的CAP2.6版本,應該得過段時間才會修複文檔,或者等 Savorboard.CAP.InMemoryMessageQueue組件更新。現在我們就在這開始我們的“快速開始”吧。我們將基於rabbitmq和sqlserver資料庫來實現。
1:創建項目
打開VS創建一個名叫CapDemo的webapi項目,版本選擇ASP.NET Core 2.2。CAP2.6不支持2.2以下的.net core
2:添加CAP引用
在Nuget中添加 DotNetCore.CAP DotNetCore.CAP.RabbitMQ DotNetCore.CAP.SqlServer 的引用。
3:配置CAP
在Startup.cs的ConfigureServices方法中添加以下代碼
services.AddCap(c => { c.UseSqlServer(@"Data Source=.\sql2014;Initial Catalog=Test;User ID=sa;Password=sa"); //使用SqlServer資料庫,連接地址請依實際修改 c.UseRabbitMQ( mq => { mq.HostName = "192.168.150.134"; //RabitMq伺服器地址,依實際情況修改此地址 mq.Port = 5672; mq.UserName = "admin"; //RabbitMq賬號 mq.Password = "admin"; //RabbitMq密碼 }); });
4:發佈事件
將 CapDemo.Controllers.ValuesController中的所有方法全部刪除。添加引用 using DotNetCore.CAP; ,並添加以下方法
[HttpGet] public async Task<string> Get([FromServices]ICapPublisher capPublish) { await capPublish.PublishAsync<string>("Order.Created", "hello,訂單創建成功啦"); //發佈Order.Created事件 return "訂單創建成功啦"; }
5:訂閱事件
在CapDemo.Controllers.ValuesController中添加以下方法:
[NonAction] [CapSubscribe("Order.Created")] //監聽Order.Created事件 public async Task OrderCreatedEventHand(string msg) { Console.WriteLine(msg); }
6:最後一步:啟動測試
在OrderCreatedEventHand方法內打個斷點,F5啟動項目訪問https://localhost:44304/api/values界面。因為此例中第一次訪問時可能發佈事件比訂閱事件要快,導致還沒訂閱就把事件發佈出去了,這樣的事件會丟失,所以我們再F5刷新一下界面,可以看到程式就進入到了訂閱事件裡面。
後記:
添加監控儀錶盤監控CAP運行狀況:
1:只需要在Startup.cs的AddCap方法中添加配置: c.UseDashboard(); 就萬事大吉了,一個功能強大的事件管理界面就出來了,具體如下圖:
2: 重新編譯並啟動項目,進入https://localhost:44304/cap ,從打開的界面里可以看到CAP的各種事件和狀態。
資料庫變化
我們再看看資料庫裡面的變化吧,從下圖可以看出CAP自動創建了兩個表,並且記錄了發佈的消息,和接收到的消息。這些數據會定時刪除。這些都是不需要我們管的。
本示例源碼下載:https://pan.baidu.com/s/1fHXSW20JHSoaYPH748VRKg