天天看点

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,有兴趣的可以自己查看下源码[思考]

这篇先到这,欢迎关注,将会持续更新

继续阅读