大概流程
- 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,有興趣的可以自己檢視下源碼[思考]
這篇先到這,歡迎關注,将會持續更新