2.1 Master启动流程(HAService)
public void start() throws Exception {
this.acceptSocketService.beginAccept();
this.acceptSocketService.start();
this.groupTransferService.start();
this.haClient.start();
}
public void start() throws Exception {
this.acceptSocketService.beginAccept();
this.acceptSocketService.start();
this.groupTransferService.start();
this.haClient.start();
}
-
建立HA服务端监听服务,处理客户Slave客户端监听请求。
-
启动AcceptSocketService,处理监听逻辑。
-
启动GroupTransferService线程。
-
启动HA客户端线程。
不管是 Master 还是 Slave 都将按照上述流程启动,在内部的实现会根据 Broker 配置来决定真正开启的流程。
2.1.1 AcceptSocketService 实现原理
AcceptSocketService作为Master端监听Slave连接的实现类,作为HAService的内部类,其类图如图所示:
-
SocketAddress socketAddressListen:Broker服务监听套接字(本地IP+端口号)。
-
ServerSocketChannel serverSocketChannel:服务端Socket通道,基于NIO。
-
Selector selector:事件选择器,基于NIO。
HAService$AcceptSocketService#beginAccept
public void beginAccept() throws Exception {
this.serverSocketChannel = ServerSocketChannel.open();
this.selector = RemotingUtil.openSelector();
this.serverSocketChannel.socket().setReuseAddress(true);
this.serverSocketChannel.socket().bind(this.socketAddressListen);
this.serverSocketChannel.configureBlocking(false);
this.serverSocketChannel.register(this.selector, SelectionKey.OP_ACCEPT);
}
创建ServerSocketChannel、创建Selector、设置TCP reuseAddress、绑定监听端口、设置为非阻塞模式,并注册OP_ACCEPT(连接事件)。
HAService$AcceptSocketService#run
this.selector.select(1000);
Set selected = this.selector.selectedKeys();
if (selected != null) {
for (SelectionKey k : selected) {
if ((k.readyOps() & SelectionKey.OP_ACCEPT) != 0) {
SocketChannel sc = ((ServerSocketChannel) k.channel()).accept();
if (sc != null) {
HAService.log.info("HAService receive new connection, "+ sc.socket().getRemoteSocketAddress());
try {
HAConnection conn = new HAConnection(HAService.this, sc);
conn.start();
HAService.this.addConnection(conn);
} catch (Exception e) {
log.error(“new HAConnection exception”, e);
sc.close();
}
}
} else {
log.warn("Unexpected ops in select " + k.readyOps());
}
}
selected.clear();
}
该方法是标准的基于NIO的服务端程式实例,选择器每1s处理一次处理一次连接就绪事件。连接事件就绪后,调用ServerSocketChannel的accept()方法创建SocketChannel,与服务端数据传输的通道。然后为每一个连接创建一个HAConnection对象,该HAConnection将负责M-S数据同步逻辑。
2.1.2 GroupTransferService实现原理
GroupTransferService同步主从同步阻塞实现,如果是同步主从模式,消息发送者将消息刷写到磁盘后,需要继续等待新数据被传输到从服务器,从服务器数据的复制是在另外一个线程HAConnection中去拉取,所以消息发送者在这里需要等待数据传输的结果,GroupTransferService就是实现该功能,该类的整体结构与同步刷盘实现类(CommitLog$GroupCommitService)类似,本节只关注该类的核心业务逻辑doWaitTransfer的实现。
private void doWaitTransfer() {
synchronized (this.requestsRead) {
if (!this.requestsRea