《通过C#学Proto.Actor模型》之Supervision
2018-08-31 09:39
99 查看
Supervision,字面意思是监督,是父Actor发现子Actor有异常发生后,对子Actor产用保种策略处理的机制,如果父Actor不处理,则往上传递。
子Actor发生异常后处理的策略有:
Resume:立即恢复
Restart:恢复之前停止Actor并重新创建它
Stop:停止
Escalate:上报到父级
Supervisor的通过Props.WithChildSupervisorStarategy()来实施的,这个方法第一个参数是接收异常和Actor的PID,以便按一定方式处理异常,第二个参数是重启的次数,第三个参数是两次重启的间隔(按照官方文档,两个连续重启时间大于间隔时间,次数会复位,但实则只按次数走,间隔不起作用)达到最大次数据,子Actor将重新生成。
码友看代码:
using Proto; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace P006_Supervision { class Program { static void Main(string[] args) { //设置监督策略,指向SupervisiorMode方法,重启次数为3,两次之间间隔1s var props = Actor.FromProducer(() => new ShopingCatActor()).WithChildSupervisorStrategy(new OneForOneStrategy(SupervisorMode.Decide, 3, TimeSpan.FromSeconds(1))); var pid = Actor.Spawn(props); var user = new User { UserName = "gsw" }; var sn = 1; while (true) { Console.WriteLine($"{sn++}--------------------begin-----------------"); foreach (var goods in user.ShopingCat.Goodses) { Console.WriteLine(goods); } Console.WriteLine("---------------------end------------------"); Console.ReadLine(); pid.Request(user, pid); } } } /// <summary> /// Supervisor 模式 /// </summary> class SupervisorMode { /// <summary> /// 用来处理异常发生的后续操作 /// </summary> /// <param name="pid">PID</param> /// <param name="reason">异常原因,Exception类型</param> /// <returns></returns> public static SupervisorDirective Decide(PID pid, Exception reason) { Console.WriteLine(" 异常发生:" + reason.Message + " " + pid); switch (reason) { //重新开始的异常 case RecoverableException _: return SupervisorDirective.Restart; //停止异常 case FatalException _: return SupervisorDirective.Stop; //其他都上报 default: return SupervisorDirective.Escalate; } } } /// <summary> /// 购物车actor /// </summary> class ShopingCatActor : IActor { ShopingCat _shopingCat; public ShopingCatActor() { _shopingCat = new ShopingCat(); Console.WriteLine("*******************actor ShopingCatActor************************"); } public Task ReceiveAsync(IContext context) { PID childPid; if (context.Children == null || context.Children.Count == 0) { var props = Actor.FromProducer(() => new GoodsActor()); childPid = context.Spawn(props); } else { childPid = context.Children.First(); } switch (context.Message) { case User user: childPid.Request(_shopingCat, childPid); user.ShopingCat = _shopingCat; break; } return Actor.Done; } } /// <summary> /// 商品actor /// </summary> class GoodsActor : IActor { public Task ReceiveAsync(IContext context) { switch (context.Message) { case ShopingCat shopingCat: var goods = new Goods { Name = "红茶", Price = 3.0m, Describe = "统一" }; //用来随机产生异常 var random = new Random(); goods.Quantity = random.Next(1, 3) - 1; if (goods.Quantity <= 0) { throw new RecoverableException("数量不能小于等于0"); } else { shopingCat.Goodses.Add(goods); Console.WriteLine($"添加 {goods} 到购物车里"); } break; } return Actor.Done; } } /// <summary> /// 用户 /// </summary> class User { public ShopingCat ShopingCat { get; set; } = new ShopingCat(); public string UserName { get; set; } } /// <summary> /// 购物车 /// </summary> class ShopingCat { public List<Goods> Goodses { get; set; } = new List<Goods>(); } /// <summary> /// 商品 /// </summary> class Goods { public string Name { get; set; } public int Quantity { get; set; } public decimal Price { get; set; } public string Describe { get; set; } public override string ToString() { return $"Name={Name},Quantity={Quantity},Price={Price},Describe={Describe}"; } } }
Demo中有三个实体类,用户类,购物车类,商品类,他们的关系一目了解,聚合关系。有两个Actor,购物车Actor(ShopingCatActor),商品Actor(GoodsActor),商品Actor是购物车Actor子Actor;ShopingCatActor下有监督策略,在
SupervisorMode下的Decide方法中,处理不同的异常,采用不同的Actor策略。GoodsActor中,添加商品时根据数量来决定是否产生异常。
看运行结果:
注意看ID $1/$2,是在发生四次异常后才生成$1/$3的(这个与文档说法有出入,也许是我理解有问题,是重启3次,不是启动3次)
相关文章推荐
- 《通过C#学Proto.Actor模型》之 HelloWorld
- 《通过C#学Proto.Actor模型》之Prpos
- 通过C#使用googleAPI (二)2/2
- C#通过WIN32 API 获取外部程序sysListview的值和TreeView的值
- C# 通过IEnumberable接口和IEnumerator接口实现自定义集合类型foreach功能
- C# asp.net页面通过URL参数传值中文乱码问题解决办法
- C++ 通过代码托管的方式调用c#的httpAgilityPack库
- C# 通过GET、POST请求获取结果
- C#通过反射获得类的实例简单实现
- C#调用短信接口(通过简单的工厂模式整合多个短信平台)
- Atitit,通过pid获取进程文件路径 java php c#.net版本大总结
- c#通过委托delegate与Dictionary实现action选择器代码举例
- c#:通过MD5得到文件和String的校验值
- 通过 API 实现 C# 对硬件的控制(二)
- C# Visual Studio 2005中,通过一个窗体打开另一个窗体
- c#通过文件存储 调用cookies的代码
- C#通过Web获取客户端的IP与Mac地址实现
- C#通过关键字访问文本特定内容
- C#通过接口与线程通信(捕获线程状态)介绍
- C#中级-通过注册表读取Windows Service程序执行路径