适用版本: 7.0-8.9
1. 错误异常的基本描述 #
became follower 是 Elasticsearch 集群协调层(Coordination Layer)抛出的异常,完整异常类通常为 CoordinationStateRejectedException: became follower。该异常表示当前节点在尝试以候选者(candidate)或领导者(leader)身份处理加入请求时,因集群状态发生变更而被迫转为追随者(follower)角色,导致正在进行的加入请求被拒绝。
该异常本身不一定是故障,而是集群选举过程中的正常状态转换信号。但在以下场景中需要引起注意:
- 集群频繁出现此异常,说明选举过程不稳定,可能存在网络抖动或节点资源问题。
- 节点长时间无法完成选举,导致集群无法选出主节点或无法稳定提供服务。
- 伴随其他异常(如
master_not_discovered_exception、node_left)同时出现,说明集群存在更严重的协调问题。
常见现象 #
- 节点日志中反复出现
CoordinationStateRejectedException: became follower日志条目。 - 集群状态频繁变更,
_cat/health或_cluster/health显示集群状态在red/yellow/green之间反复切换。 _cat/master显示主节点频繁变更,或长时间无法选出主节点。- 数据写入和搜索请求间歇性失败,返回
master_not_discovered_exception或no master node错误。 - Kibana 或其他客户端频繁断开连接,提示无法连接到 Elasticsearch 集群。
典型报错与异常栈 #
CoordinationStateRejectedException: became follower
at org.elasticsearch.cluster.coordination.Coordinator.handleJoinRequest(Coordinator.java:XXX)
at org.elasticsearch.cluster.coordination.JoinHelper.lambda$new$0(JoinHelper.java:XXX)
或出现在节点加入集群时:
[INFO ][o.e.c.c.Coordinator ] [node_name] cluster UUID changed, joining master [master_node] with term [X]
[WARN ][o.e.c.c.JoinHelper ] [node_name] failed to join {master_node}
CoordinationStateRejectedException[became follower]
2. 为什么会发生这个错误 #
Elasticsearch 7.x 之后引入了基于 Raft 的集群协调实现(由 Coordinator 类管理)。节点在集群中的角色通过选举确定:
- Leader(领导者/主节点):负责集群状态管理和协调。
- Follower(追随者):接受领导者管理,参与选举投票。
- Candidate(候选者):在选举过程中临时角色。
became follower 异常的产生机制如下:
当节点 A 以候选者身份向节点 B 发送加入请求(join request)时,如果节点 B 在此时因收到更高任期(term)的投票或发现其他主节点,而将自身角色切换为 follower,那么节点 B 会拒绝节点 A 的加入请求,并抛出 CoordinationStateRejectedException: became follower。
常见原因包括:
- 网络不稳定:节点间通信延迟或丢包,导致心跳超时,触发重新选举。
- 节点资源不足:CPU 或内存压力过大,导致节点响应心跳超时,被其他节点认为已失效。
- 集群配置不当:
discovery.seed_hosts或cluster.initial_master_nodes配置不完整,导致节点无法正确发现彼此。 - 脑裂场景:网络分区导致集群出现多个候选主节点,分区恢复后角色重新协商。
- 节点频繁重启:节点反复加入和离开集群,导致选举状态反复变化。
- 版本不兼容:混合部署不同版本的 Elasticsearch 节点,协调协议存在差异。
3. 如何排查这个异常 #
第一步:确认集群当前状态 #
# 查看集群健康状态
curl -X GET "localhost:9200/_cluster/health?pretty"
# 查看主节点信息
curl -X GET "localhost:9200/_cat/master?v"
# 查看节点列表及角色
curl -X GET "localhost:9200/_cat/nodes?v&h=name,role,master,ip,heap.percent,ram.percent,cpu,load_1m,uptime"
第二步:检查节点日志 #
在出现异常的节点上查找相关日志:
# 搜索协调相关日志
grep -E "CoordinationStateRejectedException|became follower|master|election" /var/log/elasticsearch/elasticsearch.log | tail -100
# 搜索节点加入相关日志
grep -E "joining|join|cluster UUID" /var/log/elasticsearch/elasticsearch.log | tail -50
第三步:检查网络连通性 #
# 从当前节点测试与其他节点的连通性
curl -X GET "http://<other_node_ip>:9200/"
# 检查节点间传输端口(默认 9300)是否可达
telnet <other_node_ip> 9300
第四步:检查节点资源 #
# 查看 JVM 堆使用情况
curl -X GET "localhost:9200/_nodes/stats/jvm?pretty"
# 查看节点负载
curl -X GET "localhost:9200/_nodes/stats/os?pretty"
4. 如何解决这个错误 #
场景一:偶发异常(无需特殊处理) #
如果异常只是偶尔出现,且集群状态正常、选举能快速完成,通常无需特殊处理。这是分布式系统选举过程中的正常现象。
场景二:频繁出现选举不稳定 #
1. 检查并优化网络配置
确保节点间网络稳定,必要时调整以下配置:
# elasticsearch.yml
# 增加心跳超时时间(默认 1s,可适当调大)
discovery.request_peers_timeout: 1s
discovery.find_peers_interval: 1s
# 确保 seed_hosts 配置完整
discovery.seed_hosts:
- "node1:9300"
- "node2:9300"
- "node3:9300"
2. 检查节点资源,降低负载
- 确保节点 JVM 堆大小不超过物理内存的 50%,且不超过 32GB。
- 检查是否有大量垃圾回收(GC)导致节点暂停,必要时优化查询或增加节点。
- 避免在主节点上运行大量数据写入或复杂聚合任务。
3. 确认主节点配置正确
对于 3 节点以上的集群,确保有奇数个具备主节点资格的节点:
# elasticsearch.yml
node.roles: [ master, data ] # 或单独设置 node.master: true
cluster.initial_master_nodes: # 仅在首次启动集群时需要
- "node1"
- "node2"
- "node3"
4. 重启节点时按顺序操作
- 先重启追随者节点,最后重启主节点,避免触发不必要的选举。
- 使用
_cluster/allocation/explainAPI 确认分片分配状态后再继续操作。
场景三:集群无法选出主节点 #
如果集群长时间无法选出主节点,可尝试:
# 强制将某个节点设为投票配置中的首选主节点(需谨慎操作)
curl -X POST "localhost:9200/_cluster/voting_config_exclusions?pretty"
# 检查投票配置
curl -X GET "localhost:9200/_cluster/state?filter_path=metadata.cluster_coordination&pretty"
5. 预防建议与最佳实践 #
- 保持奇数个主节点候选者:3 或 5 个具备
master角色的节点,避免偶数导致选举僵局。 - 分离主节点与数据节点:在规模较大的集群中,使用专用主节点(仅配置
node.roles: [ master ]),不参与数据存储和查询,降低资源竞争。 - 监控集群选举频率:通过 INFINI Console 监控集群状态变更历史,及时发现选举异常。
- 网络隔离:确保 Elasticsearch 节点间网络专享或优先保障,避免与高流量业务共用网络链路。
- 定期巡检:定期检查
_cluster/pending_tasksAPI,确认是否有堆积的任务影响集群稳定性。
借助 INFINI 产品提升排障效率 #
- INFINI Console 可实时查看集群健康状态、节点角色变更历史、选举频率和异常趋势,帮助快速判断是网络问题、资源问题还是配置问题。
- INFINI Gateway 可在集群不稳定时提供请求缓存和熔断保护,避免客户端因集群选举抖动而大量报错。
6. 小结 #
became follower 异常本身是 Elasticsearch 集群协调机制的一部分,表示节点在选举过程中角色发生了变更。单独的偶发异常通常无需处理;但如果频繁出现,则需要重点排查网络稳定性、节点资源使用和集群配置。通过建立完善的监控和遵循主节点配置最佳实践,可以有效降低此类异常的发生频率,保障集群稳定。
相关错误 #
- master-not-discovered-exception:未找到主节点
- node-left:节点离开集群
- cluster-block-exception:集群块异常
- not-master-exception:非主节点异常
- election-failed:选举失败
附:日志上下文 #
以下为源码中触发该异常的相关逻辑片段,便于结合异常调用栈定位问题:
// Coordinator.java 中处理加入请求的逻辑
if (newMode == Mode.LEADER) {
// 处理成为 leader 的逻辑
joiningTerm = ...
} else {
assert newMode == Mode.FOLLOWER : newMode;
// 当节点变为 follower 时,拒绝所有待处理的加入请求
joinRequestAccumulator.values()
.forEach(joinCallback -> joinCallback.v2().onFailure(
new CoordinationStateRejectedException("became follower")));
}
// CandidateJoinAccumulator is only closed when becoming leader or follower;
// otherwise it accumulates all joins received regardless of term.





