《通過C#學Proto.Actor模型》之Prpos


在第一篇Proto.Actor博文中,HelloWorld的第一行真正代碼是:

   var props = Actor.FromProducer(() => new HelloActor());

這個返回的變量props就是一個Props的對象,它是負責創Actor實例,以及配置Actor實例,並且產Actor上下文Context(類似asp.net中的Context)。

Props對象產生通常是用Actor.FromProducer或Actor.FromFunc產生,不過也可能實例化,實體例時可以給Actor做一系列配置,如下代碼:

 1 using Proto;
 2 using Proto.Mailbox;
 3 using System;
 4 using System.Threading.Tasks;
 5 
 6 namespace P002_CustomProps
 7 {
 8     class Program
 9     {
10         static void Main(string[] args)
11         {
12             var props = new Props()
13                 //用道具代理返回一個IActor實例
14                 .WithProducer(() => new MyActor())
15                 //默認調度器用線程池,郵箱中最多300個消息吞吐量
16                 .WithDispatcher(new ThreadPoolDispatcher { Throughput = 300 })
17                 //默認郵箱使用無界隊列
18                 .WithMailbox(() => UnboundedMailbox.Create())
19                 //默認策略在10秒的窗口內最多重新啟動子Actor 10次
20                 .WithChildSupervisorStrategy(new OneForOneStrategy((who, reason) =>
21                 SupervisorDirective.Restart, 10, TimeSpan.FromSeconds(10)))
22                 //可以將中間件鏈接起來以攔截傳入和傳出消息 
23                 //接收中間件在Actor接收消息之前被調用
24                 //發送者中間件在消息發送到目標PID之前被調用
25                 .WithReceiveMiddleware(
26                 next => async c =>
27                 {
28                     Console.WriteLine($"Receive中間件 1 開始,{c.Message.GetType()}:{c.Message}");
29                     await next(c);
30                     Console.WriteLine($"Receive中間件 1 結束,{c.Message.GetType()}:{c.Message}");
31                 },
32                 next => async c =>
33                 {
34                     Console.WriteLine($"Receive中間件 2 開始,{c.Message.GetType()}:{c.Message}");
35                     await next(c);
36                     Console.WriteLine($"Receive中間件 2 結束,{c.Message.GetType()}:{c.Message}");
37                 })
38                 .WithSenderMiddleware(
39                 next => async (c, target, envelope) =>
40                 {
41                     Console.WriteLine($"Sender中間件 1 開始, {c.Message.GetType()}:{c.Message}");
42                     await next(c, target, envelope);
43                     Console.WriteLine($"Sender中間件 1 結束,{c.Message.GetType()}:{c.Message}");
44                 },
45                 next => async (c, target, envelope) =>
46                 {
47                     Console.WriteLine($"Sender中間件 2 開始,{c.Message.GetType()}:{c.Message}");
48                     await next(c, target, envelope);
49                     Console.WriteLine($"Sender中間件 2 結束,{c.Message.GetType()}:{c.Message}");
50                 })
51                 // 默認的 spawner 構造  Actor, Context 和 Process
52                 .WithSpawner(Props.DefaultSpawner);
53 
54             //從props衍生pid,pid代理一個actor的地址
55             var pid = Actor.Spawn(props);       
56             //把Hello對象交給HelloActor處理
57             pid.Tell(new MyEntity
58             {
59                 Message = "我是MyEntity的Message,請求"
60             });
61             Console.ReadLine();    
62         }
63     }
64 
65     public class MyActor : IActor
66     {
67         public Task ReceiveAsync(IContext context)
68         {
69             if (context.Message is MyEntity myEntity)
70             {
71                 Console.WriteLine(myEntity.Message);
72                 context.Tell(context.Sender, new MyEntity() { Message = "我是MyEntity的Message,應答" });
73             }
74             return Actor.Done;
75         }
76     }
77     public class MyEntity
78     {
79         public string Message { get; set; }
80     }
81 }

你會發現,Demo中,總有一個實例類+一個Actor類,這是構成Actor模型的必備,Actor類就是主體,實體類就是Actor類運算的載體,所以它們總是如影隨形。

 第15 行到第21 行代碼含意以后會解釋。 

這里說Recevie和Sender的中間件,這里很像一個AOP,可以在調用某個行為前后作處理統一的處理,比如日志,權限等統一的規則,也和asp.net core里的中件間如出一轍【如里你是一個asp.net core碼友,熟悉的Context,熟悉的next(),還有熟悉的Middleware】。

現在可以自己運行一下分析一下結果吧:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM