2017-12-27 331 views

回答

0

所有以sharded actor(实体)为目标的消息都必须经过负责实体的givent类型的shard区域。一个碎片区域可以初始化这样的:

var sharding = ClusterSharding.Get(system); 
var shardRegion = sharding.Start(
    typeName: nameof(MyActor), 
    entityProps: Props.Create<MyActor>(), // the Props used to create entities 
    settings: ClusterShardingSettings.Create(system), 
    messageExtractor: messageExtractor 
); 

为了正确地将消息路由到实体,碎片区域必须能够提取碎片-ID和实体的实体ID和碎片,它属于。这是一个messageExtractor对象的作业(它必须实现IMessageExtractor接口)。

这里的常见模式是创建一个专用信封,用于将实际消息路由到实体。在下面你可以看到一个例子 - shard id没有被明确地提供,而是从实体id的模数最大的shards数量中计算出来的(这个值一旦被选中就不能改变)。

public sealed class ShardEnvelope 
{ 
    public readonly string EntityId; 
    public readonly object Payload; 

    public ShardEnvelope(string entityId, object payload) 
    { 
     EntityId = entityId; 
     Payload = payload; 
    } 
} 

public sealed class MessageExtractor : HashCodeMessageExtractor 
{ 
    public MessageExtractor(int maxNumberOfShards) : base(maxNumberOfShards) { } 
    public override string EntityId(object message) => 
     (message as ShardEnvelope)?.EntityId; 
    public override object EntityMessage(object message) => 
     (message as ShardEnvelope)?.Payload; 
} 

现在,当实体的生命周期完全由集群分片管理,并在群集内的实际定位可以随时间变化(由于再平衡),给定的群集节点内的相对路径始终保持不变,并符合下列模式:

/user/sharding/<typeName>/<shard-id>/<entity-id> 

这意味着,如果要提取实体ID和当前演员的碎片-ID,您可以直接从演员的路径做到这一点:

var entityId = Self.Path.Name; 
var shardId = Self.Path.Parent.Name; 
相关问题