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次)