如何在部署在不同集群节点上的两个相同参与者之间保持状态? (akka.net)

How do I persist states between two same actors deployed on different cluster node? (akka.net)

如果我有如下设置,假设我将有 3 个节点加入集群,并且我使用循环池。

var worker = cluster.ActorOf(Props.Create<Worker>().WithRouter(
                 new ClusterRouterPool(
                     new RoundRobinPool(5),
                     new ClusterRouterPoolSettings(30, true, 1))), "worker");

"worker" 只是记住它处理了多少条消息,如下所示

public class Worker : TypedActor, IHandle<int> {
readonly List<int> processed;

public Worker()
{
    processed = new List<int>();
}

public void Handle(int message)
{
    System.Threading.Thread.Sleep(new Random().Next(1000, 2000));
    processed.Add(message);
    Console.WriteLine("WORKER ({0}) [{1}:{2}], processed: {3}", message, Context.Self.Path, Cluster.Get(Context.System).SelfUniqueAddress.Address.Port, processed.Count);
}

是否可以在不同集群节点上的不同参与者之间同步 "processed List"?这是 akka.net.cluster.sharding 最终会做的事情吗?还是我在做一些完全没有意义的事情?

总的来说,您的问题似乎与 JVM akka eventuate and ddata 插件提供的问题最接近。在每种情况下,当你让演员在同一条数据上工作时,一般的副作用是最终的一致性——因为你的状态是 'shared' 在多台机器上工作的许多演员之间,特定时间点的实际状态可能会变得模糊,并且会因您采用哪个演员的观点而有所不同。

目前我还没有听说过任何针对您的案例的 .NET 土地上已完成的生产就绪选项,但是 Akka.DistributedData - which is currently under development - will allow you to complete your task. It's a Akka implementation of CRDTs

当整个应用程序中的总状态简洁时,CRDT 将为您提供的是访问最终一致的数据类型,该数据类型可以在分布式集群中的不同节点上复制。在这种情况下,您可以将 processed 列表替换为 GSet,这将允许您以分布式方式将元素附加到一个数据集。

如果您不想等待、冒险或自己构建 CRDT,您可以使用第三方解决方案,例如 Riak

PS:Akka.Cluster.Sharding 有一个不同的目的,即自动将你的 actors 平均分布在你的集群上——即使节点数量发生变化——这样只有一个特定参与者的实例将出现在当前集群范围内。