Akka集群脑裂

集群脑裂

问题和影响

系统集群化后,出现物理机崩溃的情况,或者节点奔溃,如果没有从集群成员中剔除,系统会一直尝试连接。而网络分区、以及进程高负载无响应情况,则会引发脑裂现象。当一个节点观察到另外节点异常时,系统无法判定它暂时性故障还是永久性故障,所以我们把这些情况一起处理。

脑裂会把集群划分成多个集群,且独立运行,如果使用了类似Singleton唯一性业务的功能,就会有问题。

期望

发生崩溃时,我们希望集群立即把崩溃的节点从成员资格中剔除;网络分区或者无响应时,我们希望等待一会,再检查节点是否治愈,如果治愈了就保持成员资格,如果还是无法响应就得关闭其中一侧的节点。

这里有个难点,不知道哪一侧应该保留,那一侧关闭,因为两侧也不能互相通讯。所以我们希望,双方都能自己做出决定,并且哪一侧继续运行哪一侧自行关闭得做出相同的决定。

策略

前提

所有策略的前提是集群处于一个稳定的(stable)状态。


# To enable the split brain resolver you first need to enable the provider in your application.conf:
# akka.cluster.downing-provider-class = "com.lightbend.akka.sbr.SplitBrainResolverProvider"

akka.cluster.split-brain-resolver {
  # Select one of the available strategies (see descriptions below):
  # static-quorum, keep-majority, keep-oldest, keep-referee, down-all
  # if left "off" when the downing provider is enabled cluster startup will fail.
  active-strategy = off

  # Time margin after which shards or singletons that belonged to a downed/removed
  # partition are created in surviving partition. The purpose of this margin is that
  # in case of a network partition the persistent actors in the non-surviving partitions
  # must be stopped before corresponding persistent actors are started somewhere else.
  # This is useful if you implement downing strategies that handle network partitions,
  # e.g. by keeping the larger side of the partition and shutting down the smaller side.
  # Decision is taken by the strategy when there has been no membership or
  # reachability changes for this duration, i.e. the cluster state is stable.
  stable-after = 20s

  # When reachability observations by the failure detector are changed the SBR decisions
  # are deferred until there are no changes within the 'stable-after' duration.
  # If this continues for too long it might be an indication of an unstable system/network
  # and it could result in delayed or conflicting decisions on separate sides of a network
  # partition.
  # As a precaution for that scenario all nodes are downed if no decision is made within
  # `stable-after + down-all-when-unstable` from the first unreachability event.
  # The measurement is reset if all unreachable have been healed, downed or removed, or
  # if there are no changes within `stable-after * 2`.
  # The value can be on, off, or a duration.
  # By default it is 'on' and then it is derived to be 3/4 of stable-after.
  down-all-when-unstable = on

}

stable-after参数控制着在较短的时间内尽快的删除崩溃节点,其代价是存在对可能会恢复的网络分区节点过早的采取措施的风险。不同群集大小的建议最小持续时间:

节点数之后稳定
57s
1010s
2013s
5017s
10020s
100030s

基于这个前提,akka提供了一些策略,来应付脑裂的情况

策略一 Static Quorum

静态个数

akka.cluster.split-brain-resolver.active-strategy=static-quorum
akka.cluster.split-brain-resolver.static-quorum {
  # minimum number of nodes that the cluster must have
  quorum-size = undefined

  # if the 'role' is defined the decision is based only on members with that 'role'
  role = ""
}

配置指定了一个固定的数值(static quorum), 当集群发生脑裂的时候,任何一侧中的node >= quorum-size,则认定是有效的。因此为了不产生多个集群,数值和节点数有一关系,总节点数必须小于quorum-size * 2 - 1 ,当然也必须大于quorum-size,否则整个集群会stop。

这个策略优点是,在任何脑裂发生的时候,当产生两个集群的时候,效果是非常显著的,因为必然会推举出一侧 有效,另一侧无效。
它的缺点是 :

  1. quorum的数值是静态配置的,如果集群动态增加node,这个值必须随之而调整。
  2. 如果脑裂数量超过2。 比如10 Nodes,static quorum最小的值是6 ,如果发生脑裂时,将集群划分为3个分区,分别是 (3,3,4) ,那么任何分区都无法运作。

总的来说,Static Quorum相对简单粗放一些,可以应对大部分的异常,也有不少分布式系统使用的是这个策略, 比如Elasticsearch。

策略二 Keep Majority

保持多数

akka.cluster.split-brain-resolver.active-strategy=keep-majority
akka.cluster.split-brain-resolver.keep-majority {
  # if the 'role' is defined the decision is based only on members with that 'role'
  role = ""
}

基本规则是保留所有分区中,拥有majority nodes的分区。
它和static quorum相比的好处是,如果整个 cluster的nodes数量是动态调整的,那么majority也是一个动态的值,这样会避免static quorum的问题。
但此策略依旧不能避免的是,如果两个分区所拥有的node数量是相同的,那么整个集群将会被终止。
可以居于role定义策略,如果在多个分区中,拥有这些valuable的节点数量较多的话,就会保留这个分区。
这个选项对于一个多角色的集群,某些node是无状态的(stateless)的工作节点,他们相对而言价值较低,而某些节点可能是数据持久化节点,或者是Master节点。
这样就可以区分出来多个Partition的价值,而保留价值高的部分。

策略三 Keep Oldest

保留最老

整个集群只保留一个拥有最老节点的分区。
当然,有一个特例是,如果某一个partition,只有这一个oldest node,则这个分区会关闭它自己。
这个策略适用于一些 Singleton 的场景,即某些特殊的服务只存在于 oldest的节点上。

其他说明

split brain已经开源,代码合并在akka 2.6.8+版本中,我们使用当前最新的2.6.14。

节点被关闭时,官方建议jvm关闭,但如果我们使用play-framework框架,会导致死锁,不能启用akka.coordinated-shutdown.exit-jvm,报错情况:

Can't start Play: detected "akka.coordinated-shutdown.exit-jvm = on". Using "akka.coordinated-shutdown.exit-jvm = on" in Play may cause a deadlock when shutting down. Please set "akka.coordinated-shutdown.exit-jvm = off"

节点关闭相关日志:

[akka.cluster.singleton.ClusterSingletonManager] [-[Self downed, stopping]-]
[akka.cluster.singleton.ClusterSingletonManager] [-[Self downed, stopping ClusterSingletonManager]-] 
[play.core.server.AkkaHttpServer] [-[Stopping server...]-] 
[akka.cluster.singleton.ClusterSingletonManager] [-[Self removed, stopping ClusterSingletonManager]-] 

由此可见,如果集群不可用了,akka-http也关闭了。如果不能使用akka.coordinated-shutdown.exit-jvm的话,我们可以通过http检测来判断集群的健康状态。

参考文档

https://doc.akka.io/docs/akka-enhancements/current/split-brain-resolver.html
https://doc.akka.io/docs/akka/current/split-brain-resolver.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Akka是一个基于Actor模型的并发编程框架,它提供了一种简单而强大的方式来处理并发编程和分布式系统。WebSocket是一种在客户端和服务器之间进行双向通信的协议。而wss是WebSocket***可以通过akka-http模块来实现。akka-http提供了一套灵活的工具和API来处理HTTP和WebSocket请求。 要在Akka中使用WebSocket over SSL(wss),你需要做以下几步: 1. 配置SSL证书:你需要生成和配置一个SSL证书,可以使用自签名证书或者购买一个由可信机构签名的证书。 2. 导入依赖:确保你的项目中导入了akka-http和akka-stream依赖。 3. 创建WebSocket路由:使用akka-http的路由DSL创建一个WebSocket路由。你可以定义处理WebSocket消息的逻辑,比如收到消息时的处理和发送消息给客户端等。 4. 启动HTTP服务:创建一个HTTP服务器,并将WebSocket路由添加到路由器中。 下面是一个简单示例,演示了如何在Akka中使用WebSocket over SSL: ```scala import akka.actor.ActorSystem import akka.http.scaladsl.Http import akka.http.scaladsl.model.ws.{Message, TextMessage} import akka.http.scaladsl.server.Directives._ import akka.stream.ActorMaterializer import akka.stream.scaladsl.{Flow, Sink, Source} import scala.concurrent.ExecutionContext.Implicits.global object WebSocketServer { def main(args: Array[String]): Unit = { implicit val system = ActorSystem("websocket-system") implicit val materializer = ActorMaterializer() val route =

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值