大概流程
- dashboard启动初始化客户端InitFunc,其中包括通过SPI加载的CommandCenterInitFunc,HeartbeatSenderInitFunc,
- 执行CommandCenterInitFunc中的init方法,init方法中会执行CommandCenter的start方法,即通过SPI加载的SimpleHttpCommandCenter的beforeStart方法和start方法,
- 执行HeartbeatSenderInitFunc中的init方法,执行向 dashboard 发送心跳包scheduleHeartbeatTask方法
- dashboard 接收心跳将客户端 的机器信息保存在内存中
- dashboard 根据客户端的机器信息通过 httpClient 获取实时的统计数据
- 客户端 接收到请求之后,会找到具体的 CommandHandler 来处理
- 客户端将处理好的结果返回给 dashboard
dashboard启动初始化客户端InitFunc
执行到客户端的init方法,也就是sentinel-core模块中的InitExecutor这个类
执行CommandCenterInitFunc中的init方法
在beforeStart方法中加载了所有的CommandHandler,并放到一个Map中
在Start方法中则是开启了一个线程池,异步占用配置port的ServerSocket;
执行HeartbeatSenderInitFunc中的init方法
执行HeartbeatSenderInitFunc中的scheduleHeartbeatTask方法就是执行SimpleHttpHeartbeatSender中的sendHeartbeat方法,在这个方法里就是给dashboard发送心跳
dashboard 接收心跳将客户端 的机器信息保存在内存中
@ResponseBody
@RequestMapping("/machine")
public Result<?> receiveHeartBeat(String app, @RequestParam(value = "app_type", required = false, defaultValue = "0") Integer appType, Long version, String v, String hostname, String ip, Integer port) {
if (app == null) {
app = MachineDiscovery.UNKNOWN_APP_NAME;
}
if (ip == null) {
return Result.ofFail(-1, "ip can't be null");
}
if (port == null) {
return Result.ofFail(-1, "port can't be null");
}
if (port == -1) {
logger.info("Receive heartbeat from " + ip + " but port not set yet");
return Result.ofFail(-1, "your port not set yet");
}
String sentinelVersion = StringUtil.isEmpty(v) ? "unknown" : v;
version = version == null ? System.currentTimeMillis() : version;
try {
MachineInfo machineInfo = new MachineInfo();
machineInfo.setApp(app);
machineInfo.setAppType(appType);
machineInfo.setHostname(hostname);
machineInfo.setIp(ip);
machineInfo.setPort(port);
machineInfo.setHeartbeatVersion(version);
machineInfo.setLastHeartbeat(System.currentTimeMillis());
machineInfo.setVersion(sentinelVersion);
appManagement.addMachine(machineInfo);
return Result.ofSuccessMsg("success");
} catch (Exception e) {
logger.error("Receive heartbeat error", e);
return Result.ofFail(-1, e.getMessage());
}
}
获取客户端中规则
在笔者的初识Sentinel源码中已经介绍了获取规则的方法是fetchFlowRuleOfMachine,这里就不细说了,关注一个细节就是调用这个方法是在dashboad规则列表里;
那发送给客户端后客户端在哪里处理的这个请求的呢?还记得刚刚CommandCenterInitFunc中会加载的很多CommandCenter吗,客户端收到请求后会启动一个CommandCenter对外提供客户端的数据处理功能。刚刚介绍说会起一个线程池执行一个异步任务,这个任务就是接收dashboard请求的!!!ServerThread这个类。
具体如何找到哪个CommandCenter,有兴趣的可以自己查看下源码[思考]
这篇先到这,欢迎关注,将会持续更新