private void ConnectCallback(IAsyncResult ar) { if (_closed) return; try { var session = (AsyncSession<ServerTimer>) ar.AsyncState; ServerTimer timer = session.State; _server = timer.Server; timer.Elapsed -= destConnectTimer_Elapsed; timer.Enabled = false; timer.Dispose(); var remote = session.Remote; // Complete the connection. remote.EndConnectDest(ar); _destConnected = true; if (_config.isVerboseLogging) { Logging.Info($"Socket connected to ss server: {_server.FriendlyName()}"); } var latency = DateTime.Now - _startConnectTime; IStrategy strategy = _controller.GetCurrentStrategy(); strategy?.UpdateLatency(_server, latency); _tcprelay.UpdateLatency(_server, latency); StartPipe(session); } catch (ArgumentException) { } catch (Exception e) { if (_server != null) { IStrategy strategy = _controller.GetCurrentStrategy(); strategy?.SetFailure(_server); } Logging.LogUsefulException(e); Close(); } }
private async Task<ICMPResult> ICMPTest(Server server) { Logging.Debug("Ping " + server.FriendlyName()); if (server.server == "") return null; var result = new ICMPResult(server); try { var IP = Dns.GetHostAddresses(server.server) .First( ip => ip.AddressFamily == AddressFamily.InterNetwork || ip.AddressFamily == AddressFamily.InterNetworkV6); var ping = new Ping(); foreach (var _ in Enumerable.Range(0, Repeat)) { try { var reply = await ping.SendTaskAsync(IP, TimeoutMilliseconds); if (reply.Status.Equals(IPStatus.Success)) { result.RoundtripTime.Add((int?) reply.RoundtripTime); } else { result.RoundtripTime.Add(null); } //Do ICMPTest in a random frequency Thread.Sleep(TimeoutMilliseconds + new Random().Next()%TimeoutMilliseconds); } catch (Exception e) { Logging.Error($"An exception occured while eveluating {server.FriendlyName()}"); Logging.LogUsefulException(e); } } } catch (Exception e) { Logging.Error($"An exception occured while eveluating {server.FriendlyName()}"); Logging.LogUsefulException(e); } return result; }
public void SetFailure(Server server) { Logging.Debug($"failure: {server.FriendlyName()}"); }
private async Task<List<DataList>> ICMPTest(Server server) { Logging.Debug("Ping " + server.FriendlyName()); if (server.server == "") return null; var IP = Dns.GetHostAddresses(server.server).First(ip => (ip.AddressFamily == AddressFamily.InterNetwork || ip.AddressFamily == AddressFamily.InterNetworkV6)); var ping = new Ping(); var ret = new List<DataList>(); foreach (var timestamp in Enumerable.Range(0, Repeat).Select(_ => DateTime.Now.ToString(DateTimePattern))) { //ICMP echo. we can also set options and special bytes try { var reply = await ping.SendTaskAsync(IP, Timeout); ret.Add(new List<KeyValuePair<string, string>> { new KeyValuePair<string, string>("Timestamp", timestamp), new KeyValuePair<string, string>("Server", server.FriendlyName()), new KeyValuePair<string, string>("Status", reply?.Status.ToString()), new KeyValuePair<string, string>("RoundtripTime", reply?.RoundtripTime.ToString()) //new KeyValuePair<string, string>("data", reply.Buffer.ToString()); // The data of reply }); Thread.Sleep(Timeout + new Random().Next() % Timeout); //Do ICMPTest in a random frequency } catch (Exception e) { Logging.Error($"An exception occured while eveluating {server.FriendlyName()}"); Logging.LogUsefulException(e); } } return ret; }
public void SetFailure(Server server) { Logging.Debug(String.Format("failure: {0}", server.FriendlyName())); }
/** * once failed, try after 5 min * and (last write - last read) < 5s * and (now - last read) < 5s // means not stuck * and latency < 200ms, try after 30s */ public void ChooseNewServer() { Server oldServer = _currentServer; List<ServerStatus> servers = new List<ServerStatus>(_serverStatus.Values); DateTime now = DateTime.Now; foreach (var status in servers) { // all of failure, latency, (lastread - lastwrite) normalized to 1000, then // 100 * failure - 2 * latency - 0.5 * (lastread - lastwrite) status.score = 100 * 1000 * Math.Min(5 * 60, (now - status.lastFailure).TotalSeconds) -2 * 5 * (Math.Min(2000, status.latency.TotalMilliseconds) / (1 + (now - status.lastTimeDetectLatency).TotalSeconds / 30 / 10) + -0.5 * 200 * Math.Min(5, (status.lastRead - status.lastWrite).TotalSeconds)); Logging.Debug(String.Format("server: {0} latency:{1} score: {2}", status.server.FriendlyName(), status.latency, status.score)); } ServerStatus max = null; foreach (var status in servers) { if (max == null) { max = status; } else { if (status.score >= max.score) { max = status; } } } if (max != null) { _currentServer = max.server; if (_currentServer != oldServer) { Console.WriteLine("HA switching to server: {0}", _currentServer.FriendlyName()); } Logging.Debug(String.Format("choosing server: {0}", _currentServer.FriendlyName())); } }