You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When creating a cluster using Akka.NET to facilitiate real-time UI type applications it is extremely likely you will run into a situation where nodes running behind firewalls will break your cluster. This will exhibit strangly in that the cluster will typically successfully form (because you might have multiple nodes on the local subnet) but eventually 'intermittently' disassociate when a 'hidden' external node joins.
This occurs when nodes behind firewalls propogate through your cluster and 'visible nodes' attempt to communicate back to your 'hidden' nodes. Worse yet, Akka.NET errors are not always clear and while in hindsight this situation is obvious it is not necessarily intuitive when you run into it, particularly when you're new to the technology.
After some time learning to understand how Akka.NET works and finding a hole punching implementation that could be leveraged I am hoping to save other developers this headache.
public class PortBuster : IPortBuster
{
public static int[] DefaultPorts = new int[]
{
5283,
5284,
5285,
5286,
5287,
5288,
5289,
5290,
5291,
5292,
5293,
5294,
5295,
5296,
5297
};
public async Task<int> BustPortAsync()
{
int port = this.GetUnusedPort();
try
{
var discoverer = new NatDiscoverer();
var device = await discoverer.DiscoverDeviceAsync();
await device.CreatePortMapAsync(new Mapping(Open.Nat.Protocol.Tcp, port, port));
}
catch { }
return port;
}
public int GetUnusedPort()
{
string localIp = Networking.GetLocalIPAddress();
IPAddress localAddr = IPAddress.Parse(localIp);
int result = -1;
for (int i = 0; i < DefaultPorts.Length; i++)
{
try
{
using (Socket tempServer = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
{
tempServer.Bind(new IPEndPoint(localAddr, DefaultPorts[i]));
tempServer.Close();
result = DefaultPorts[i];
}
break;
}
catch
{
// Binding failed, port is in use, try next one
}
}
return result > -1 ? result : throw new OperationCanceledException("Could not find unused port.");
}
}
I then leverage the port created when I create my configuration with something like this.
int port = await this._portBuster.BustPortAsync();
var config = AkkaConfigManager.GetAkkaClientConfig(isSubnetDeployment,
port,
this._appSettings.Host,
this._appSettings.Port.Value,
this._appSettings.Roles);
The only other caveat I ran into was that I needed Open.NAT to run in a xamarin application and this required me recompiling the project in .NET standard as the nuget packages didnt work.
The text was updated successfully, but these errors were encountered:
MaximG1234
changed the title
Documentation should include info about NAT hole punching (Dissociation error).
Documentation should include info about TCP/NAT hole punching (Dissociation error).
Feb 5, 2020
When creating a cluster using Akka.NET to facilitiate real-time UI type applications it is extremely likely you will run into a situation where nodes running behind firewalls will break your cluster. This will exhibit strangly in that the cluster will typically successfully form (because you might have multiple nodes on the local subnet) but eventually 'intermittently' disassociate when a 'hidden' external node joins.
This occurs when nodes behind firewalls propogate through your cluster and 'visible nodes' attempt to communicate back to your 'hidden' nodes. Worse yet, Akka.NET errors are not always clear and while in hindsight this situation is obvious it is not necessarily intuitive when you run into it, particularly when you're new to the technology.
After some time learning to understand how Akka.NET works and finding a hole punching implementation that could be leveraged I am hoping to save other developers this headache.
I was able to find this stackoverflow question which basically provides a complete working solution using Open.NAT.
I ended up with a class that looks like this
I then leverage the port created when I create my configuration with something like this.
The only other caveat I ran into was that I needed Open.NAT to run in a xamarin application and this required me recompiling the project in .NET standard as the nuget packages didnt work.
The text was updated successfully, but these errors were encountered: