Akka.NET 在 Linux 和 Windows 之间远程
Akka.NET Remote between Linux and Windows
我有一个分布式演员系统,一些在 Windows 上,一些在 Linux 机器上。有时一个演员可能需要联系其他演员并进行一些交流。当然,也有其中一个在Windows系统上,另一个在Linux系统上的情况。
Actor 通过 ActorSelection 相互连接。问题是,当 Windows 演员试图与 Linux 演员交流时,一切正常。但是当 Linux actor 发起通信时,ActorSelection.ResolveOne 失败。
我在这里做了一个小样本:
static void Main(string[] args)
{
ActorSystem system = ActorSystem.Create("TestSystem");
system.ActorOf(Props.Create(() => new ConnectActor()), "test");
while (true)
{
var address = Console.ReadLine();
if (string.IsNullOrEmpty(address))
{
system.Terminate();
return;
}
var remoteAddress = $"akka.tcp://{system.Name}@{address}/user/test";
try
{
var actor = system.ActorSelection(remoteAddress).ResolveOne(TimeSpan.FromMilliseconds(5000)).Result;
Console.WriteLine("Resolved: " + actor.Path);
}
catch (Exception ex)
{
Console.WriteLine("Failed: " + ex.Message);
}
}
}
app.config中的配置如下:
akka {
loggers = ["Akka.Logger.NLog.NLogLogger, Akka.Logger.NLog"]
suppress-json-serializer-warning = on
loglevel = "DEBUG"
log-config-on-start = on
actor {
provider = "Akka.Remote.RemoteActorRefProvider, Akka.Remote"
debug {
receive = on
autoreceive = on
lifecycle = on
event-stream = on
unhandled = on
}
}
remote {
log-remote-lifecycle-events = DEBUG
log-received-messages = on
helios.tcp {
transport-class = "Akka.Remote.Transport.Helios.HeliosTcpTransport, Akka.Remote"
transport-protocol = tcp
applied-adapters = []
port = 9000
hostname = "0.0.0.0"
public-hostname = "192.168.0.251" // This is different for different hosts, of course
}
}
}
public-主机名是public唯一可用的 ip 地址。
所以,这里是案例:
- 当 运行 Windows/Windows 时,两个实例相互看到(我给他们远程地址 - 他们输出 "Resolved ")
- 当运行Windows/Linux时,将linuxactor地址给windowsactor,输出"Resolved"。所以 windows 连接 linux 没有问题。之后将 windows actor 的地址提供给 linux actor 也会给出 "Resolved" - 我想,连接已经建立并且没有真正的握手通过
- 但是当 运行 Windiws/Linux 并将 windows 演员的地址给 linux 演员时,它会给出 "Failed"。没有关于任何错误或丢包的消息。日志末尾有以下内容:
Akka.Remote.Transport.AkkaProtocolManager|now supervising akka://TestSystem/system/transports/akkaprotocolmanager.tcp.0/akkaProtocol-tcp%3A%2F%2FTestSystem%40%5B%3A%3Affff%3A192.168.0.252%5D%3A36983-1||||
13:20:08.3766|DEBUGAkka.Remote.Transport.ProtocolStateActor|Started (Akka.Remote.Transport.ProtocolStateActor)||||
13:20:08.3922|DEBUG|Akka.Remote.Transport.ProtocolStateActor|Stopped||||
此处描述了类似日志的问题:
原因是系统协议不兼容。这是同一个问题吗?正如我从 Akka.NET 文档和发行说明中获得的那样,它具有完整的 linux 支持...
那么,我是不是在配置中遗漏了什么?任何人都可以使此示例与 Linux -> Windows 连接一起使用吗?
这里的问题似乎是 Mono 出于某种原因在其绑定地址中使用映射到 IPV4 的 IPV6 地址。
akka://TestSystem/system/transports/akkaprotocolmanager.tcp.0/akkaProtocol-tcp%3A%2F%2FTestSystem%40%5B%3A%3Affff%3A192.168.0.252%5D%3A36983-1
如果你解码这个 URL 会被翻译成
akkaProtocol-tcp://TestSystem@[::ffff:192.168.0.252]:36983-
所以我认为这里发生的事情是出站地址 Helios 应该从中解析,但在 Linux 端被搞砸了,所以它试图连接到一个格式错误的地址与 Windows 收听的相同。我怀疑演员选择 URI 解析代码中特定于平台的内容不正确。
我在这里提交了一个错误:https://github.com/akkadotnet/akka.net/issues/2254
我有一个分布式演员系统,一些在 Windows 上,一些在 Linux 机器上。有时一个演员可能需要联系其他演员并进行一些交流。当然,也有其中一个在Windows系统上,另一个在Linux系统上的情况。
Actor 通过 ActorSelection 相互连接。问题是,当 Windows 演员试图与 Linux 演员交流时,一切正常。但是当 Linux actor 发起通信时,ActorSelection.ResolveOne 失败。
我在这里做了一个小样本:
static void Main(string[] args)
{
ActorSystem system = ActorSystem.Create("TestSystem");
system.ActorOf(Props.Create(() => new ConnectActor()), "test");
while (true)
{
var address = Console.ReadLine();
if (string.IsNullOrEmpty(address))
{
system.Terminate();
return;
}
var remoteAddress = $"akka.tcp://{system.Name}@{address}/user/test";
try
{
var actor = system.ActorSelection(remoteAddress).ResolveOne(TimeSpan.FromMilliseconds(5000)).Result;
Console.WriteLine("Resolved: " + actor.Path);
}
catch (Exception ex)
{
Console.WriteLine("Failed: " + ex.Message);
}
}
}
app.config中的配置如下:
akka {
loggers = ["Akka.Logger.NLog.NLogLogger, Akka.Logger.NLog"]
suppress-json-serializer-warning = on
loglevel = "DEBUG"
log-config-on-start = on
actor {
provider = "Akka.Remote.RemoteActorRefProvider, Akka.Remote"
debug {
receive = on
autoreceive = on
lifecycle = on
event-stream = on
unhandled = on
}
}
remote {
log-remote-lifecycle-events = DEBUG
log-received-messages = on
helios.tcp {
transport-class = "Akka.Remote.Transport.Helios.HeliosTcpTransport, Akka.Remote"
transport-protocol = tcp
applied-adapters = []
port = 9000
hostname = "0.0.0.0"
public-hostname = "192.168.0.251" // This is different for different hosts, of course
}
}
}
public-主机名是public唯一可用的 ip 地址。
所以,这里是案例:
- 当 运行 Windows/Windows 时,两个实例相互看到(我给他们远程地址 - 他们输出 "Resolved ")
- 当运行Windows/Linux时,将linuxactor地址给windowsactor,输出"Resolved"。所以 windows 连接 linux 没有问题。之后将 windows actor 的地址提供给 linux actor 也会给出 "Resolved" - 我想,连接已经建立并且没有真正的握手通过
- 但是当 运行 Windiws/Linux 并将 windows 演员的地址给 linux 演员时,它会给出 "Failed"。没有关于任何错误或丢包的消息。日志末尾有以下内容:
Akka.Remote.Transport.AkkaProtocolManager|now supervising akka://TestSystem/system/transports/akkaprotocolmanager.tcp.0/akkaProtocol-tcp%3A%2F%2FTestSystem%40%5B%3A%3Affff%3A192.168.0.252%5D%3A36983-1|||| 13:20:08.3766|DEBUGAkka.Remote.Transport.ProtocolStateActor|Started (Akka.Remote.Transport.ProtocolStateActor)|||| 13:20:08.3922|DEBUG|Akka.Remote.Transport.ProtocolStateActor|Stopped||||
此处描述了类似日志的问题:
那么,我是不是在配置中遗漏了什么?任何人都可以使此示例与 Linux -> Windows 连接一起使用吗?
这里的问题似乎是 Mono 出于某种原因在其绑定地址中使用映射到 IPV4 的 IPV6 地址。
akka://TestSystem/system/transports/akkaprotocolmanager.tcp.0/akkaProtocol-tcp%3A%2F%2FTestSystem%40%5B%3A%3Affff%3A192.168.0.252%5D%3A36983-1
如果你解码这个 URL 会被翻译成
akkaProtocol-tcp://TestSystem@[::ffff:192.168.0.252]:36983-
所以我认为这里发生的事情是出站地址 Helios 应该从中解析,但在 Linux 端被搞砸了,所以它试图连接到一个格式错误的地址与 Windows 收听的相同。我怀疑演员选择 URI 解析代码中特定于平台的内容不正确。
我在这里提交了一个错误:https://github.com/akkadotnet/akka.net/issues/2254