Heartbeat(心跳检测) 在Cobar中的主要用途是检查各个数据节点的连接是否正常,当连接出现问题时,则切换到备机;
1.它是如何被使用的?
CobarNode: 数据节点对象
CobarNodeConfig:数据节点连接设置
CommandPacket:执行语句封装
---startup()函数---
timer.schedule(dataNodeHeartbeat(), 0L, system.getDataNodeHeartbeatPeriod());
---dataNodeHeartbeat函数---
Map<String, MySQLDataNode> nodes = config.getDataNodes();
for (MySQLDataNode node : nodes.values()) {
node.doHeartbeat();
}
---doHeartbeat函数---
if (!heartbeat.isStop()) {
try {
heartbeat.heartbeat();
} catch (Throwable e) {
LOGGER.error(name + " heartbeat error.", e);
}
}
---heartbeat函数---
MySQLDetector detector = this.detector;
if (detector == null || detector.isQuit() || detector.isClosed()) {
try {
detector = factory.make(this);
} catch (Throwable e) {
LOGGER.warn(source.getConfig().toString(), e);
setError(null);
return;
}
this.detector = detector;
} else {
detector.heartbeat();
}
--detector验证登录并执行SQL检查连接--
2.如何在异常时切换到备用机
---I---NIOConnection
---register 注册网络事件
---read 读取数据
---handle 处理数据
---write 写出一块缓存数据
---writeByQueue 基于处理器队列的方式写数据
---writeByEvent 基于监听事件的方式写数据
---error 发生错误
---close 关闭连接
#继承关系
MySQLDetector-->A:BackendConnection-->A:AbstractConnection-->I:NIOConnection
#连接异常捕获
//授权异常,直接退出心跳检测
authenticate();
//捕获中断异常,调用虚函数error()
@Override
public void write(ByteBuffer buffer) {
if (isClosed.get()) {
processor.getBufferPool().recycle(buffer);
return;
}
if (isRegistered) {
try {
writeQueue.put(buffer);
} catch (InterruptedException e) {
error(ErrorCode.ERR_PUT_WRITE_QUEUE, e);
return;
}
processor.postWrite(this);
} else {
processor.getBufferPool().recycle(buffer);
close();
}
}
#MySQlDetector中实现error方法
@Override
public void error(int errCode, Throwable t) {
LOGGER.warn(toString(), t);
switch (errCode) {
case ErrorCode.ERR_HANDLE_DATA:
//完成备用机切换
heartbeat.setResult(MySQLHeartbeat.ERROR_STATUS, this, false);
break;
default:
heartbeat.setResult(MySQLHeartbeat.ERROR_STATUS, this, true);
}
}
关键点
1.使用Timer和TimeTask实现定时调度任务
2.CommandPacket封装Heartbeat语句,NIOConnection定义同一连接接口(error方法)
3.NIO方式完成通讯