Added Regions to Load Balancer Setup.
This commit is contained in:
parent
36362af6ba
commit
14ea6243d0
12 changed files with 171 additions and 43 deletions
|
|
@ -8,10 +8,10 @@ namespace LightReflectiveMirror.LoadBalancing
|
|||
[Serializable]
|
||||
public struct RelayServerInfo
|
||||
{
|
||||
public int ConnectedClients;
|
||||
public int RoomCount;
|
||||
public int PublicRoomCount;
|
||||
public TimeSpan Uptime;
|
||||
public int connectedClients;
|
||||
public int roomCount;
|
||||
public int publicRoomCount;
|
||||
public TimeSpan uptime;
|
||||
|
||||
[JsonIgnore]
|
||||
public List<Room> serversConnectedToRelay;
|
||||
|
|
@ -20,21 +20,22 @@ namespace LightReflectiveMirror.LoadBalancing
|
|||
[Serializable]
|
||||
internal struct LoadBalancerStats
|
||||
{
|
||||
public int NodeCount;
|
||||
public TimeSpan Uptime;
|
||||
public int nodeCount;
|
||||
public TimeSpan uptime;
|
||||
public long CCU;
|
||||
public long TotalServerCount;
|
||||
public long totalServerCount;
|
||||
}
|
||||
|
||||
// container for relay address info
|
||||
[JsonObject(MemberSerialization.OptOut)]
|
||||
public struct RelayAddress
|
||||
{
|
||||
public ushort Port;
|
||||
public ushort EndpointPort;
|
||||
public string Address;
|
||||
public ushort port;
|
||||
public ushort endpointPort;
|
||||
public string address;
|
||||
public LRMRegions serverRegion;
|
||||
[JsonIgnore]
|
||||
public string EndpointAddress;
|
||||
public string endpointAddress;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
|
|
@ -50,4 +51,6 @@ namespace LightReflectiveMirror.LoadBalancing
|
|||
|
||||
public RelayAddress relayInfo;
|
||||
}
|
||||
|
||||
public enum LRMRegions { Any, NorthAmerica, SouthAmerica, Europe, Asia, Africa, Oceania }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,16 +18,30 @@ namespace LightReflectiveMirror.LoadBalancing
|
|||
[RestResource]
|
||||
public class Endpoint
|
||||
{
|
||||
public static string cachedServerList = "[]";
|
||||
public static string allCachedServers = "[]";
|
||||
public static string NorthAmericaCachedServers = "[]";
|
||||
public static string SouthAmericaCachedServers = "[]";
|
||||
public static string EuropeCachedServers = "[]";
|
||||
public static string AsiaCachedServers = "[]";
|
||||
public static string AfricaCachedServers = "[]";
|
||||
public static string OceaniaCachedServers = "[]";
|
||||
|
||||
private static List<Room> northAmericaServers = new();
|
||||
private static List<Room> southAmericaServers = new();
|
||||
private static List<Room> europeServers = new();
|
||||
private static List<Room> africaServers = new();
|
||||
private static List<Room> asiaServers = new();
|
||||
private static List<Room> oceaniaServers = new();
|
||||
private static List<Room> allServers = new();
|
||||
|
||||
private LoadBalancerStats _stats
|
||||
{
|
||||
get => new()
|
||||
{
|
||||
NodeCount = Program.instance.availableRelayServers.Count,
|
||||
Uptime = DateTime.Now - Program.startupTime,
|
||||
nodeCount = Program.instance.availableRelayServers.Count,
|
||||
uptime = DateTime.Now - Program.startupTime,
|
||||
CCU = Program.instance.GetTotalCCU(),
|
||||
TotalServerCount = Program.instance.GetTotalServers(),
|
||||
totalServerCount = Program.instance.GetTotalServers(),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -45,12 +59,14 @@ namespace LightReflectiveMirror.LoadBalancing
|
|||
string endpointPort = req.Headers["x-EndpointPort"];
|
||||
string gamePort = req.Headers["x-GamePort"];
|
||||
string publicIP = req.Headers["x-PIP"];
|
||||
string region = req.Headers["x-Region"];
|
||||
int regionId = 1;
|
||||
|
||||
string address = context.Request.RemoteEndPoint.Address.ToString();
|
||||
Logger.WriteLogMessage("Received auth req [" + receivedAuthKey + "] == [" + Program.conf.AuthKey + "]");
|
||||
|
||||
// if server is authenticated
|
||||
if (receivedAuthKey != null && address != null && endpointPort != null && gamePort != null && receivedAuthKey == Program.conf.AuthKey)
|
||||
if (receivedAuthKey != null && region != null && int.TryParse(region, out regionId) && address != null && endpointPort != null && gamePort != null && receivedAuthKey == Program.conf.AuthKey)
|
||||
{
|
||||
Logger.WriteLogMessage($"Server accepted: {address}:{gamePort}");
|
||||
|
||||
|
|
@ -58,7 +74,7 @@ namespace LightReflectiveMirror.LoadBalancing
|
|||
{
|
||||
var _gamePort = Convert.ToUInt16(gamePort);
|
||||
var _endpointPort = Convert.ToUInt16(endpointPort);
|
||||
await Program.instance.AddServer(address, _gamePort, _endpointPort, publicIP);
|
||||
await Program.instance.AddServer(address, _gamePort, _endpointPort, publicIP, regionId);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
|
@ -82,20 +98,66 @@ namespace LightReflectiveMirror.LoadBalancing
|
|||
// Dont allow unauthorizated access waste computing resources.
|
||||
string auth = context.Request.Headers["Authorization"];
|
||||
|
||||
if(!string.IsNullOrEmpty(auth) && auth == Program.conf.AuthKey)
|
||||
if (!string.IsNullOrEmpty(auth) && auth == Program.conf.AuthKey)
|
||||
{
|
||||
var relays = Program.instance.availableRelayServers.ToList();
|
||||
List<Room> masterList = new();
|
||||
ClearAllServersLists();
|
||||
List<Room> requestedRooms;
|
||||
|
||||
for(int i = 0; i < relays.Count; i++)
|
||||
for (int i = 0; i < relays.Count; i++)
|
||||
{
|
||||
masterList.AddRange(await Program.instance.RequestServerListFromNode(relays[i].Key.Address, relays[i].Key.EndpointPort));
|
||||
requestedRooms = await Program.instance.RequestServerListFromNode(relays[i].Key.address, relays[i].Key.endpointPort);
|
||||
allServers.AddRange(requestedRooms);
|
||||
|
||||
switch (relays[i].Key.serverRegion)
|
||||
{
|
||||
case (LRMRegions.NorthAmerica):
|
||||
northAmericaServers.AddRange(requestedRooms);
|
||||
break;
|
||||
case (LRMRegions.SouthAmerica):
|
||||
southAmericaServers.AddRange(requestedRooms);
|
||||
break;
|
||||
case (LRMRegions.Europe):
|
||||
europeServers.AddRange(requestedRooms);
|
||||
break;
|
||||
case (LRMRegions.Africa):
|
||||
africaServers.AddRange(requestedRooms);
|
||||
break;
|
||||
case (LRMRegions.Asia):
|
||||
asiaServers.AddRange(requestedRooms);
|
||||
break;
|
||||
case (LRMRegions.Oceania):
|
||||
oceaniaServers.AddRange(requestedRooms);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cachedServerList = JsonConvert.SerializeObject(masterList);
|
||||
CacheAllServers();
|
||||
}
|
||||
}
|
||||
|
||||
void CacheAllServers()
|
||||
{
|
||||
allCachedServers = JsonConvert.SerializeObject(allServers);
|
||||
NorthAmericaCachedServers = JsonConvert.SerializeObject(northAmericaServers);
|
||||
SouthAmericaCachedServers = JsonConvert.SerializeObject(southAmericaServers);
|
||||
EuropeCachedServers = JsonConvert.SerializeObject(europeServers);
|
||||
AsiaCachedServers = JsonConvert.SerializeObject(asiaServers);
|
||||
AfricaCachedServers = JsonConvert.SerializeObject(africaServers);
|
||||
OceaniaCachedServers = JsonConvert.SerializeObject(oceaniaServers);
|
||||
}
|
||||
|
||||
void ClearAllServersLists()
|
||||
{
|
||||
northAmericaServers.Clear();
|
||||
southAmericaServers.Clear();
|
||||
europeServers.Clear();
|
||||
asiaServers.Clear();
|
||||
africaServers.Clear();
|
||||
oceaniaServers.Clear();
|
||||
allServers.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hooks into from unity side, client will call this to
|
||||
/// find the least populated server to join
|
||||
|
|
@ -119,7 +181,7 @@ namespace LightReflectiveMirror.LoadBalancing
|
|||
|
||||
for (int i = 0; i < servers.Count; i++)
|
||||
{
|
||||
if (servers[i].Value.ConnectedClients < lowest.Value.ConnectedClients)
|
||||
if (servers[i].Value.connectedClients < lowest.Value.connectedClients)
|
||||
{
|
||||
lowest = servers[i];
|
||||
}
|
||||
|
|
@ -127,7 +189,7 @@ namespace LightReflectiveMirror.LoadBalancing
|
|||
|
||||
// respond with the server ip
|
||||
// if the string is still dummy then theres no servers
|
||||
if (lowest.Key.Address != "Dummy")
|
||||
if (lowest.Key.address != "Dummy")
|
||||
{
|
||||
await context.Response.SendResponseAsync(JsonConvert.SerializeObject(lowest.Key));
|
||||
}
|
||||
|
|
@ -145,7 +207,40 @@ namespace LightReflectiveMirror.LoadBalancing
|
|||
[RestRoute("Get", "/api/masterlist/")]
|
||||
public async Task GetMasterServerList(IHttpContext context)
|
||||
{
|
||||
await context.Response.SendResponseAsync(cachedServerList);
|
||||
string region = context.Request.Headers["x-Region"];
|
||||
|
||||
if(int.TryParse(region, out int regionID))
|
||||
{
|
||||
switch ((LRMRegions)regionID)
|
||||
{
|
||||
case LRMRegions.Any:
|
||||
await context.Response.SendResponseAsync(allCachedServers);
|
||||
break;
|
||||
case LRMRegions.NorthAmerica:
|
||||
await context.Response.SendResponseAsync(NorthAmericaCachedServers);
|
||||
break;
|
||||
case LRMRegions.SouthAmerica:
|
||||
await context.Response.SendResponseAsync(SouthAmericaCachedServers);
|
||||
break;
|
||||
case LRMRegions.Europe:
|
||||
await context.Response.SendResponseAsync(EuropeCachedServers);
|
||||
break;
|
||||
case LRMRegions.Africa:
|
||||
await context.Response.SendResponseAsync(AfricaCachedServers);
|
||||
break;
|
||||
case LRMRegions.Asia:
|
||||
await context.Response.SendResponseAsync(AsiaCachedServers);
|
||||
break;
|
||||
case LRMRegions.Oceania:
|
||||
await context.Response.SendResponseAsync(OceaniaCachedServers);
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// They didnt submit a region header, just give them all servers as they probably are viewing in browser.
|
||||
await context.Response.SendResponseAsync(allCachedServers);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -218,7 +313,7 @@ namespace LightReflectiveMirror.LoadBalancing
|
|||
|
||||
bool hasLocal = false;
|
||||
|
||||
for(int i = 0; i < bindableIPv4Addresses.Count; i++)
|
||||
for (int i = 0; i < bindableIPv4Addresses.Count; i++)
|
||||
{
|
||||
if (bindableIPv4Addresses[i] == "127.0.0.1")
|
||||
hasLocal = true;
|
||||
|
|
@ -233,4 +328,4 @@ namespace LightReflectiveMirror.LoadBalancing
|
|||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -71,9 +71,9 @@ namespace LightReflectiveMirror.LoadBalancing
|
|||
/// <param name="endpointPort"></param>
|
||||
/// <param name="publicIP"></param>
|
||||
/// <returns></returns>
|
||||
public async Task AddServer(string serverIP, ushort port, ushort endpointPort, string publicIP)
|
||||
public async Task AddServer(string serverIP, ushort port, ushort endpointPort, string publicIP, int regionId)
|
||||
{
|
||||
var relayAddr = new RelayAddress { Port = port, EndpointPort = endpointPort, Address = publicIP, EndpointAddress = serverIP };
|
||||
var relayAddr = new RelayAddress { port = port, endpointPort = endpointPort, address = publicIP, endpointAddress = serverIP.Trim(), serverRegion = (LRMRegions)regionId };
|
||||
|
||||
if (availableRelayServers.ContainsKey(relayAddr))
|
||||
{
|
||||
|
|
@ -187,13 +187,14 @@ namespace LightReflectiveMirror.LoadBalancing
|
|||
|
||||
for (int i = 0; i < keys.Count; i++)
|
||||
{
|
||||
if(!await HealthCheckNode(keys[i].EndpointAddress, keys[i].EndpointPort))
|
||||
if(!await HealthCheckNode(keys[i].endpointAddress, keys[i].endpointPort))
|
||||
{
|
||||
Logger.ForceLogMessage($"Server {keys[i].Address}:{keys[i].Port} failed a health check, removing from load balancer.", ConsoleColor.Red);
|
||||
Logger.ForceLogMessage($"Server {keys[i].address}:{keys[i].port} failed a health check, removing from load balancer.", ConsoleColor.Red);
|
||||
availableRelayServers.Remove(keys[i]);
|
||||
}
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
await Task.Delay(_pingDelay);
|
||||
}
|
||||
}
|
||||
|
|
@ -229,5 +230,4 @@ namespace LightReflectiveMirror.LoadBalancing
|
|||
Logger.ForceLogMessage(load, ConsoleColor.Cyan);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,5 +35,6 @@ namespace LightReflectiveMirror
|
|||
public string LoadBalancerAuthKey = "AuthKey";
|
||||
public string LoadBalancerAddress = "127.0.0.1";
|
||||
public ushort LoadBalancerPort = 7070;
|
||||
public LRMRegions LoadBalancerRegion = LRMRegions.NorthAmerica;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,4 +22,19 @@
|
|||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Properties\Resources.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -225,13 +225,14 @@ namespace LightReflectiveMirror
|
|||
|
||||
var uri = new Uri($"http://{conf.LoadBalancerAddress}:{conf.LoadBalancerPort}/api/auth");
|
||||
string endpointPort = conf.EndpointPort.ToString();
|
||||
string gamePort = 7777.ToString();
|
||||
string gamePort = "7777";
|
||||
HttpWebRequest authReq = (HttpWebRequest)WebRequest.Create(uri);
|
||||
|
||||
authReq.Headers.Add("Authorization", conf.LoadBalancerAuthKey);
|
||||
authReq.Headers.Add("x-EndpointPort", endpointPort);
|
||||
authReq.Headers.Add("x-GamePort", gamePort);
|
||||
authReq.Headers.Add("x-PIP", publicIP); // Public IP
|
||||
authReq.Headers.Add("x-Region", ((int)conf.LoadBalancerRegion).ToString());
|
||||
|
||||
var res = await authReq.GetResponseAsync();
|
||||
|
||||
|
|
|
|||
|
|
@ -34,4 +34,6 @@ namespace LightReflectiveMirror
|
|||
|
||||
private readonly string CONFIG_PATH = System.Environment.GetEnvironmentVariable("LRM_CONFIG_PATH") ?? "config.json";
|
||||
}
|
||||
|
||||
public enum LRMRegions { Any, NorthAmerica, SouthAmerica, Europe, Asia, Africa, Oceania }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,10 +132,10 @@ namespace LightReflectiveMirror
|
|||
serverData = serverData,
|
||||
clients = new List<int>(),
|
||||
|
||||
// hard coded for now REMEMBER TO UN-HARDCODE RETARD
|
||||
// hard coded for now REMEMBER TO UN-HARDCODE
|
||||
// this is needed for load balancer to know which server this room
|
||||
// belongs to
|
||||
relayInfo = new RelayAddress { Address = Program.publicIP, Port = 7777, EndpointPort = Program.conf.EndpointPort },
|
||||
relayInfo = new RelayAddress { address = Program.publicIP, port = 7777, endpointPort = Program.conf.EndpointPort },
|
||||
|
||||
serverId = GetRandomServerID(),
|
||||
hostIP = hostIP,
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ namespace LightReflectiveMirror
|
|||
[Serializable]
|
||||
public struct RelayAddress
|
||||
{
|
||||
public ushort Port;
|
||||
public ushort EndpointPort;
|
||||
public string Address;
|
||||
public ushort port;
|
||||
public ushort endpointPort;
|
||||
public string address;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -152,22 +152,23 @@ namespace LightReflectiveMirror
|
|||
}
|
||||
}
|
||||
}
|
||||
else if(lrm.NATPunchtroughPort < 0)
|
||||
else if (lrm.NATPunchtroughPort < 0)
|
||||
{
|
||||
// NAT Punchthrough configuration.
|
||||
EditorGUILayout.HelpBox("Do you wish to use NAT Punchthrough? This can reduce load by up to 80% on your LRM nodes, but exposes players IP's to other players.", MessageType.None);
|
||||
|
||||
if(GUILayout.Button("Use NAT Punchthrough"))
|
||||
if (GUILayout.Button("Use NAT Punchthrough"))
|
||||
{
|
||||
lrm.NATPunchtroughPort = 1;
|
||||
lrm.useNATPunch = true;
|
||||
lrm.gameObject.AddComponent<LRMDirectConnectModule>();
|
||||
}
|
||||
|
||||
if(GUILayout.Button("Do NOT use NAT Punchthrough"))
|
||||
if (GUILayout.Button("Do NOT use NAT Punchthrough"))
|
||||
lrm.NATPunchtroughPort = 1;
|
||||
|
||||
}else if(directModule != null && directModule.directConnectTransport == null)
|
||||
}
|
||||
else if (directModule != null && directModule.directConnectTransport == null)
|
||||
{
|
||||
// NAT Punchthrough setup.
|
||||
EditorGUILayout.HelpBox("To use direct connecting, we need a transport to communicate with the other clients. Please select a transport to use.", MessageType.None);
|
||||
|
|
@ -217,7 +218,7 @@ namespace LightReflectiveMirror
|
|||
break;
|
||||
case 1:
|
||||
// NAT punch tab.
|
||||
if(directModule == null)
|
||||
if (directModule == null)
|
||||
{
|
||||
EditorGUILayout.HelpBox("If you wish to use NAT punch, you will need to add a \"Direct Connect Module\" to this gameobject.", MessageType.Info);
|
||||
}
|
||||
|
|
@ -230,8 +231,14 @@ namespace LightReflectiveMirror
|
|||
case 2:
|
||||
// Load balancer tab
|
||||
lrm.useLoadBalancer = EditorGUILayout.Toggle("Use Load Balancer", lrm.useLoadBalancer);
|
||||
if (!lrm.useLoadBalancer)
|
||||
GUI.enabled = false;
|
||||
lrm.loadBalancerAddress = EditorGUILayout.TextField("Load Balancer Address", lrm.loadBalancerAddress);
|
||||
lrm.loadBalancerPort = (ushort)Mathf.Clamp(EditorGUILayout.IntField("Load Balancer Port", lrm.loadBalancerPort), ushort.MinValue, ushort.MaxValue);
|
||||
lrm.region = (LRMRegions)EditorGUILayout.EnumPopup("Node Region", lrm.region);
|
||||
if (!lrm.useLoadBalancer)
|
||||
GUI.enabled = true;
|
||||
|
||||
break;
|
||||
case 3:
|
||||
// Other tab...
|
||||
|
|
|
|||
|
|
@ -148,6 +148,7 @@ namespace LightReflectiveMirror
|
|||
|
||||
using (UnityWebRequest webRequest = UnityWebRequest.Get(uri))
|
||||
{
|
||||
webRequest.SetRequestHeader("x-Region", ((int)region).ToString());
|
||||
// Request and wait for the desired page.
|
||||
yield return webRequest.SendWebRequest();
|
||||
var result = webRequest.downloadHandler.text;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ namespace LightReflectiveMirror
|
|||
|
||||
private LRMDirectConnectModule _directConnectModule;
|
||||
|
||||
public LRMRegions region = LRMRegions.NorthAmerica;
|
||||
private byte[] _clientSendBuffer;
|
||||
private bool _connectedToRelay = false;
|
||||
private bool _isClient = false;
|
||||
|
|
@ -61,4 +62,6 @@ namespace LightReflectiveMirror
|
|||
private BiDictionary<int, int> _connectedRelayClients = new BiDictionary<int, int>();
|
||||
private BiDictionary<int, int> _connectedDirectClients = new BiDictionary<int, int>();
|
||||
}
|
||||
|
||||
public enum LRMRegions { Any, NorthAmerica, SouthAmerica, Europe, Asia, Africa, Oceania }
|
||||
}
|
||||
Loading…
Reference in a new issue