Browse Source

HA almost works

tags/2.5
clowwindy 9 years ago
parent
commit
cb5fece8b3
2 changed files with 56 additions and 11 deletions
  1. +2
    -1
      shadowsocks-csharp/Controller/Service/TCPRelay.cs
  2. +54
    -10
      shadowsocks-csharp/Controller/Strategy/HighAvailabilityStrategy.cs

+ 2
- 1
shadowsocks-csharp/Controller/Service/TCPRelay.cs View File

@@ -441,7 +441,8 @@ namespace Shadowsocks.Controller
if (totalRead == 0)
{
// closed before anything received, reports as failure
controller.GetCurrentStrategy().SetFailure(this.server);
// disable this feature
// controller.GetCurrentStrategy().SetFailure(this.server);
}
}
}


+ 54
- 10
shadowsocks-csharp/Controller/Strategy/HighAvailabilityStrategy.cs View File

@@ -16,6 +16,7 @@ namespace Shadowsocks.Controller.Strategy
{
// time interval between SYN and SYN+ACK
public TimeSpan latency;
public DateTime lastTimeDetectLatency;
// last time anything received
public DateTime lastRead;
@@ -27,13 +28,9 @@ namespace Shadowsocks.Controller.Strategy
public DateTime lastFailure;
public Server server;
}
/**
* if last failure is > 10 min
* and (last write > last read) and (now - last read < 5s) // means not stuck
* choose the lowest latency
*/
public double score;
}
public HighAvailabilityStrategy(ShadowsocksController controller)
{
@@ -63,22 +60,68 @@ namespace Shadowsocks.Controller.Strategy
{
var status = new ServerStatus();
status.server = server;
status.lastFailure = DateTime.MinValue;
status.lastRead = DateTime.Now;
status.lastWrite = DateTime.Now;
status.latency = new TimeSpan(0, 0, 0, 0, 10);
status.lastTimeDetectLatency = DateTime.Now;
newServerStatus[server] = status;
}
}
_serverStatus = newServerStatus;
// just leave removed servers there
// TODO
_currentServer = _controller.GetCurrentConfiguration().configs[0];
ChooseNewServer();
}
public Server GetAServer(IStrategyCallerType type, System.Net.IPEndPoint localIPEndPoint)
{
// TODO don't choose new server too frequently
ChooseNewServer();
return _currentServer;
}
/**
* 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()
{
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 / 2) +
-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;
Logging.Debug(String.Format("choosing server: {0}", _currentServer.FriendlyName()));
}
}
public void UpdateLatency(Model.Server server, TimeSpan latency)
{
Logging.Debug(String.Format("latency: {0} {1}", server.FriendlyName(), latency));
@@ -87,6 +130,7 @@ namespace Shadowsocks.Controller.Strategy
if (_serverStatus.TryGetValue(server, out status))
{
status.latency = latency;
status.lastTimeDetectLatency = DateTime.Now;
}
}


Loading…
Cancel
Save