首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用Akka.NET API在Akka.FSharp集群中实现故障转移?

如何使用Akka.NET API在Akka.FSharp集群中实现故障转移?
EN

Stack Overflow用户
提问于 2017-03-14 19:52:36
回答 1查看 428关注 0票数 2

如何使用Akka.NET API在Akka.FSharp集群中实现故障转移?

I有以下用作种子的集群节点:

代码语言:javascript
复制
open Akka
open Akka.FSharp
open Akka.Cluster
open System
open System.Configuration

let systemName = "script-cluster"
let nodeName = sprintf "cluster-node-%s" Environment.MachineName
let akkaConfig = Configuration.parse("""akka {  
                                          actor {
                                            provider = "Akka.Cluster.ClusterActorRefProvider, Akka.Cluster"
                                          }
                                          remote {
                                            log-remote-lifecycle-events = off
                                            helios.tcp {
                                                hostname = "127.0.0.1"
                                                port = 2551       
                                            }
                                          }
                                          cluster {
                                            roles = ["seed"]  # custom node roles
                                            seed-nodes = ["akka.tcp://script-cluster@127.0.0.1:2551"]
                                            # when node cannot be reached within 10 sec, mark is as down
                                            auto-down-unreachable-after = 10s
                                          }
                                        }""")
let actorSystem = akkaConfig |> System.create systemName

let clusterHostActor =
    spawn actorSystem nodeName (fun (inbox: Actor<ClusterEvent.IClusterDomainEvent>) -> 
        let cluster = Cluster.Get actorSystem
        cluster.Subscribe(inbox.Self, [| typeof<ClusterEvent.IClusterDomainEvent> |])
        inbox.Defer(fun () -> cluster.Unsubscribe(inbox.Self))
        let rec messageLoop () = 
            actor {
                let! message = inbox.Receive()                        
                // TODO: Handle messages
                match message with
                | :? ClusterEvent.MemberJoined as event -> printfn "Member %s Joined the Cluster at %O" event.Member.Address.Host DateTime.Now
                | :? ClusterEvent.MemberLeft as event -> printfn "Member %s Left the Cluster at %O" event.Member.Address.Host DateTime.Now
                | other -> printfn "Cluster Received event %O at %O" other DateTime.Now

                return! messageLoop()
            }
        messageLoop())

然后,我有一个可能死掉的任意节点:

代码语言:javascript
复制
open Akka
open Akka.FSharp
open Akka.Cluster
open System
open System.Configuration

let systemName = "script-cluster"
let nodeName = sprintf "cluster-node-%s" Environment.MachineName
let akkaConfig = Configuration.parse("""akka {  
                                          actor {
                                            provider = "Akka.Cluster.ClusterActorRefProvider, Akka.Cluster"
                                          }
                                          remote {
                                            log-remote-lifecycle-events = off
                                            helios.tcp {
                                                hostname = "127.0.0.1"
                                                port = 0       
                                            }
                                          }
                                          cluster {
                                            roles = ["role-a"]  # custom node roles
                                            seed-nodes = ["akka.tcp://script-cluster@127.0.0.1:2551"]
                                            # when node cannot be reached within 10 sec, mark is as down
                                            auto-down-unreachable-after = 10s
                                          }
                                        }""")
let actorSystem = akkaConfig |> System.create systemName

let listenerRef =  
    spawn actorSystem "temp2"
    <| fun mailbox ->
        let cluster = Cluster.Get (mailbox.Context.System)
        cluster.Subscribe (mailbox.Self, [| typeof<ClusterEvent.IMemberEvent>|])
        mailbox.Defer <| fun () -> cluster.Unsubscribe (mailbox.Self)
        printfn "Created an actor on node [%A] with roles [%s]" cluster.SelfAddress (String.Join(",", cluster.SelfRoles))
        let rec seed () = 
            actor {
                let! (msg: obj) = mailbox.Receive ()
                match msg with
                | :? ClusterEvent.MemberRemoved as actor -> printfn "Actor removed %A" msg
                | :? ClusterEvent.IMemberEvent           -> printfn "Cluster event %A" msg
                | _ -> printfn "Received: %A" msg
                return! seed () }
        seed ()

在集群中实现故障转移的推荐实践是什么?

具体来说,当集群的一个节点不再可用时,是否有一个集群应该如何运行的代码示例?

  • 我的集群节点应该分拆一个替代品,还是有不同的行为?
  • 是否有一种可以自动处理这一问题的配置,而无需编写代码即可进行设置?
  • 我需要实现什么代码,在哪里实现?
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-03-14 20:58:16

首先,当节点加入/离开过程已经完成时,最好依靠MemberUpMemberRemoved事件(都实现ClusterEvent.IMemberEvent接口,所以订阅它们),因为它们标记阶段。联合事件和左事件并不一定确保节点在发出信号的时间点完全可操作。

关于故障转移方案:

  • 自动旋转的替代品可以通过Akka.Cluster.Sharding插件(阅读文章12,以获得更多关于它如何工作的信息)。Akka.FSharp中没有类似的功能,但是您可以使用Akkling.Cluster.Sharding插件:参见示例代码
  • 另一种方法是在每个节点上预先创建替换参与者。您可以使用集群路由器分布式发布/订阅将消息路由到它们。然而,当您有无状态的场景时,这更像是一种情况,这样每个参与者都能够在任何时候完全能够接收到另一个参与者的工作。这是更通用的解决方案,用于在生活在许多不同节点上的许多参与者之间分配工作。
  • 您还可以设置对处理参与者的监视。通过使用监控器函数,您可以命令您的演员监视另一个演员(不管它住在哪里)。在节点故障的情况下,将以Terminated消息的形式向所有观察者发送有关即将死亡的参与者的信息。这样,您可以实现自己的逻辑,即在另一个节点上重新创建参与者。这实际上是最通用的方式,因为它不使用任何额外的插件或配置,但行为需要自己描述。
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42795321

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档