《通过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】。
现在可以自己运行一下分析一下结果吧:
****欢迎关注我的asp.net core系统课程****
《asp.net core精要讲解》 https://ke.qq.com/course/265696
《asp.net core 3.0》 https://ke.qq.com/course/437517
《asp.net core项目实战》 https://ke.qq.com/course/291868
《基于.net core微服务》 https://ke.qq.com/course/299524
《asp.net core精要讲解》 https://ke.qq.com/course/265696
《asp.net core 3.0》 https://ke.qq.com/course/437517
《asp.net core项目实战》 https://ke.qq.com/course/291868
《基于.net core微服务》 https://ke.qq.com/course/299524