akkadotnet / akka.net

Canonical actor model implementation for .NET with local + distributed actors in C# and F#.
http://getakka.net
Other
4.69k stars 1.04k forks source link

Issue with akka local messages serialization with hyperion #4805

Open brunoalfano opened 3 years ago

brunoalfano commented 3 years ago

I'm trying to understand more of the Akka framework, in particular I'm working on an application in C# (.NET standard 2) I inherited that works within a Shared Actor Cluster. I'm working with Visual Studio 2019 under Windows 10, with Akka.Net version 1.4.10.0.

I have found a strage issue I cannot understand: when I send a local Akka message between actors, it is correctly serialized only when the class of the message is defined outside of the CLR of the actors (e.g. in a DLL). This of course happens only if you force the serialization to happen with the setting: akka{ actor{ serialize-messages = on } } which forces the local messages to be serialized instead of being passed as a reference. Note that everything is working fine with Publish/Subscribe. Just to give an example on when this happens, if I have an actor which wants to send a message of class MsgClass to its child Child, I do it like this: Child.Tell(new MsgClass());

In the Child class I register this type of message with: Receive<MsgClass>(MessageReceiveMethod);

Where the handling method is for instance: private void MessageReceiveMethod(MsgClass msg){}

If MsgClass is defined in a different DLL than the actors, the message gets handled correctly. If it's defined in the same executable, it gets handled by the: protected override void Unhandled(object message){}

But when in debug I check the message it has the correct class type and content.

As a final detail this is how the actor system is setup: `actor { serialize-messages = on

debug {
        receive = on      # log any received message
        autoreceive = on  # log automatically received messages, e.g. PoisonPill
        lifecycle = on    # log actor lifecycle changes
        event-stream = on # log subscription changes for Akka.NET event stream
        unhandled = on    # log unhandled messages sent to actors
}

provider = "Akka.Cluster.ClusterActorRefProvider, Akka.Cluster"

serializers {
    hyperion = "Akka.Serialization.HyperionSerializer, Akka.Serialization.Hyperion"
    akka-pubsub = "Akka.Cluster.Tools.PublishSubscribe.Serialization.DistributedPubSubMessageSerializer, Akka.Cluster.Tools"
}

serialization-bindings {
    "System.Object" = hyperion
    "Akka.Cluster.Tools.PublishSubscribe.IDistributedPubSubMessage, Akka.Cluster.Tools" = akka-pubsub
    "Akka.Cluster.Tools.PublishSubscribe.Internal.SendToOneSubscriber, Akka.Cluster.Tools" = akka-pubsub
}

serialization-identifiers {
    "Akka.Cluster.Tools.PublishSubscribe.Serialization.DistributedPubSubMessageSerializer, Akka.Cluster.Tools" = 9
}

} ` I've tried to look for similar issues but couldn't get any insight. I really hope it's something stupid on my side, I'll be really grateful if you can enlighten me on this matter. Thank you!

Aaronontheweb commented 3 years ago

@Arkatufus mind looking into this one too?

Arkatufus commented 3 years ago

Will do

Arkatufus commented 3 years ago

@brunoalfano You mentioned cluster, are the children on the same system as the parent? If they are different, when serializing/deserializing a message Type, both the class name and the assembly must match exactly on both ends. A Type that was described locally on both system would most probably fail, the only way for 2 separate system to talk over the wire using serialized/deserialized message is by sharing the same Type declared in a single assembly that is shared on both system.

brunoalfano commented 3 years ago

@Arkatufus Thank you for the support! Yes, the children are on the same system as the parent, so the Type they refer to is actually the same. In fact I have the issue when they are in the same assembly, while the issue is solved when they refer to a message Type that is in a different assembly, which seems to trigger a different behavior for the serializer. The issue even happens when I define an Actor and from its own parent i use the Tell to try to send the message, so I don't think it is a problem related to the Type being local only.

Arkatufus commented 3 years ago

@brunoalfano I'm still trying to reproduce this, but there are just way too many variables to consider. Can you post a gist or make a github repo of a small reproduction project of what you're trying to do?

Aaronontheweb commented 3 years ago

Dropping this from the milestone until we get a better reproduction