《通过C#学Proto.Actor模型》之Supervision
程序员文章站
2023-11-02 14:16:46
Supervision,字面意思是监督,是父Actor发现子Actor有异常发生后,对子Actor产用保种策略处理的机制,如果父Actor不处理,则往上传递。 ......
supervision,字面意思是监督,是父actor发现子actor有异常发生后,对子actor产用保种策略处理的机制,如果父actor不处理,则往上传递。
子actor发生异常后处理的策略有:
resume:立即恢复
restart:恢复之前停止actor并重新创建它
stop:停止
escalate:上报到父级
supervisor的通过props.withchildsupervisorstarategy()来实施的,这个方法第一个参数是接收异常和actor的pid,以便按一定方式处理异常,第二个参数是重启的次数,第三个参数是两次重启的间隔(按照官方文档,两个连续重启时间大于间隔时间,次数会复位,但实则只按次数走,间隔不起作用)达到最大次数据,子actor将重新生成。
码友看代码:
1 using proto; 2 using system; 3 using system.collections.generic; 4 using system.linq; 5 using system.threading.tasks; 6 7 namespace p006_supervision 8 { 9 class program 10 { 11 static void main(string[] args) 12 { 13 //设置监督策略,指向supervisiormode方法,重启次数为3,两次之间间隔1s 14 var props = actor.fromproducer(() => new shopingcatactor()).withchildsupervisorstrategy(new oneforonestrategy(supervisormode.decide, 3, timespan.fromseconds(1))); 15 var pid = actor.spawn(props); 16 var user = new user { username = "gsw" }; 17 18 var sn = 1; 19 while (true) 20 { 21 console.writeline($"{sn++}--------------------begin-----------------"); 22 foreach (var goods in user.shopingcat.goodses) 23 { 24 console.writeline(goods); 25 } 26 console.writeline("---------------------end------------------"); 27 console.readline(); 28 pid.request(user, pid); 29 } 30 } 31 } 32 /// <summary> 33 /// supervisor 模式 34 /// </summary> 35 class supervisormode 36 { 37 /// <summary> 38 /// 用来处理异常发生的后续操作 39 /// </summary> 40 /// <param name="pid">pid</param> 41 /// <param name="reason">异常原因,exception类型</param> 42 /// <returns></returns> 43 public static supervisordirective decide(pid pid, exception reason) 44 { 45 console.writeline(" 异常发生:" + reason.message + " " + pid); 46 switch (reason) 47 { 48 //重新开始的异常 49 case recoverableexception _: 50 return supervisordirective.restart; 51 //停止异常 52 case fatalexception _: 53 return supervisordirective.stop; 54 //其他都上报 55 default: 56 return supervisordirective.escalate; 57 } 58 } 59 } 60 /// <summary> 61 /// 购物车actor 62 /// </summary> 63 class shopingcatactor : iactor 64 { 65 shopingcat _shopingcat; 66 public shopingcatactor() 67 { 68 _shopingcat = new shopingcat(); 69 console.writeline("*******************actor shopingcatactor************************"); 70 } 71 public task receiveasync(icontext context) 72 { 73 pid childpid; 74 if (context.children == null || context.children.count == 0) 75 { 76 var props = actor.fromproducer(() => new goodsactor()); 77 childpid = context.spawn(props); 78 } 79 else 80 { 81 childpid = context.children.first(); 82 } 83 switch (context.message) 84 { 85 case user user: 86 childpid.request(_shopingcat, childpid); 87 user.shopingcat = _shopingcat; 88 break; 89 } 90 return actor.done; 91 } 92 } 93 /// <summary> 94 /// 商品actor 95 /// </summary> 96 class goodsactor : iactor 97 { 98 public task receiveasync(icontext context) 99 { 100 switch (context.message) 101 { 102 case shopingcat shopingcat: 103 104 var goods = new goods { name = "红茶", price = 3.0m, describe = "统一" }; 105 //用来随机产生异常 106 var random = new random(); 107 goods.quantity = random.next(1, 3) - 1; 108 if (goods.quantity <= 0) 109 { 110 throw new recoverableexception("数量不能小于等于0"); 111 } 112 else 113 { 114 shopingcat.goodses.add(goods); 115 console.writeline($"添加 {goods} 到购物车里"); 116 } 117 break; 118 } 119 return actor.done; 120 } 121 } 122 /// <summary> 123 /// 用户 124 /// </summary> 125 class user 126 { 127 public shopingcat shopingcat { get; set; } = new shopingcat(); 128 public string username { get; set; } 129 } 130 /// <summary> 131 /// 购物车 132 /// </summary> 133 class shopingcat 134 { 135 public list<goods> goodses 136 { get; set; } = new list<goods>(); 137 } 138 /// <summary> 139 /// 商品 140 /// </summary> 141 class goods 142 { 143 public string name { get; set; } 144 145 public int quantity { get; set; } 146 147 public decimal price { get; set; } 148 149 public string describe { get; set; } 150 public override string tostring() 151 { 152 return $"name={name},quantity={quantity},price={price},describe={describe}"; 153 } 154 } 155 156 }
demo中有三个实体类,用户类,购物车类,商品类,他们的关系一目了解,聚合关系。有两个actor,购物车actor(shopingcatactor),商品actor(goodsactor),商品actor是购物车actor子actor;shopingcatactor下有监督策略,在
supervisormode下的decide方法中,处理不同的异常,采用不同的actor策略。goodsactor中,添加商品时根据数量来决定是否产生异常。
看运行结果:
注意看id $1/$2,是在发生四次异常后才生成$1/$3的(这个与文档说法有出入,也许是我理解有问题,是重启3次,不是启动3次)
推荐阅读