主文章:
http://blog.csdn.net/fei33423/article/details/53013333
1.流程:
选举流程: 了解算法.
2.边界:
外部通信边界(含客户端和服务端):
1.
1.1 QuorumCnxManager.toSend(Long, ByteBuffer) (org.apache.zookeeper.server.quorum)里生成一个客户端连接.
sock.connect(self.getView().get(sid).electionAddr, cnxTO);最终对socket绑定send和recWorker;SendWorker sw = new SendWorker(sock, sid);
RecvWorker rw = new RecvWorker(sock, sid, sw); //负责将无边界流阶段,size法,放到message类中.
1.2. QuorumCnxManager类里的属性 senderWorkerMap 保存着和其他服务器的server.accept连接.
QuorumCnxManager Listener类,主要启动socketServer,监听客户端消息.ss.bind(addr); 最终对socket绑定send和recWorker;
SendWorker sw = new SendWorker(sock, sid);
RecvWorker rw = new RecvWorker(sock, sid, sw); //负责将无边界流阶段,size法,放到message类中.
值的注意的两点:
1. server接受连接的的过程中,自动断开连接比自己id小的连接.( QuorumCnxManager.receiveConnection(Socket) )
2. 客户端连接和服务端连接的worker都是一样的,原因是客户端和服务端都是同构的,都是相同的zookeeper服务器.
3. QuorumCnxManager类增加了读写缓存,缓存的都是buffer信息.无业务含义(这点值的表扬,分层明确)
2. udp 入口.QuorumPeer udpSocket和 QuorumPeer.ResponderThread类
DatagramSocket udpSocket = new DatagramSocket(myQuorumAddr.getPort());
/** Mapping from Peer to Thread number */ final ConcurrentHashMap<Long, SendWorker> senderWorkerMap; final ConcurrentHashMap<Long, ArrayBlockingQueue<ByteBuffer>> queueSendMap;public final ArrayBlockingQueue<Message> recvQueue;
启动后负责客户端部分的读写,这个和选举里面的FastLeaderElection类里的sendQueue和receiveQueue结合一起了.
FastLeaderElection.Messenger.WorkerReceiver真正把message类里的byte[]数据转换为业务数据.
n.leader = response.buffer.getLong();
n.zxid = response.buffer.getLong();
n.electionEpoch = response.buffer.getLong();
n.state = ackstate;
n.sid = response.sid;
if(!backCompatibility){
n.peerEpoch = response.buffer.getLong();
} else {
if(LOG.isInfoEnabled()){
LOG.info("Backward compatibility mode, server id=" + n.sid);
}
n.peerEpoch = ZxidUtils.getEpochFromZxid(n.zxid);
}
/*
* Version added in 3.4.6
*/
n.version = (response.buffer.remaining() >= 4) ?
response.buffer.getInt() : 0x0;
<span style="color:#FF0000;">疑惑这些数据来自于哪里?</span>
主动发送的肯定是客户端操作,故通知别人的流程肯定是客户端发出,返回消息肯定是服务端数据.