Dapr牵手.NET学习笔记:Actor小试
Actor模型是一種避免線程共享數據,相同Actor實體串行化的方案,所以不便dapr的其他功能,幾乎都是非編程入侵的,相反,Dapr Acror深度定制的,關于Actor,.net中有一些通用框架,比如Akka.net,微軟的Orleans,還有最近復活的Proto actor。Dapr下的Actor,是dapr實現了一些庫,基于這些庫來實現actor模型編程的。
本篇開個小頭,實際體會一下actor的作用,actor的一大作用就是實例隔離,相同實例不共享內存,不同實例間還是可以并行的,當然這個實現并不與OOP中的實例相等,還是看下面這個小例子吧,通過代碼來感覺。
一、首先定義一個類庫項目
需要引用Nuget包 Dapr.Actors
二、定義一個asp.net api項目
實現上面定義的接口,需要引入Nuget包Dapr.Actors.AspNetCore
需要在向Services中注入Actor
為了對比測試,可以定義一個/gettime的api,比較并串行
[ApiController] [Route("[controller]")] public class HomeController : ControllerBase {private readonly ILogger<HomeController> _logger;public HomeController(ILogger<HomeController> logger){_logger = logger;}[HttpGet("/gettime")]public IActionResult Get(string inTime){Task.Delay(3000).Wait();return Ok($"傳入時間:{inTime},返回時間:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");} }三、添加一個Actor客戶端項目
需要引用Nuget包?Dapr.Actors
using?Dapr.Actors; using Dapr.Actors.Client; using IOrderFactoryActory.Interfaces;Console.WriteLine("回車開始"); Console.ReadLine();//調用api是并行的 var client = new HttpClient(); var httpTask1 = new Task(async () => {Console.WriteLine(await client.GetStringAsync("http://localhost:5000/gettime?intime=" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"))); }); var httpTask2 = new Task(async () => {Console.WriteLine(await client.GetStringAsync("http://localhost:5000/gettime?intime=" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"))); }); httpTask1.Start(); httpTask2.Start();//相同ID的actor是串行的,不同ID的actor是并行的 var factory = new ActorProxyFactory(new ActorProxyOptions { HttpEndpoint = "http://localhost:3999" }); var account1 = CreateActor(factory, "11111111111"); var account2 = CreateActor(factory, "22222222222"); var actorTask1_1 = new Task(async () => {Console.WriteLine(await account1.GetTimeAsync(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"))); }); var actorTask1_2 = new Task(async () => {Console.WriteLine(await account1.GetTimeAsync(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"))); }); var actorTask2 = new Task(async () => {Console.WriteLine(await account2.GetTimeAsync(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"))); }); actorTask1_1.Start(); actorTask1_2.Start(); actorTask2.Start();Console.WriteLine("回車結束"); Console.ReadLine();static IAccountActor CreateActor(ActorProxyFactory factory, string accountNo) {var actorType = "AccountActor";var actorId = new ActorId(accountNo); return factory.CreateActorProxy<IAccountActor>(actorId, actorType); }四、開始測試
啟動sidecar
dapr?run?--app-id?account?--app-port?5000?--dapr-http-port?3999
運行結果:
可以通過上面的例子看到,web api的傳入時間和返回時間幾乎相同,說明他們是并行運行的,都在內部等了3秒;Actor有兩個實例,是通過ActorID來區分實例的,ID為1開頭的兩個實例雖然傳入時間幾乎相同,但在返回時間上,第二次明顯是排在第一次返回后的(這正是Actor的串行基本準則),ID為2開頭的,可以與1并行。
實際場景是什么呢?前一段時間開發了一套賬務系統,場景是有很多賬戶批量入帳,當然有可能有相同帳戶同時入帳,入帳時需要取出舊的帳戶余額,加上本次入帳金額,然后更新掉帳戶余額;因為是通過web api調過來的并發,處理辦法是在表的數據行上用行級鎖(DBA會罵娘的),保證兩個相同帳戶入帳時,不會同時取,然后都用舊余額相加。但如果這里用Actor,就可以釋放數據庫的壓力(DBA會很開心的),相同帳戶的Actor是串行執行,所以在業務層就避免了并發,不同帳戶不受影響,關鍵是Actor是細小的顆粒,可以大量創建銷毀。篇幅和時間所限,下一篇會用例子來實現這個場景。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的Dapr牵手.NET学习笔记:Actor小试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WPF中的命令(Command)
- 下一篇: 03Prism WPF 入门实战 - R