/// <summary> /// 加载节点 /// </summary> /// <param name="input">"name=dc1,ip=192.168.X.X,port=6659,timeout=3000,weight=5"</param> public bool Add(Dictionary <string, string> input) { lock (LockAdd) { try { var ip = GetValidIp(input["ip"], Convert.ToInt32(input["port"])); if (ip == string.Empty) { return(false); } ServiceInfo ips = new ServiceInfo { Timeout = input["timeout"] == null ? TimeOut : Convert.ToInt32(input["timeout"]), Name = input["name"], NickName = input["nickname"], Ip = ip, Port = Convert.ToInt32(input["port"]) }; int weight = input["weight"] == null ? 1 : (int)Convert.ToDecimal(input["weight"]); ips.Weight = weight; #region 原有服务 var oldService = ServiceInfoList.FirstOrDefault(t => ips.Ip == t.Ip && ips.Port == t.Port); #endregion ServiceInfoList.RemoveAll(t => ips.Ip == t.Ip && ips.Port == t.Port); for (int w = 0; w < weight; w++) //权重 { ServiceInfoList.Add(ips); } Log.WriteLine($"{ips.Ip}:{ips.Port}", ConsoleColor.DarkGreen); ips.Name.Split(',').ToList().ForEach(f => { Log.WriteLine($"{f}", ConsoleColor.DarkGreen); }); Log.WriteLine($"{"权重:" + ips.Weight}", ConsoleColor.DarkGreen); Log.WriteLine($"{ips.NickName}已登记!", ConsoleColor.DarkGreen); Log.WriteLineNoDate($"-----------------------------------------------------------------------------"); #region 线和变更通知 if (OnlineNotice != null && oldService == null) { OnlineNotice.Invoke(ips, NoticeType.OnLine); } else if (ChangeNotice != null && oldService != null) { ChangeNotice.Invoke(ips, oldService); } #endregion } catch (Exception ex) { Console.WriteLine(ex); return(false); } finally { Save(); } } return(true); }
/// <summary> /// 健康检查,如果连接不上 每秒做一次尝试。 /// 尝试 errorCount 次失败,软删除。 /// 60次失败,永久删除。 /// </summary> /// <param name="service">被检测主机信息</param> /// <param name="errorCount">尝试 errorCount 次失败,软删除</param> /// <returns></returns> public static void HealthCheck(ServiceInfo service, int errorCount = 3) { int hc = 60; //检查次数 hCheck: //再次 心跳检测 TTransport transport = new TSocket(service.Ip, service.Port, 3000); try { service.Checking = true; transport.Open(); if (transport.IsOpen) { if (hc != 60) { Console.ForegroundColor = ConsoleColor.DarkGreen; Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss}: "); Console.WriteLine($"{service.Ip}:{service.Port}"); foreach (var f in service.Name.Split(',')) { Console.WriteLine($"{f}"); } Console.WriteLine($"{"w:" + service.Weight}"); Console.WriteLine($"恢复正常!"); Console.ResetColor(); Console.WriteLine($"----------------------------------------------------------------- "); } if (hc <= (60 - errorCount)) { CheckNotice?.Invoke(service, NoticeType.RecoverHealth); } transport.Flush(); transport.Close(); lock (LockHelper) //防止高并发下 影响权重 { if (!Tc.ServiceInfoList.Exists(s => s.Ip == service.Ip && s.Port == service.Port)) { //已存在不再添加 不存在则添加 for (int i = 0; i < service.Weight; i++) { Tc.ServiceInfoList.Add(service); } } } } transport.Dispose(); } catch (Exception ex) { Console.WriteLine($"Error Info:{service.Ip}:{service.Port} {ex.Message}"); if (hc == 60) { Console.ForegroundColor = ConsoleColor.DarkYellow; Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss}: "); Console.WriteLine($"{service.Ip}:{service.Port}"); foreach (var f in service.Name.Split(',')) { Console.WriteLine($"{f}"); } Console.WriteLine($"{"w:" + service.Weight}"); Console.WriteLine($"检测中···{hc}!"); Console.ResetColor(); Console.WriteLine($"----------------------------------------------------------------- "); } else if (hc == (60 - errorCount)) { Console.ForegroundColor = ConsoleColor.DarkYellow; Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss}: "); Console.WriteLine($"{service.Ip}:{service.Port}"); foreach (var f in service.Name.Split(',')) { Console.WriteLine($"{f}"); } Console.WriteLine($"{"w:" + service.Weight}"); Console.WriteLine($"故障恢复中···{hc}!"); Console.ResetColor(); Console.WriteLine($"----------------------------------------------------------------- "); } else if (hc == 0) //硬删除 { Console.ForegroundColor = ConsoleColor.DarkRed; Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss}:"); Console.WriteLine($"{service.Ip}:{service.Port}"); foreach (var f in service.Name.Split(',')) { Console.WriteLine($"{f}"); } Console.WriteLine($"{"w:" + service.Weight}"); Console.WriteLine($"永久移除!"); Console.ResetColor(); Console.WriteLine($"----------------------------------------------------------------- "); CheckNotice?.Invoke(service, NoticeType.OffLine); } if (hc == (60 - errorCount)) //三次失败之后 临时移除 ,防止更多请求转发给此服务节点 { //临时移除 并不从配置文件移除 Tc.ServiceInfoList.RemoveAll(i => i.Ip == service.Ip && i.Port == service.Port); CheckNotice?.Invoke(service, NoticeType.NotHealth); } else if (hc == 0) //硬删除 { Dictionary <string, string> rp = new Dictionary <string, string> { { "ip", service.Ip }, { "port", service.Port.ToString() } }; Tc.Remove(rp); return; } Thread.Sleep(1000); //间隔一秒 健康检查 hc--; transport.Dispose(); goto hCheck; } finally { if (transport.IsOpen) { transport.Flush(); transport.Close(); } transport.Dispose(); service.Checking = false; } }
/// <summary> /// 变更服务信息 /// </summary> /// <param name="input"></param> /// <returns></returns> public bool ChangeMicroServiceWeight(Dictionary <string, string> input) { lock (LockAdd) { try { if (!input.ContainsKey("ip") || !input.ContainsKey("port") || (!input.ContainsKey("weight") && !input.ContainsKey("timeout"))) { return(false); } var ip = input["ip"]; int.TryParse(input["port"], out int port); var hasWeight = false; int weight = 0; int timeout = 0; if (input.ContainsKey("weight")) { hasWeight = int.TryParse(input["weight"], out weight); } var hasTimeOut = false; if (input.ContainsKey("timeout")) { hasTimeOut = int.TryParse(input["timeout"], out timeout); } #region 原有服务 var oldService = ServiceInfoList.FirstOrDefault(t => ip == t.Ip && port == t.Port); if (oldService == null) { return(false); } #endregion ServiceInfo serviceInfo = new ServiceInfo() { Timeout = oldService.Timeout, Name = oldService.Name, NickName = oldService.NickName, Ip = oldService.Ip, Port = oldService.Port, Weight = oldService.Weight }; if (hasTimeOut) { serviceInfo.Timeout = timeout; } if (hasWeight) { serviceInfo.Weight = weight; } ServiceInfoList.RemoveAll(t => ip == t.Ip && port == t.Port); for (int w = 0; w < weight; w++) //权重 { ServiceInfoList.Add(serviceInfo); } /* * 至少保留一条服务信息数据 */ if (weight <= 0) { ServiceInfoList.Add(serviceInfo); } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine($"{serviceInfo.Ip}:{serviceInfo.Port}"); foreach (var f in serviceInfo.Name.Split(',')) { stringBuilder.AppendLine($"{f}"); } stringBuilder.AppendLine($"{"权重:" + serviceInfo.Weight}"); stringBuilder.AppendLine($"{serviceInfo.NickName}已登记!"); Log.Anno(stringBuilder.ToString(), typeof(ThriftConfig)); #region 线和变更通知 if (ChangeNotice != null && oldService != null) { ChangeNotice.Invoke(serviceInfo, oldService); } #endregion } catch (Exception ex) { Log.Anno(ex, typeof(ThriftConfig)); return(false); } finally { Save(); } } return(true); }
/// <summary> /// 加载节点 /// </summary> /// <param name="input">"name=dc1,ip=192.168.X.X,port=6659,timeout=3000,weight=5"</param> public bool Add(Dictionary <string, string> input) { lock (LockAdd) { try { var ip = GetValidIp(input["ip"], Convert.ToInt32(input["port"])); if (ip == string.Empty) { return(false); } ServiceInfo ips = new ServiceInfo { Timeout = input["timeout"] == null ? TimeOut : Convert.ToInt32(input["timeout"]), Name = input["name"], NickName = input["nickname"], Ip = ip, Port = Convert.ToInt32(input["port"]) }; int weight = input["weight"] == null ? 1 : (int)Convert.ToDecimal(input["weight"]); ips.Weight = weight; #region 原有服务 var oldService = ServiceInfoList.FirstOrDefault(t => ips.Ip == t.Ip && ips.Port == t.Port); #endregion ServiceInfoList.RemoveAll(t => ips.Ip == t.Ip && ips.Port == t.Port); for (int w = 0; w < weight; w++) //权重 { ServiceInfoList.Add(ips); } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine($"{ips.Ip}:{ips.Port}"); foreach (var f in ips.Name.Split(',')) { stringBuilder.AppendLine($"{f}"); } stringBuilder.AppendLine($"{"权重:" + ips.Weight}"); stringBuilder.AppendLine($"{ips.NickName}已登记!"); Log.Anno(stringBuilder.ToString(), typeof(ThriftConfig)); #region 线和变更通知 if (OnlineNotice != null && oldService == null) { OnlineNotice.Invoke(ips, NoticeType.OnLine); } else if (ChangeNotice != null && oldService != null) { ChangeNotice.Invoke(ips, oldService); } #endregion } catch (Exception ex) { Log.Anno(ex, typeof(ThriftConfig)); return(false); } finally { Save(); } } return(true); }
/// <summary> /// 加载节点 /// </summary> /// <param name="input">"name=dc1,ip=192.168.X.X,port=6659,timeout=3000,weight=5"</param> public bool Add(Micro input) { lock (LockAdd) { try { var ip = GetValidIp(input.Ip, input.Port); if (ip == string.Empty) { return(false); } ServiceInfo ips = new ServiceInfo { Timeout = input.Timeout, Name = input.Name, NickName = input.Nickname, Ip = ip, Port = input.Port }; int weight = input.Weight <= 0 ? 1 : input.Weight; ips.Weight = weight; #region 线和变更通知 var oldService = ServiceInfoList.FirstOrDefault(t => ips.Ip == t.Ip && ips.Port == t.Port); if (OnlineNotice != null && oldService == null) { OnlineNotice.Invoke(ips, NoticeType.OnLine); } else if (ChangeNotice != null && oldService != null) { ChangeNotice.Invoke(ips, oldService); } #endregion ServiceInfoList.RemoveAll(t => ips.Ip == t.Ip && ips.Port == t.Port); for (int w = 0; w < weight; w++) //权重 { ServiceInfoList.Add(ips); } Console.ForegroundColor = ConsoleColor.DarkGreen; Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss}"); Console.WriteLine($"{ips.Ip}:{ips.Port}"); ips.Name.Split(',').ToList().ForEach(f => { Console.WriteLine($"{f}"); }); Console.WriteLine($"{"w:" + ips.Weight}"); Console.WriteLine($"{ips.NickName}已登记!"); Console.ResetColor(); Console.WriteLine($"----------------------------------------------------------------- "); } catch (Exception ex) { Console.WriteLine(ex); return(false); } finally { Save(); } } return(true); }
/// <summary> /// 健康检查,如果连接不上 每秒做一次尝试。 /// 尝试 errorCount 次失败,软删除。 /// 60次失败,永久删除。 /// </summary> /// <param name="service">被检测主机信息</param> /// <param name="errorCount">尝试 errorCount 次失败,软删除</param> /// <returns></returns> public static void HealthCheck(ServiceInfo service, int errorCount = 3) { try { int hc = 60;//检查次数 service.Checking = true; while (hc > 0) { var client = new BrokerService.BrokerServiceClient(new Channel($"{service.Ip}:{service.Port}", ChannelCredentials.Insecure)); if (Alive(client)) { if (hc == 60) { break; } else { if (hc < (60 - errorCount)) { WriteHealthCheck(service, hc, "恢复正常"); } if (service.IsTemporaryRemove) //如果服务已被临时移除则找回 { lock (LockHelper) //防止高并发下 影响权重 { if (!Tc.ServiceInfoList.Exists(s => s.Ip == service.Ip && s.Port == service.Port)) { //已存在不再添加 不存在则添加 for (int i = 0; i < service.Weight; i++) { Tc.ServiceInfoList.Add(service); } } } CheckNotice?.Invoke(service, NoticeType.RecoverHealth); } } break; } else { hc--; if (hc < (60 - errorCount) && (hc % errorCount == 0)) { Log.Anno($"Error Info:{service.Ip}:{service.Port} not alive {hc}", typeof(Distribute)); } if (hc == (60 - errorCount))//三次失败之后 临时移除 ,防止更多请求转发给此服务节点 { //临时移除 并不从配置文件移除 Tc.ServiceInfoList.RemoveAll(i => i.Ip == service.Ip && i.Port == service.Port); service.IsTemporaryRemove = true; CheckNotice?.Invoke(service, NoticeType.NotHealth); WriteHealthCheck(service, hc, "故障恢复中"); } else if (hc == 0) //硬删除 { Dictionary <string, string> rp = new Dictionary <string, string> { { "ip", service.Ip }, { "port", service.Port.ToString() } }; Tc.Remove(rp); CheckNotice?.Invoke(service, NoticeType.OffLine); WriteHealthCheck(service, hc, "永久移除"); break; } Task.Delay(1000).Wait();//间隔一秒 健康检查 } } } finally { service.Checking = false; } }
/// <summary> /// 健康检查,如果连接不上 每秒做一次尝试。 /// 尝试 errorCount 次失败,软删除。 /// 60次失败,永久删除。 /// </summary> /// <param name="service">被检测主机信息</param> /// <param name="errorCount">尝试 errorCount 次失败,软删除</param> /// <returns></returns> public static void HealthCheck(ServiceInfo service, int errorCount = 3) { int hc = 60; //检查次数 hCheck: //再次 心跳检测 var client = new BrokerService.BrokerServiceClient(new Channel($"{service.Ip}:{service.Port}", ChannelCredentials.Insecure)); try { service.Checking = true; if (!client.Ping(new Empty()).Reply) { if (hc != 60) { Console.ForegroundColor = ConsoleColor.DarkGreen; Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss}: "); Console.WriteLine($"{service.Ip}:{service.Port}"); Console.WriteLine($"{service.Name}"); foreach (var f in service.Name.Split(',')) { Console.WriteLine($"{f}"); } Console.WriteLine($"{"w:" + service.Weight}"); Console.WriteLine($"恢复正常!"); Console.ResetColor(); Console.WriteLine($"----------------------------------------------------------------- "); } lock (LockHelper) //防止高并发下 影响权重 { if (!Tc.ServiceInfoList.Exists(s => s.Ip == service.Ip && s.Port == service.Port)) { //已存在不再添加 不存在则添加 for (int i = 0; i < service.Weight; i++) { Tc.ServiceInfoList.Add(service); } } } } } catch (Exception ex) { Console.WriteLine($"Error Info:{service.Ip}:{service.Port} {ex.Message}"); if (hc == 60) { Console.ForegroundColor = ConsoleColor.DarkYellow; Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss}: "); Console.WriteLine($"{service.Ip}:{service.Port}"); foreach (var f in service.Name.Split(',')) { Console.WriteLine($"{f}"); } Console.WriteLine($"{"w:" + service.Weight}"); Console.WriteLine($"检测中···{hc}!"); Console.ResetColor(); Console.WriteLine($"----------------------------------------------------------------- "); } else if (hc == (60 - errorCount)) { Console.ForegroundColor = ConsoleColor.DarkYellow; Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss}: "); Console.WriteLine($"{service.Ip}:{service.Port}"); foreach (var f in service.Name.Split(',')) { Console.WriteLine($"{f}"); } Console.WriteLine($"{"w:" + service.Weight}"); Console.WriteLine($"故障恢复中···{hc}!"); Console.ResetColor(); Console.WriteLine($"----------------------------------------------------------------- "); } else if (hc == 0) //硬删除 { Console.ForegroundColor = ConsoleColor.DarkRed; Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss}:"); Console.WriteLine($"{service.Ip}:{service.Port}"); foreach (var f in service.Name.Split(',')) { Console.WriteLine($"{f}"); } Console.WriteLine($"{"w:" + service.Weight}"); Console.WriteLine($"永久移除!"); Console.ResetColor(); Console.WriteLine($"----------------------------------------------------------------- "); } if (hc == (60 - errorCount)) //三次失败之后 临时移除 ,防止更多请求转发给此服务节点 { //临时移除 并不从配置文件移除 Tc.ServiceInfoList.RemoveAll(i => i.Ip == service.Ip && i.Port == service.Port); } else if (hc == 0) //硬删除 { Dictionary <string, string> rp = new Dictionary <string, string> { { "ip", service.Ip }, { "port", service.Port.ToString() } }; Tc.Remove(rp); return; } Thread.Sleep(1000); //间隔一秒 健康检查 hc--; goto hCheck; } finally { service.Checking = false; } }