我们间歇性地收到以下错误
2022-05-25 08:32:30,691 ERROR app=abc a.c.s.DDataShardCoordinator - The ShardCoordinator was unable to update a distributed state within ‘updating-state-timeout’: 2000 millis (retrying). Perhaps the ShardRegion has not started on all active nodes yet? event=ShardRegionRegistered(Actor[akka://application@10.52.174.4:25520/system/sharding/abcapp#-1665332307])
2022-05-25 08:32:31,348 WARN app=abc a.c.s.ShardRegion - abcapp: Trying to register to coordinator at [ActorSelection[Anchor(akka://application@10.52.103.132:25520/), Path(/system/sharding/abcappCoordinator/singleton/coordinator)]], but no acknowledgement. Total [22] buffered messages. [Coordinator [Member(address = akka://application@10.52.103.132:25520, status = Up)] is reachable.]
While we check cluster members by using /cluster/members we got “10.52.174.4:25520” this as
{
“node”: “akka://application@10.52.252.4:25520”,
“nodeUid”: “7353086881718190138”,
“roles”: [
“dc-default”
],
“status”: “Up”
},
表示运行正常,但当我们使用
从集群中删除此节点时,问题就解决了/cluster/members/{address}
(leave operation to remove 10.52.252.4 from cluster,一旦它被移除,cluster将创建新的pod并重新平衡。
需要帮助了解处理此错误的最佳方法。
感谢您当然可以实现一个外部控制平面来解析日志,并将显示此错误的节点从集群中移除。
也就是说,最好理解这里发生了什么。ShardCoordinator
运行在集群中最老的节点上,并且需要确保在诸如哪些节点拥有哪些分片之类的事情上达成一致。它通过要求集群中的大多数节点确认更新来实现这一点。如果状态更新未被确认,则对状态的进一步更新(例如重新平衡)将被延迟。
我说的是"多数",但由于在相对于集群大小有大量节点周转率的集群中,简单的多数可能导致数据丢失,因此它变得更加复杂。考虑一个3个节点的集群,N1, N2, N3。N1 (ShardCoordinator
)更新状态,当它和N3都更新状态时,认为更新成功。从簇中去掉N1,代之以N4;N2成为分片协调器(成为下一个最老的节点),并从自己和其他节点请求状态;N4首先响应。结果导致N1所做的状态更新丢失。因此,有两个其他设置起作用:
akka.cluster.coordinator-state.write-majority-plus
(默认3)将其添加到大多数写入要求(向下舍入)akka.cluster.distributed-data.majority-min-cap
(默认5),它要求大多数加上添加的节点必须至少是这个
如果计算出的多数数大于节点数,则多数数变为所有节点。因此,在节点少于9个的集群中,这些默认值将成为有效的所有节点(更新时的实际超时是配置超时的四分之一,以允许三次重试)。
你没有说你的集群大小是多少,但是如果在一个少于9个节点的集群中运行,将akka.cluster.sharding.updating-state-timeout
从默认的5秒增加到允许增加一致性级别是一个好主意。减少write-majority-plus
和majority-min-cap
是一种选择,如果你愿意承担违反集群分片保证的风险(例如,同一实体的多个实例运行并可能破坏它们的持久状态)。矛盾的是,如果其他节点响应缓慢的原因是过载,增加集群大小也可能有所帮助。