关闭

数据库中间件Mycat源码解析(四):Mycat的心跳管理

标签: mycat源码JAVA中间件
1248人阅读 评论(0) 收藏 举报
分类:

MyCat的服务端在启动时会执行node.startHeartbeat()去设置每个node的heartbeat的状态为DBHeartbeat.OK_STATUS,然后针对每个node节点启动一个线程去对对应的node发送heartbeat sql(比如select user())进行心跳检测。

private Runnable dataNodeHeartbeat() {
		return new Runnable() {
			@Override
			public void run() {
				timerExecutor.execute(new Runnable() {
					@Override
					public void run() {
						Map<String, PhysicalDBPool> nodes = config
								.getDataHosts();
						for (PhysicalDBPool node : nodes.values()) {
							node.doHeartbeat();
						}
					}
				});
			}
		};
	}

heatbeat类会调用heartbeat方法。

public void heartbeat() {
		final ReentrantLock lock = this.lock;
		lock.lock();
		try {
			//改变状态
			if (isChecking.compareAndSet(false, true)) {
				MySQLDetector detector = this.detector;
				if (detector == null || detector.isQuit()) {
					try {
						detector = new MySQLDetector(this);
						detector.heartbeat();
					} catch (Exception e) {
						LOGGER.warn(source.getConfig().toString(), e);
						setResult(ERROR_STATUS, detector, null);
						return;
					}
					this.detector = detector;
				} else {
					detector.heartbeat();
				}
			} else {
				MySQLDetector detector = this.detector;
				if (detector != null) {
					if (detector.isQuit()) {
						isChecking.compareAndSet(true, false);
					} else if (detector.isHeartbeatTimeout()) {
						setResult(TIMEOUT_STATUS, detector, null);
					}
				}
			}
		} finally {
			lock.unlock();
		}
	}
它会调用detector属性的heartbeat方法。

public void heartbeat() {
		lastSendQryTime = System.currentTimeMillis();
		MySQLDataSource ds = heartbeat.getSource();
		String databaseName = ds.getDbPool().getSchemas()[0];
		String[] fetchColms={};
		if (heartbeat.getSource().getHostConfig().isShowSlaveSql() ) {
			fetchColms=MYSQL_SLAVE_STAUTS_COLMS;
		}
		if (heartbeat.getSource().getHostConfig().isShowClusterSql() ) {
			fetchColms=MYSQL_CLUSTER_STAUTS_COLMS;
		}
		OneRawSQLQueryResultHandler resultHandler = new OneRawSQLQueryResultHandler( fetchColms, this);
		sqlJob = new SQLJob(heartbeat.getHeartbeatSQL(), databaseName, resultHandler, ds);
		sqlJob.run();
	}
它会获取数据源和数据库名,然后创建并注册一个OneRawSQLQueryResultHandler到sqlJob,再由这个job发送sql到数据库将结果取回交给注册的handler处理。

public boolean onRowData(String dataNode, byte[] rowData) {
		RowDataPacket rowDataPkg = new RowDataPacket(fieldCount);
		rowDataPkg.read(rowData);
		String variableName = "";
		String variableValue = "";
		//fieldcount为2可能是select x也可能是show create table命令
		if(fieldCount==2 && (fetchColPosMap.get("Variable_name")!=null || fetchColPosMap.get("Value")!=null)){
			Integer ind = fetchColPosMap.get("Variable_name");
			if (ind != null) {
				byte[] columnData = rowDataPkg.fieldValues.get(ind);
                String columnVal = columnData!=null?new String(columnData):null;
                variableName = columnVal;
            }
			ind = fetchColPosMap.get("Value");
			if (ind != null) {
				byte[] columnData = rowDataPkg.fieldValues.get(ind);
                String columnVal = columnData!=null?new String(columnData):null;
                variableValue = columnVal;
            }
            result.put(variableName, variableValue);
		}else{
			for (String fetchCol : fetchCols) {
				Integer ind = fetchColPosMap.get(fetchCol);
				if (ind != null) {
					byte[] columnData = rowDataPkg.fieldValues.get(ind);
	                String columnVal = columnData!=null?new String(columnData):null;
	                result.put(fetchCol, columnVal);
				} else {
					LOGGER.warn("cant't find column in sql query result " + fetchCol);
				}
			}
		}
		return false;
	}
如果客户端发送reload指令或stop指令到服务端就会修改hearbeat的状态为stop,停止进行心跳检测。




0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:257440次
    • 积分:337
    • 等级:
    • 排名:千里之外
    • 原创:82篇
    • 转载:13篇
    • 译文:0篇
    • 评论:25条
    最新评论