Akka.Remote F# 序列化仅适用于可区分联合的第一个字段
Akka.Remote F# Serialization works only on the first field of a discriminated union
为了将已区分的联合字段发送到远程参与者,我使用 Hyperion 作为序列化程序,但它似乎只序列化第一个字段而不序列化联合的其余部分。
示例代码如下:
Server.fsx
#r "nuget: Akka.FSharp"
#r "nuget: Akka.TestKit"
#r "nuget: Akka.Remote"
#r "nuget: Akka.Serialization.Hyperion"
#load "Message.fsx"
open Message
open System
open Akka.FSharp
open Akka.Remote
open Akka.Configuration
open Akka.Serialization
let configuration =
ConfigurationFactory.ParseString(
@"akka {
actor {
provider = ""Akka.Remote.RemoteActorRefProvider, Akka.Remote""
debug : {
receive : on
autoreceive : on
lifecycle : on
event-stream : on
unhandled : on
}
serializers {
hyperion = ""Akka.Serialization.HyperionSerializer, Akka.Serialization.Hyperion""
}
serialization-bindings {
""System.Object"" = hyperion
}
}
remote {
helios.tcp {
port = 9002
hostname = 192.168.0.94
}
}
}")
let serversystem = System.create "Server" configuration
let server (mailbox:Actor<_>) =
let rec loop () = actor {
let! message = mailbox.Receive()
match message with
| Message(num, num1, str) -> printfn "Got a number %d %d %s" num num1 str
| CreateDone(num, num1, str) -> printfn "Got a create %d %d %s" num num1 str
}
loop ()
let serveRef = spawn serversystem "server" server
Console.ReadLine() |> ignore
Client.fsx
#r "nuget: Akka.FSharp"
#r "nuget: Akka.TestKit"
#r "nuget: Akka.Remote"
#r "nuget: Akka.Serialization.Hyperion"
#load "Message.fsx"
open Message
open System
open Akka.FSharp
open Akka.Remote
open Akka.Configuration
open Akka.Serialization
let configuration =
ConfigurationFactory.ParseString(
@"akka {
actor {
provider = ""Akka.Remote.RemoteActorRefProvider, Akka.Remote""
serializers {
hyperion = ""Akka.Serialization.HyperionSerializer, Akka.Serialization.Hyperion""
}
serialization-bindings {
""System.Object"" = hyperion
}
}
remote {
helios.tcp {
port = 2552
hostname = localhost
}
}
}")
let clientSystem = System.create "client" configuration
let serveRef = select ("akka.tcp://Server@192.168.0.94:9002/user/server") clientSystem
serveRef <! Message(10L, 20, "Hello")
serveRef <! CreateDone(10L, 20, "Hi")
Console.ReadLine()
Message.fsx
type Message = Message of int64 * int * string
| CreateDone of int64 * int * string
服务器的输出是:
F:\UF\Courses\FALL2020\DOS\Projects\Project4.1>dotnet fsi --langversion:preview serve.fsx
[INFO][12/2/2020 1:42:13 AM][Thread 0001][remoting (akka://Server)] Starting remoting
[INFO][12/2/2020 1:42:13 AM][Thread 0001][remoting (akka://Server)] Remoting started; listening on addresses : [akka.tcp://Server@192.168.0.94:9002]
[INFO][12/2/2020 1:42:13 AM][Thread 0001][remoting (akka://Server)] Remoting now listens on addresses: [akka.tcp://Server@192.168.0.94:9002]
Got a number 10 20 Hello
所以似乎只有第一个字段在可区分的联合中被序列化。如何克服这个问题?
您的 actor 没有循环,因此在第一条消息后终止
添加一个
return! loop()
在你的递归循环中。
我觉得这个问题有点令人困惑。它指出第一个字段已打印,但所有字段都出现在打印输出中。我假设你的意思只是第一个 message
C# 示例中的 Akka 不需要循环,但 Akka.fsharp 匹配 MailboxProxessor 语法,因此需要显式循环。
为了将已区分的联合字段发送到远程参与者,我使用 Hyperion 作为序列化程序,但它似乎只序列化第一个字段而不序列化联合的其余部分。 示例代码如下:
Server.fsx
#r "nuget: Akka.FSharp"
#r "nuget: Akka.TestKit"
#r "nuget: Akka.Remote"
#r "nuget: Akka.Serialization.Hyperion"
#load "Message.fsx"
open Message
open System
open Akka.FSharp
open Akka.Remote
open Akka.Configuration
open Akka.Serialization
let configuration =
ConfigurationFactory.ParseString(
@"akka {
actor {
provider = ""Akka.Remote.RemoteActorRefProvider, Akka.Remote""
debug : {
receive : on
autoreceive : on
lifecycle : on
event-stream : on
unhandled : on
}
serializers {
hyperion = ""Akka.Serialization.HyperionSerializer, Akka.Serialization.Hyperion""
}
serialization-bindings {
""System.Object"" = hyperion
}
}
remote {
helios.tcp {
port = 9002
hostname = 192.168.0.94
}
}
}")
let serversystem = System.create "Server" configuration
let server (mailbox:Actor<_>) =
let rec loop () = actor {
let! message = mailbox.Receive()
match message with
| Message(num, num1, str) -> printfn "Got a number %d %d %s" num num1 str
| CreateDone(num, num1, str) -> printfn "Got a create %d %d %s" num num1 str
}
loop ()
let serveRef = spawn serversystem "server" server
Console.ReadLine() |> ignore
Client.fsx
#r "nuget: Akka.FSharp"
#r "nuget: Akka.TestKit"
#r "nuget: Akka.Remote"
#r "nuget: Akka.Serialization.Hyperion"
#load "Message.fsx"
open Message
open System
open Akka.FSharp
open Akka.Remote
open Akka.Configuration
open Akka.Serialization
let configuration =
ConfigurationFactory.ParseString(
@"akka {
actor {
provider = ""Akka.Remote.RemoteActorRefProvider, Akka.Remote""
serializers {
hyperion = ""Akka.Serialization.HyperionSerializer, Akka.Serialization.Hyperion""
}
serialization-bindings {
""System.Object"" = hyperion
}
}
remote {
helios.tcp {
port = 2552
hostname = localhost
}
}
}")
let clientSystem = System.create "client" configuration
let serveRef = select ("akka.tcp://Server@192.168.0.94:9002/user/server") clientSystem
serveRef <! Message(10L, 20, "Hello")
serveRef <! CreateDone(10L, 20, "Hi")
Console.ReadLine()
Message.fsx
type Message = Message of int64 * int * string
| CreateDone of int64 * int * string
服务器的输出是:
F:\UF\Courses\FALL2020\DOS\Projects\Project4.1>dotnet fsi --langversion:preview serve.fsx
[INFO][12/2/2020 1:42:13 AM][Thread 0001][remoting (akka://Server)] Starting remoting
[INFO][12/2/2020 1:42:13 AM][Thread 0001][remoting (akka://Server)] Remoting started; listening on addresses : [akka.tcp://Server@192.168.0.94:9002]
[INFO][12/2/2020 1:42:13 AM][Thread 0001][remoting (akka://Server)] Remoting now listens on addresses: [akka.tcp://Server@192.168.0.94:9002]
Got a number 10 20 Hello
所以似乎只有第一个字段在可区分的联合中被序列化。如何克服这个问题?
您的 actor 没有循环,因此在第一条消息后终止
添加一个
return! loop()
在你的递归循环中。
我觉得这个问题有点令人困惑。它指出第一个字段已打印,但所有字段都出现在打印输出中。我假设你的意思只是第一个 message
C# 示例中的 Akka 不需要循环,但 Akka.fsharp 匹配 MailboxProxessor 语法,因此需要显式循环。