如何使用 F# 实现 Props.Create
How to implement Props.Create using F#
我试图将工作的 C# 示例移植到 OOP version of F#。
远程参与者(在单独的进程上)没有接收消息。
我收到以下错误:
[ERROR][3/23/2017 4:39:10 PM][Thread 0008][[akka://system2/system/endpointManage
r/reliableEndpointWriter-akka.tcp%3A%2F%2Fsystem1%40localhost%3A8090-1/endpointW
riter#1919547364]] AssociationError [akka.tcp://system2@localhost:8080] <- akka.
tcp://system1@localhost:8090: Error [Object reference not set to an instance of
an object.] [ at Akka.Serialization.Serialization.FindSerializerForType(Type o
bjectType)
at Akka.Remote.Serialization.DaemonMsgCreateSerializer.GetArgs(DaemonMsgCreat
eData proto)
at Akka.Remote.Serialization.DaemonMsgCreateSerializer.FromBinary(Byte[] byte
s, Type type)
at Akka.Serialization.Serialization.Deserialize(Byte[] bytes, Int32 serialize
rId, String manifest)
这是可用的 C# 版本:
using (var system = ActorSystem.Create("system1", config))
{
var reply = system.ActorOf<ReplyActor>("reply");
//create a remote deployed actor
var remote1 = system.ActorOf(Props.Create(() => new SomeActor()).WithRouter(FromConfig.Instance), "remoteactor1");
var remote2 = system.ActorOf(Props.Create(() => new SomeActor()).WithRouter(FromConfig.Instance), "remoteactor2");
var remote3 = system.ActorOf(Props.Create(() => new SomeActor()).WithRouter(FromConfig.Instance), "remoteactor3");
var hashGroup = system.ActorOf(Props.Empty.WithRouter(new ConsistentHashingGroup(config)));
Task.Delay(500).Wait();
var routee1 = Routee.FromActorRef(remote1);
hashGroup.Tell(new AddRoutee(routee1));
var routee2 = Routee.FromActorRef(remote2);
hashGroup.Tell(new AddRoutee(routee2));
var routee3 = Routee.FromActorRef(remote3);
hashGroup.Tell(new AddRoutee(routee3));
Task.Delay(500).Wait();
for (var i = 0; i < 5; i++)
{
for (var j = 0; j < 7; j++)
{
var message = new SomeMessage(j, $"remote message: {j}");
hashGroup.Tell(message, reply);
}
}
Console.ReadLine();
}
这是使用 OOP 到 F# 的端口:
use system = ActorSystem.Create("system1", config)
let reply = system.ActorOf<ReplyActor>("reply")
let props1 = Props.Create(fun () -> SomeActor() :> obj)
let props2 = Props.Create(fun () -> SomeActor() :> obj)
let props3 = Props.Create(fun () -> SomeActor() :> obj)
let remote1 = system.ActorOf(props1.WithRouter(FromConfig.Instance), "remoteactor1")
let remote2 = system.ActorOf(props2.WithRouter(FromConfig.Instance), "remoteactor2")
let remote3 = system.ActorOf(props3.WithRouter(FromConfig.Instance), "remoteactor3")
let hashGroup = system.ActorOf(Props.Empty.WithRouter(ConsistentHashingGroup(config)))
Task.Delay(500).Wait();
let routee1 = Routee.FromActorRef(remote1);
hashGroup.Tell(new AddRoutee(routee1));
let routee2 = Routee.FromActorRef(remote2);
hashGroup.Tell(new AddRoutee(routee2));
let routee3 = Routee.FromActorRef(remote3);
hashGroup.Tell(new AddRoutee(routee3));
Task.Delay(500).Wait();
for i = 0 to 5 do
for j = 0 to 7 do
let message = new HashMessage(j, sprintf "remote message: %i" j);
hashGroup.Tell(message, reply);
Console.ReadLine() |> ignore
问题:
我是否应该在调用 Props.Create[= 时将 SomeActor 向上转换为 object 类型55=] 方法?
let props1 = Props.Create(fun () -> SomeActor() :> obj)
let props2 = Props.Create(fun () -> SomeActor() :> obj)
let props3 = Props.Create(fun () -> SomeActor() :> obj)
上面的代码是我所知道的唯一区别。
唯一的区别是 tcp 路径。
C# 的 TCP:
remote {
dot-netty.tcp {
port = 8090
hostname = localhost
}
F# 的 TCP:
remote {
helios.tcp {
port = 8090
hostname = localhost
}
Props对象是目标actor创建过程的描述符。此外,它必须是可序列化的,因为有时它可能包含在通过网络传递的消息中。
为了以这种方式工作,Props 在内部以(actor-type,actor-constructor-arguments)的形式描述了 actor 构造。 Props.Create(() => new Actor())
在这里只是一个帮手:它实际上做的是将构造函数表达式解构为带参数的类型信息。这就是为什么它只适用于 new Actor()
表达式。
您的 F# 代码存在的问题是您将 actor 创建定义为 F# 函数,道具解构器不知道如何处理。您可能仍想使用以下方法创建您的演员:
Props.Create(typeof<Actor>, [| arg1; arg2 |])
但是你需要自己保持构造函数参数的正确性。您也可以使用 Akkling 及其 typed version of props.
我试图将工作的 C# 示例移植到 OOP version of F#。
远程参与者(在单独的进程上)没有接收消息。
我收到以下错误:
[ERROR][3/23/2017 4:39:10 PM][Thread 0008][[akka://system2/system/endpointManage
r/reliableEndpointWriter-akka.tcp%3A%2F%2Fsystem1%40localhost%3A8090-1/endpointW
riter#1919547364]] AssociationError [akka.tcp://system2@localhost:8080] <- akka.
tcp://system1@localhost:8090: Error [Object reference not set to an instance of
an object.] [ at Akka.Serialization.Serialization.FindSerializerForType(Type o
bjectType)
at Akka.Remote.Serialization.DaemonMsgCreateSerializer.GetArgs(DaemonMsgCreat
eData proto)
at Akka.Remote.Serialization.DaemonMsgCreateSerializer.FromBinary(Byte[] byte
s, Type type)
at Akka.Serialization.Serialization.Deserialize(Byte[] bytes, Int32 serialize
rId, String manifest)
这是可用的 C# 版本:
using (var system = ActorSystem.Create("system1", config))
{
var reply = system.ActorOf<ReplyActor>("reply");
//create a remote deployed actor
var remote1 = system.ActorOf(Props.Create(() => new SomeActor()).WithRouter(FromConfig.Instance), "remoteactor1");
var remote2 = system.ActorOf(Props.Create(() => new SomeActor()).WithRouter(FromConfig.Instance), "remoteactor2");
var remote3 = system.ActorOf(Props.Create(() => new SomeActor()).WithRouter(FromConfig.Instance), "remoteactor3");
var hashGroup = system.ActorOf(Props.Empty.WithRouter(new ConsistentHashingGroup(config)));
Task.Delay(500).Wait();
var routee1 = Routee.FromActorRef(remote1);
hashGroup.Tell(new AddRoutee(routee1));
var routee2 = Routee.FromActorRef(remote2);
hashGroup.Tell(new AddRoutee(routee2));
var routee3 = Routee.FromActorRef(remote3);
hashGroup.Tell(new AddRoutee(routee3));
Task.Delay(500).Wait();
for (var i = 0; i < 5; i++)
{
for (var j = 0; j < 7; j++)
{
var message = new SomeMessage(j, $"remote message: {j}");
hashGroup.Tell(message, reply);
}
}
Console.ReadLine();
}
这是使用 OOP 到 F# 的端口:
use system = ActorSystem.Create("system1", config)
let reply = system.ActorOf<ReplyActor>("reply")
let props1 = Props.Create(fun () -> SomeActor() :> obj)
let props2 = Props.Create(fun () -> SomeActor() :> obj)
let props3 = Props.Create(fun () -> SomeActor() :> obj)
let remote1 = system.ActorOf(props1.WithRouter(FromConfig.Instance), "remoteactor1")
let remote2 = system.ActorOf(props2.WithRouter(FromConfig.Instance), "remoteactor2")
let remote3 = system.ActorOf(props3.WithRouter(FromConfig.Instance), "remoteactor3")
let hashGroup = system.ActorOf(Props.Empty.WithRouter(ConsistentHashingGroup(config)))
Task.Delay(500).Wait();
let routee1 = Routee.FromActorRef(remote1);
hashGroup.Tell(new AddRoutee(routee1));
let routee2 = Routee.FromActorRef(remote2);
hashGroup.Tell(new AddRoutee(routee2));
let routee3 = Routee.FromActorRef(remote3);
hashGroup.Tell(new AddRoutee(routee3));
Task.Delay(500).Wait();
for i = 0 to 5 do
for j = 0 to 7 do
let message = new HashMessage(j, sprintf "remote message: %i" j);
hashGroup.Tell(message, reply);
Console.ReadLine() |> ignore
问题:
我是否应该在调用 Props.Create[= 时将 SomeActor 向上转换为 object 类型55=] 方法?
let props1 = Props.Create(fun () -> SomeActor() :> obj)
let props2 = Props.Create(fun () -> SomeActor() :> obj)
let props3 = Props.Create(fun () -> SomeActor() :> obj)
上面的代码是我所知道的唯一区别。
唯一的区别是 tcp 路径。
C# 的 TCP:
remote {
dot-netty.tcp {
port = 8090
hostname = localhost
}
F# 的 TCP:
remote {
helios.tcp {
port = 8090
hostname = localhost
}
Props对象是目标actor创建过程的描述符。此外,它必须是可序列化的,因为有时它可能包含在通过网络传递的消息中。
为了以这种方式工作,Props 在内部以(actor-type,actor-constructor-arguments)的形式描述了 actor 构造。 Props.Create(() => new Actor())
在这里只是一个帮手:它实际上做的是将构造函数表达式解构为带参数的类型信息。这就是为什么它只适用于 new Actor()
表达式。
您的 F# 代码存在的问题是您将 actor 创建定义为 F# 函数,道具解构器不知道如何处理。您可能仍想使用以下方法创建您的演员:
Props.Create(typeof<Actor>, [| arg1; arg2 |])
但是你需要自己保持构造函数参数的正确性。您也可以使用 Akkling 及其 typed version of props.