定义路由器配置时,不要使用/user
前缀 - 它是自动添加的。
此外,如果您想选择驻留在另一个节点上的参与者,则需要使用完整的参与者路径(带有节点地址) - 这是因为事实上,可能有不同的参与者居住在具有相同路径的不同节点上。你必须精确。
通常,在编译时您不会知道节点的地址。有两种方法可以提取:
1.从集群状态获取地址
这更容易,但您失去了对加入/离开节点做出反应的能力。你被迫每次都检查它,这很慢。本示例使用ActorSelection.ResolveOne
检索实际的IActorRef
实例。
async {
let members = Cluster.Get(system).State.Members
let actorRefs =
members
|> Seq.filter (fun m -> m.Roles.Contains("expected")) // use roles to filter out nodes that shouldn't be checked
|> Seq.map (fun m ->
let selection = select (m.Address.ToString() + "user/r-actor") system
let actorRef = selection.ResolveOne(timeout) |> Async.AwaitTask)
|> Async.Parallel }
2. 订阅集群事件并对加入/离开节点做出反应
在这里,您可以在节点加入/离开时对其做出反应。它还使用Identify
/ActorIdentity
接收实际的IActorRef
,这是更快的选项。
let aref =
spawn system "listener"
<| fun mailbox ->
let cluster = Cluster.Get (mailbox.Context.System)
cluster.Subscribe (mailbox.Self, [| typeof<ClusterEvent.IMemberEvent> |])
mailbox.Defer <| fun () -> cluster.Unsubscribe (mailbox.Self)
let rec loop () =
actor {
let! (msg: obj) = mailbox.Receive ()
match msg with
| :? ClusterEvent.MemberUp as up ->
// new node joined the cluster
let selection = select (up.Member.Address.ToString() + "user/r-actor") mailbox
selection <! Identify(null) // request actor under selection to identify itself
| :? ActorIdentity as id when id.Subject <> null ->
// actor has identified itself
id.Subject <! "hello"
| :? ClusterEvent.MemberRemoved as rem ->
// node leaved the cluster, invalidate all actors from that node
| _ -> ()
return! loop () }
loop ()
如果有疑问,我写了一个博客文章 http://bartoszsypytkowski.com/how-create-an-akka-net-cluster-in-f/关于从 F# 创建 Akka.NET 集群。也许你会发现它很有用。