我有一个包含 2 个命令行项目的解决方案,它创建了一个带有种子和客户端进程的 akka.net 集群。种子启动集群,然后实例化一个一致哈希集群路由器,该路由器对实现我的接口“IHasRouting”的任何消息执行哈希映射。因此,任何 IHasRouting 消息(来自种子或客户端)都应该以该消息的哈希值在 routee 上的种子处结束。
项目开始正常,集群形成没有错误。种子和客户端都实例化了一个路由器。来自种子和客户端的所有消息都具有相同的“VolumeId”,因此它们应该在种子处使用相同的路由。但是来自客户端节点的消息会为种子中的这些消息产生一个新的路由!
我对一致哈希集群路由器的理解是:
- 一个表示它的 IActorRef 应该在该节点中的参与者打算向路由器发送消息的每个节点上退出。
- 路由器的实现在每个节点上应该是相同的,并且具有相同的参与者名称。
- 所有到路由器的消息都应该实现 IConsistentHash 或者路由器实例应该有一个“WithHashMapping()”
- 具有相同哈希的所有消息将仅到达一个路由,并且始终是相同的路由
- 一个路由可能需要多个哈希
我相信我了解一致哈希集群路由器的行为方式,并且许多 DEV 似乎都在正确使用路由器类型,所以我的实现一定是错误的......请帮助!如果有帮助,我可以提供完整的解决方案。
创建路由器的代码:
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 都相同。
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 接口:
public interface IHasRouting
{
Company Company { get; }
}
可以发送到路由器的示例消息类:
public class GetTripsMessage : IHasRouting
{
public Company Company { get; private set; }
public GetTripsMessage(Company company)
{
this.Company = company;
}
}
最后是在路由器上为每个路由实例化的 CompanyDeliverActor:
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);
}
}
感谢您的任何指导。