pulsar 报错源码排查:"Not enough non-faulty bookies available"
1)报错背景
有个客户的环境,在重启机器之后,bookie 一直报错,还连累了 broker 一直无法启动
无可奈何,找到了我这里
简单介绍下环境
pulsar in k8s,3 broker,3 bookie
可以看到几个明显的错误,虽然是 WARN
WARN:Failed to find 1 bookie:excludeBookies:puslar-bookie-0 1 2
WARN:Not enough non-faulty bookies available
2)源码追踪(不想看的可以直接看结论)
拿着关键字 Not enough non-faulty bookies available
google 了一下
有的说是磁盘满了,有的说是网络不通,但是我的环境十分健康,这些结论明显站不住脚,于是我觉得自己浅浅追踪一下源码
2.1)源码中搜一下报错:ReplicationWorker
先在 bookie 源码中找到 Not enough non-faulty bookies available 报错的异常
整个源码中,只有该异常会打印这样的日志
而抛出该类异常的场景也比较少,一下子就定位到了 ReplicationWorker
图中红框部分,很明显,在执行 admin.replicateLedgerFragment 的时候,抛出了 BKNotEnoughBookiesException 的异常
既然是发生在 ReplicationWorker,说明是做了 ledger 同步的操作
那么,在什么时候 bookie 需要同步呢
1)bookie 定期的数据同步
2)bookie 节点故障了,需要把数据同步到其他健康的 bookie 节点
3)bookie 节点的新增与删除
我们在同步的时候,肯定有一个要同步的目的地,看这个报错,应该就是找不到合适的目标 bookie
2.2)触发同步时,究竟做了什么:replicateLedgerFragment
仔细查看上面调用的 replicateLedgerFragment 方法
在同步时,首先会寻找目标 bookie 的地址
调用 getReplacementBookiesByIndexes 获取 targetBookieAddresses
下面红框是 getReplacementBookiesByIndexes 的核心逻辑
这段代码有两个关键点
1)首先会排除被同步的节点,add 进 bookieToExclude(我本身就是被同步出去的节点,不可能被选成目标)
2)进一步调用了 replaceBookie 选择 targetBookie,并且传递了一大堆很有意思的参数~
在传递的参数中,有一些与我们 broker.conf 中一些配置项有关(贴一下配置原文)
EnsembleSize,WriteQuorumSize,AckQuorumSize = 3 1 1
代表着,当前这个集群,创建 ledger 往里面写数据,需要起码三台 bookie 存活,并没有其他副本,只需要一个确认
说明环境的数据没有冗余(这是后话)
2.3)看看 bookie 用这些参数做什么:replaceBookie
我们来看看它对应的 replaceBookie,到底用这些参数做了什么?
重点来了!!!!
选取目标 bookie 时,第一件事,就是把 Ensemble 集合中的所有 bookie 都排除在选择外!!!然后再进行选取
难怪日志中报错 Failed to find 1 bookie:excludeBookies:puslar-bookie-0 1 2
原来是选择新的 Bookie,会从 ensemble 集合外选取
那么到这里,我们的问题基本可以解释了
3)结论
出现 Not enough non-faulty bookies available,是多个原因综合的结果
这套环境,有且只有 3 个 Bookie 节点
broker.conf 配置文件中,配置了 managedLedgerDefaultEnsembleSize = 3,意味着必须要有 3 个存活,才能创建 ledger 成功,少一个都不行
因为某些原因,bookie 有一个节点发生故障,触发日志同步
我现在 bookie 挂了,需要找个别的健康 bookie 代替
在 ensemble 集合之外找,但是对不起,除了这三个,已经没有了!!!
这就导致 bookie 数量满足不了 EnsembleSize 的大小,此时如果有新数据要写入,就会失败,无法写入
同时,因为该环境使用官方 chart 包部署 pulsar,也导致 broker 启动失败,一直卡住
这是因为 broker 的启动条件与 EnsembleSize 有关!!!
部署 broker 时,必须等待 EnsembleSize 数量的 bookie 就绪,才能够启动 broker
好家伙,bookie 挂一个,不仅数据不能同步,broker 也起不了
4)解决办法
部署中间件,或者说调优,应该准确理解中间件的部署参数
在这个例子中,EnsembleSize 不应该设置的与 bookie 实际数量一样,可以变成 2
这样即使 bookie 挂了一个,也可以得到补充,且不影响正常读写,甚至 broker 也不会启动失败
提高了 pulsar 集群的容错
5)留下的坑以后再填
autoRecovery 的机制与坑
pulsar 的同步机制
版权声明: 本文为 InfoQ 作者【李code】的原创文章。
原文链接:【http://xie.infoq.cn/article/0dd3ae703c7bc38f662b82b96】。文章转载请联系作者。
评论