flashflight的专栏

was a coder, is a coder, to be a coder!

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

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,停止进行心跳检测。




阅读更多
个人分类: JAVA学习
上一篇数据库中间件Mycat源码解析(三):Mycat的SQL解析和路由
下一篇开发一款开源爬虫框架系列(一):分析nutch,scrapy的爬虫设计
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭