#f# #akka #akka.net #f#-interactive
#f# #akka #akka.net #f # -интерактивный
Вопрос:
Чтобы отправить дискриминируемое поле объединения удаленному субъекту, я использую 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:UFCoursesFALL2020DOSProjectsProject4.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
Таким образом, похоже, что только первое поле сериализуется в дискриминируемом объединении. Как это преодолеть?
Комментарии:
1. Я вижу, вы используете helios.tcp, но я использую dot-netty.tcp. Хорошо работает уже много лет.
Ответ №1:
Ваш актер не выполняет цикл, поэтому завершается после первого сообщения
Добавьте
return! loop()
внутри вашего рекурсивного цикла.
Я думаю, что вопрос немного сбивает с толку. В нем указано, что 1-е поле напечатано, но все поля присутствуют в выводе на печать. Я полагаю, вы имеете в виду только первое сообщение
Akka в примерах c # не нуждается в цикле, но Akka.fsharp соответствует синтаксису MailboxProxessor, поэтому требует явного цикла.
Комментарии:
1. Я чувствую себя очень плохо, так как пропустил это при редактировании:-(