天天看點

Sentinel源碼解析-用戶端與服務端互動流程

作者:打籃球的程式員

大概流程

  1. dashboard啟動初始化用戶端InitFunc,其中包括通過SPI加載的CommandCenterInitFunc,HeartbeatSenderInitFunc,
  2. 執行CommandCenterInitFunc中的init方法,init方法中會執行CommandCenter的start方法,即通過SPI加載的SimpleHttpCommandCenter的beforeStart方法和start方法,
  3. 執行HeartbeatSenderInitFunc中的init方法,執行向 dashboard 發送心跳包scheduleHeartbeatTask方法
  4. dashboard 接收心跳将用戶端 的機器資訊儲存在記憶體中
  5. dashboard 根據用戶端的機器資訊通過 httpClient 擷取實時的統計資料
  6. 用戶端 接收到請求之後,會找到具體的 CommandHandler 來處理
  7. 用戶端将處理好的結果傳回給 dashboard

dashboard啟動初始化用戶端InitFunc

Sentinel源碼解析-用戶端與服務端互動流程
Sentinel源碼解析-用戶端與服務端互動流程

執行到用戶端的init方法,也就是sentinel-core子產品中的InitExecutor這個類

執行CommandCenterInitFunc中的init方法

Sentinel源碼解析-用戶端與服務端互動流程

在beforeStart方法中加載了所有的CommandHandler,并放到一個Map中

Sentinel源碼解析-用戶端與服務端互動流程
Sentinel源碼解析-用戶端與服務端互動流程
Sentinel源碼解析-用戶端與服務端互動流程

在Start方法中則是開啟了一個線程池,異步占用配置port的ServerSocket;

執行HeartbeatSenderInitFunc中的init方法

Sentinel源碼解析-用戶端與服務端互動流程

執行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規則清單裡;

Sentinel源碼解析-用戶端與服務端互動流程

那發送給用戶端後用戶端在哪裡處理的這個請求的呢?還記得剛剛CommandCenterInitFunc中會加載的很多CommandCenter嗎,用戶端收到請求後會啟動一個CommandCenter對外提供用戶端的資料處理功能。剛剛介紹說會起一個線程池執行一個異步任務,這個任務就是接收dashboard請求的!!!ServerThread這個類。

Sentinel源碼解析-用戶端與服務端互動流程

具體如何找到哪個CommandCenter,有興趣的可以自己檢視下源碼[思考]

這篇先到這,歡迎關注,将會持續更新

繼續閱讀