集群一致哈希池为相同映射生成新路由 [英] clustered consistent hash pool producing new routee for same mapping

查看:129
本文介绍了集群一致哈希池为相同映射生成新路由的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含2个命令行项目的解决方案,它们创建了一个带有种子和客户端进程的akka​​.net集群.种子启动集群,然后实例化一个consistent-hash-cluster-router,该路由器对实现我的接口"IHasRouting"的任何消息执行哈希映射.因此,任何(来自种子或客户端的)IHasRouting消息都应以该消息的散列在路由上的种子处结束.

I have a solution with 2 command line projects that creates an akka.net cluster with a seed and client process. The seed starts the cluster and then instantiates a consistent-hash-cluster-router that performs hash mapping on any message that implements my interface "IHasRouting". So any IHasRouting message (from the seed or client) should end up at seed on a routee for the hash of that message.

项目正常启动,并且群集形成没有错误.种子和客户端都实例化路由器.来自种子和客户端的所有消息都具有相同的"VolumeId",因此它们应在种子处使用相同的路由. 来自客户端节点的BUT消息会在种子处为这些消息产生新的路由!

The projects start fine and the cluster forms without error. Both seed and client instantiate a router. All messages from the seed and client have the same "VolumeId" so they should go to the same route at the seed. BUT Messages from the client node result in a new routee for those messages at the seed!

我对一致性哈希路由器的理解是:

My understanding of a consistent-hash-cluster-router is that:

  • 包含IActorRef的IActorRef应该在该节点上的参与者要向路由器发送消息的每个节点上退出.
  • 路由器的权限在每个节点上应该相同,并且参与者名称相同.
  • 所有发送到路由器的消息都应实现IConsistentHash或路由器实例应具有"WithHashMapping()"
  • 所有具有相同哈希值的邮件将仅到达一个路由,并且始终是相同的路由
  • 一个路由可能会使用多个哈希值

我相信我了解一致的哈希群集路由器应该如何工作,并且许多DEV似乎正确使用了路由器类型,因此我的实现一定是错误的...请帮助!如果有帮助,我可以提供完整的解决方案.

I believe I understand how a consistent-hash-cluster-router should behave and plenty of the DEVs would appear to be using the router type correctly so my implementation must be wrong... Please help! I can provide the full solution if that helps.

创建路由器的代码:

system.ActorOf(
   new ClusterRouterPool(
       local: new ConsistentHashingPool(nrOfInstances: 1)
          .WithHashMapping(m => (m as IHasRouting)?.Company?.VolumeId ?? throw new Exception("no routing!")),
                settings: new ClusterRouterPoolSettings(
                    100,
                    100,
                    allowLocalRoutees: allowLocalRoutees, //true if the node role is a Seed
                    useRole: "Seed"))
                    .Props(Props.Create(() => new CompanyDeliveryActor())), "company-router");

我有一个公司"类,该类是发送到路由器的消息所必需的.此测试的所有VolumeId均相同.

I have a "Company" class that is required for messages to the router. All VolumeIds are the same for this test.

public class Company
{
    public readonly Guid CompanyId;
    public readonly Guid VolumeId;
    public readonly string CompanyName;
    public Company(Guid companyId, Guid volumeId, string companyName)
    {
        this.CompanyId = companyId;
        this.VolumeId = volumeId;
        this.CompanyName = companyName;
    }
}

路由器映射所使用的IHasRouting接口:

The IHasRouting interface that is used by the router mapping:

public interface IHasRouting
{
    Company Company { get; }
}

可以发送到路由器的示例消息类:

An example message class that can be sent to the router:

public class GetTripsMessage : IHasRouting
{
    public Company Company { get; private set; }
    public GetTripsMessage(Company company)
    {
        this.Company = company;
    }
}

最后是在路由器上为每个路由实例化的CompanyDeliverActor:

And Finally the CompanyDeliverActor which is instantiated for each routee at the router:

public class CompanyDeliveryActor : ReceiveActor
{
    private readonly Dictionary<Guid, IActorRef> companyManagers = new Dictionary<Guid, IActorRef>();
    private readonly Guid instanceid = Guid.NewGuid();

    public CompanyDeliveryActor()
    {
        this.Receive<GetTripsMessage>(m => this.RouteCompanyMessage(m, m.Company));
        this.Receive<SetTripsMessage>(m => this.RouteCompanyMessage(m, m.Company));
    }

    private void RouteCompanyMessage(object m, Company company)
    {
        //placing a watch here shows that this.instanceid is different for messages from the client.

        if (!this.companyManagers.TryGetValue(company.CompanyId, out var manager))
        {
            manager = Context.ActorOf(Props.Create(() => new CompanyManagerActor()));
            this.companyManagers[company.CompanyId] = manager;                
        }

        manager.Tell(m, Context.Sender);
    }
}

感谢您的指导.

推荐答案

经过调查,我同意我对clustering-consistent-hash-router的理解是错误的.现在,我知道我需要将代表路由器的IActorRef与集群的其余部分进行通信.这可以通过ClusterSinglton或某种类型的分布式pub子机制来完成.一种机制需要处理以下情况:节点或Actor变得丢失",实例化新的Actor(具有新的路由),并将新的Actor传达给集群中具有先前引用的所有Actor.

After investigation I agree that my understanding of the clustered-consistent-hash-router is wrong. I now understand that I need to communicate the IActorRef that represents the router to the rest of the cluster. This might be accomplished via a ClusterSinglton or (possibly) a distributed pub sub mechanism of some type. A mechanism needs to handle the situation where the node or Actor becomes "lost", a new Actor (with new routees) is instantiated and the new Actor is communicated to all those in the cluster that had the previous reference.

我正在研究群集分片"方法,并将就该方法遇到的技术困难提出另一个问题.

I am investigating the Cluster Sharding approach and will post another question in regards to technical difficulties that I am having with that approach.

这篇关于集群一致哈希池为相同映射生成新路由的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆