《通过C#学Proto.Actor模型》之Prpos
程序员文章站
2023-12-25 12:37:27
在第一篇Proto.Actor博文中,HelloWorld的第一行真正代码是: var props = Actor.FromProducer(() => new HelloActor()); 这个返回的变量props就是一个Props的对象,它是负责创Actor实例,以及配置Actor实例,并... ......
在第一篇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】。
现在可以自己运行一下分析一下结果吧: