其代码主要是ZenDiscovery这个类,在它的innerJoinCluster()方法中,最主要的一部分代码就是
publicvoid innerJoinCluster() {
//.......
while (masterNode == null) {
masterNode = findMaster();
}
//......
}
一直阻塞直到找到master节点
private DiscoveryNode findMaster() {
// 连接其他节点,获取其他节点的信息
ZenPing.PingResponse[] fullPingResponses =pingService.pingAndWait(pingTimeout);
if (fullPingResponses == null) {
returnnull;
}
//过滤所有响应节点, 排除掉client节点,单纯的data节点
List<ZenPing.PingResponse> pingResponses = new ArrayList<>();
for (ZenPing.PingResponse pingResponse : fullPingResponses) {
DiscoveryNode node = pingResponse.node();
//排除掉client节点
if ((node.clientNode() || (!node.masterNode()&& !node.dataNode()))) {
}
//排除掉单纯的数据节点
elseif ((!node.masterNode() && node.dataNode())) {
}
//可以参与选举的节点
else {
pingResponses.add(pingResponse);
}
}
final DiscoveryNode localNode = clusterService.localNode();
List<DiscoveryNode> pingMasters = new ArrayList<>();
//获取所有响应节点中的master节点
for (ZenPing.PingResponse pingResponse : pingResponses) {
if (pingResponse.master() != null) {
if (!localNode.equals(pingResponse.master())) {
pingMasters.add(pingResponse.master());
}
}
}
Set<DiscoveryNode> activeNodes = Sets.newHashSet();
//如果本节点配置为可以参与master的选举,
//将本节点加入候选节点进行选举
if (localNode.masterNode()) {
activeNodes.add(localNode);
}
for (ZenPing.PingResponse pingResponse : pingResponses) {
activeNodes.add(pingResponse.node());
}
//集群没有一个正常的master,进行选举
if (pingMasters.isEmpty()) {
//保证选举数量,候选节点数量需大于等于配置的数量
if (electMaster.hasEnoughMasterNodes(activeNodes)) {
returnelectMaster.electMaster(activeNodes);
}
else {
returnnull;
}
}
//集群中已经有一个正常的master,这时候接受那个master
else {
return electMaster.electMaster(pingMasters);
}
}
public DiscoveryNodeelectMaster(Iterable<DiscoveryNode> nodes) {
//根据nodeId排序,选举第一个为master
List<DiscoveryNode>sortedNodes = sortedMasterNodes(nodes);
if (sortedNodes == null || sortedNodes.isEmpty()) {
returnnull;
}
returnsortedNodes.get(0);
}
这里来说明一下集群启动时master的选举场景:
假设有三个节点node1, node2, node3, 我们配置每个节点都有机会可以成为master(node.master: true)。
node1启动,此时node1去执行findMaster(),由于此时只有一个节点, node1只能发现自己这个节点, 不满足节点数大于n/2+1的条件(配置文件指定的),所以此时找不到master, node1会不断的执行while循环直到找到master位置。
然后node2启动,此时node2 通过ping可以发现node1,node1和node2构成了两个节点,可以知道activeNodes里面将会存放node1,node2,此时候选节点数量满足条件,选举并产生master节点。
此时node1 的循环又开始了,他就会发现master不是自己而是node2, 这样就会接受node2是master
然后第三个节点node3启动, 此时他也会执行while循环中的findMaster方法, 发现集群中已经有一个正常的master, 这时候也是接受那个master, 并加入集群。




