?
CAP介紹:
CAP是一個(gè)用來(lái)解決微服務(wù)或者分布式系統(tǒng)中分布式事務(wù)問(wèn)題的一個(gè)開(kāi)源項(xiàng)目解決方案??梢越鉀Q跨服務(wù)器的數(shù)據(jù)一致性問(wèn)題。一個(gè)簡(jiǎn)單的列子,如:訂單系統(tǒng)創(chuàng)建訂單后需要通知郵件通知用戶(hù)下單成功,解決方案有下面幾種:
?
?1:創(chuàng)建訂單時(shí)同步調(diào)用郵件發(fā)送,郵件發(fā)送失敗則整個(gè)訂單創(chuàng)建失敗,這樣保證了一致性,但性能和可用性有非常大的問(wèn)題?;蛘卟还茑]件發(fā)送狀態(tài),失敗了就算了,這樣用戶(hù)就可能收不到通知郵件了。
?
?2:創(chuàng)建訂單時(shí)通過(guò)消息隊(duì)列推送一個(gè)訂單創(chuàng)建成功的事件,另外創(chuàng)建一個(gè)服務(wù)來(lái)監(jiān)聽(tīng)消費(fèi)此事件,并執(zhí)行郵件發(fā)送的功能。這種方案存在往消息隊(duì)列推送數(shù)據(jù)失敗的可能,存在和方案1一樣的問(wèn)題。
? ?3:創(chuàng)建訂單時(shí)同時(shí)往一個(gè)叫“訂單創(chuàng)建成功”的事件表中插入相關(guān)數(shù)據(jù),兩者在同一事務(wù)中。
另外創(chuàng)建一個(gè)服務(wù)定時(shí)查詢(xún)此表,發(fā)現(xiàn)有待處理的數(shù)據(jù)時(shí),執(zhí)行郵件發(fā)送,成功后把此數(shù)據(jù)刪除或更新為已處理。此方案保證了最終一致性和可用性,但得定時(shí)掃描,性能和及時(shí)性有問(wèn)題。
?
?4:創(chuàng)建訂單時(shí)同時(shí)往一個(gè)叫“訂單創(chuàng)建成功”的事件表中插入相關(guān)數(shù)據(jù),兩者在同一事務(wù)中。并且通過(guò)消息隊(duì)列推送此消息,如果推送失敗,則定時(shí)掃描“訂單創(chuàng)建成功”表將失敗的數(shù)據(jù)重新推送。另外創(chuàng)建一個(gè)服務(wù)來(lái)監(jiān)聽(tīng)消費(fèi)此事件,這種方案集成了方案1和方案2的優(yōu)點(diǎn),即保證了最終一致性,也保證了可用性。
?
從上面來(lái)看最優(yōu)的方案顯示是方案4,我們這次的主角CAP也正是采用了此種方案來(lái)實(shí)現(xiàn)的,我們這里介紹的方案4還是比較簡(jiǎn)單的,CAP的實(shí)現(xiàn)要更加的嚴(yán)謹(jǐn)、更加強(qiáng)大,我們不需要建過(guò)程表,也不需要處理消息隊(duì)列的問(wèn)題,底層很多的細(xì)節(jié)都不需要我們考慮,只管用就好了。CAP數(shù)據(jù)庫(kù)存儲(chǔ)支持:Sql
Server,MySql,PostgreSql,MongoDB。消息隊(duì)列支持:RabbitMQ,Kafka,Azure Service Bus等。
?
各多CAP的介紹可以參考官網(wǎng),詳細(xì)的CAP理論可以參考其它文章。?官網(wǎng)?http://cap.dotnetcore.xyz/
<http://cap.dotnetcore.xyz/>?,開(kāi)源地址:https://github.com/dotnetcore/CAP
<https://github.com/dotnetcore/CAP>? ,作者blog?https://www.cnblogs.com/savorboard/
<https://www.cnblogs.com/savorboard/>
?
快速開(kāi)始
CAP2.6是2019-8-29發(fā)布的,目前官網(wǎng)上的文檔快速開(kāi)始已經(jīng)無(wú)法使用,因?yàn)槔锩嬗昧?
Savorboard.CAP.InMemoryMessageQueue
?組件,該組件還是2.51,不支持最新的CAP2.6版本,應(yīng)該得過(guò)段時(shí)間才會(huì)修復(fù)文檔,或者等?
Savorboard.CAP.InMemoryMessageQueue
組件更新?,F(xiàn)在我們就在這開(kāi)始我們的“快速開(kāi)始”吧。我們將基于rabbitmq和sqlserver數(shù)據(jù)庫(kù)來(lái)實(shí)現(xiàn)。
?
1:創(chuàng)建項(xiàng)目
打開(kāi)VS創(chuàng)建一個(gè)名叫CapDemo的webapi項(xiàng)目,版本選擇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數(shù)據(jù)庫(kù),連接地址請(qǐng)依實(shí)際修改
c.UseRabbitMQ( mq => { mq.HostName = "192.168.150.134"; //
RabitMq服務(wù)器地址,依實(shí)際情況修改此地址 mq.Port = 5672; mq.UserName = "admin"; //RabbitMq賬號(hào)
mq.Password ="admin"; //RabbitMq密碼 }); });
?
?
4:發(fā)布事件
將?CapDemo.Controllers.ValuesController中的所有方法全部刪除。添加引用?using DotNetCore.CAP;
?,并添加以下方法
[HttpGet] public async Task<string> Get([FromServices]ICapPublisher
capPublish) {await capPublish.PublishAsync<string>("Order.Created", "
hello,訂單創(chuàng)建成功啦"); //發(fā)布Order.Created事件 return "訂單創(chuàng)建成功啦"; }
?
5:訂閱事件
在CapDemo.Controllers.ValuesController中添加以下方法:
[NonAction] [CapSubscribe("Order.Created")] //監(jiān)聽(tīng)Order.Created事件 public async
Task OrderCreatedEventHand(string msg) { Console.WriteLine(msg); }
?
6:最后一步:?jiǎn)?dòng)測(cè)試
在OrderCreatedEventHand方法內(nèi)打個(gè)斷點(diǎn),F(xiàn)5啟動(dòng)項(xiàng)目訪(fǎng)問(wèn)https://localhost:44304
<https://localhost:44304/cap>/api/values <https://localhost:44304/api/values>
界面。因?yàn)榇死械谝淮卧L(fǎng)問(wèn)時(shí)可能發(fā)布事件比訂閱事件要快,導(dǎo)致還沒(méi)訂閱就把事件發(fā)布出去了,這樣的事件會(huì)丟失,所以我們?cè)貴5刷新一下界面,可以看到程序就進(jìn)入到了訂閱事件里面。
?
?
?
后記:
?
添加監(jiān)控儀表盤(pán)監(jiān)控CAP運(yùn)行狀況:
1:只需要在Startup.cs的AddCap方法中添加配置:?c.UseDashboard();
?就萬(wàn)事大吉了,一個(gè)功能強(qiáng)大的事件管理界面就出來(lái)了,具體如下圖:
?
?
2: 重新編譯并啟動(dòng)項(xiàng)目,進(jìn)入https://localhost:44304/cap <https://localhost:44304/cap>?
,從打開(kāi)的界面里可以看到CAP的各種事件和狀態(tài)。
?
?
?
數(shù)據(jù)庫(kù)變化
我們?cè)倏纯磾?shù)據(jù)庫(kù)里面的變化吧,從下圖可以看出CAP自動(dòng)創(chuàng)建了兩個(gè)表,并且記錄了發(fā)布的消息,和接收到的消息。這些數(shù)據(jù)會(huì)定時(shí)刪除。這些都是不需要我們管的。
?
本示例源碼下載:https://pan.baidu.com/s/1fHXSW20JHSoaYPH748VRKg
<https://pan.baidu.com/s/1fHXSW20JHSoaYPH748VRKg>
?
熱門(mén)工具 換一換
