簡體   English   中英

使用ClusterSharding在Akka群集中存儲實體ID

[英]Storing entity IDs in an Akka cluster using ClusterSharding

我有一個akka.net群集,我打算在其中使用ClusterSharding在群集中的各個節點之間分片實體(角色)。 位於集群上方的是一層,它將是標准的REST風格的API,提供用於創建和檢索實體的端點。 我還希望能夠通過此API返回集群中當前所有實體的ID(就像您通常在REST風格的API中那樣,例如通過/ api / entity上的GET)-這些ID將是實體的屬性,或者是定向消息時ClusterSharding模塊使用的完整ID。

是否有一種簡單的方法可以從集群中檢索所有這些ID? 還是應該創建一個單獨的“緩存” actor來存儲ID,並在創建/恢復實體時(對於持久性actor)將這些ID存儲起來,REST API層可以直接調用這些ID? 還是API層應該在每次調用集群時向集群查詢ID(通過向所有實體廣播消息並匯總響應)? 最后一個似乎有點浪費,尤其是在實體列表相對靜態的時候。

還是我錯過了一些東西,需要設計不同的東西?

謝謝你提供的所有幫助。

如果您僅對當前處於活動狀態的實體感興趣,則可以簡單地向當前碎片區域詢問其實體ID:

var region = ClusterSharding.Get(system).ShardRegion(typeName);
var state = await region.Ask<CurrentShardRegionState>(GetShardRegionState.Instance);
foreach (var shard in state.Shards) 
    foreach(var entityId in shard.EntityIds)
        Console.WriteLine($"{typeName}/{shard.ShardId}/{entityId}");

但是,這將僅檢索有關生活在當前群集節點上的實體的信息,而不是在任何地方。 但是,如果需要,您可以匯總結果:

var cluster = Cluster.Get(system);
var region = ClusterSharding.Get(system).ShardRegion(typeName);
var members = cluster.State.Members;
var regions = members
    .Select(m => region.Path.ToStringWithAddress(m.Address))
    .Select(system.ActorSelection);

// at this point regions variable is a collection of ActorSelections poiting
// to regions on all known nodes. You can use Ask pattern on them directly

請記住,這種請求可能非常龐大。

盡管此操作可以讓您檢索有關特定typeName的所有節點上所有EntityID的信息,但仍不計入非活動實體。

如果要獲取生活在所有節點上的所有實體的ID,則需要對分片模塊使用的ReadJournal進行查詢。 這需要滿足兩個條件:

  1. 僅當您的群集分片擴展使用的是支持Akka.Persistence.Query的持久后端時,它才有效
  2. 設置時需要akka.cluster.sharding.remember-entities = on -默認情況下處於關閉狀態,一旦啟用,它將增加集群分片基礎架構的成本。

如果是SQL期刊,則應大致如下所示:

var queries = PersistenceQuery.Get(actorSystem)
    .ReadJournalFor<SqlReadJournal>("path-to-sharding-journal");

var shardPrefix = "/sharding/" + typeName + "Shard/"
Source<string, NotUsed> entitySource = queries
    .AllPersistenceIds() 
    .Where(pid => pid.StartsWith(shardPrefix)) // get all shard IDs ever known
    .ConcatMany(shardId => queries.CurrentEventsByPersistenceId(shardId)) // get stream of persisted events for each shard (you may need to stretch the query limit here)
    .Collect(env => env.Event as Shard.EntityStarted) // filter out EntityStarted events
    .Select(e => e.EntityId); // extract entity ID

using (var mat = system.Materializer())
{
    // materialize source into a list
    var entityIds = await entitySource
        .RunAggregate(ImmutableList<string>.Emtpy, (acc, id) => acc.Add(id), mat);
}

請記住,這種查詢也可能非常昂貴。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM