如何使用 Akka.FSharp API 在 Akka.NET 集群中实现故障转移?
我有以下集群节点用作种子:
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())
然后我有一个可能会死的任意节点:
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 ()
在集群中实施故障转移的推荐做法是什么?
具体来说,是否有一个代码示例说明当其中一个节点不再可用时集群的行为方式?
- 我的集群节点应该启动替换还是有不同的行为?
- 是否有一个配置可以自动处理这个我可以设置而无需编写代码?
- 我必须在哪里实现什么代码?