likes
comments
collection
share

Sentinel Dashboard 交互最核心的内容,拿下!

作者站长头像
站长
· 阅读数 11

👈👈👈 欢迎点赞收藏关注哟

一. 前言

Sentinel 数据交互是集群环境中非常重要的一环。

之前已经了解了 Sentinel 的核心拦截逻辑以及 Dashboard 的原理。这一篇来了解下 Sentinel 集群见交互的流程。

Dashboard 使用

Sentinel Dashboard 交互最核心的内容,拿下!

这里演示通过源码运行 Dashboard ,启动命令如下 :

-Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard

Sentinel Dashboard 交互最核心的内容,拿下!

  • S1 : 可以监控到当前应用的实时监控 , 意味着 Client 和 Dashboard 有实时交互
  • S2 : 可以查看到当前配置的流控信息,这个配置信息是从 Client 端拿到的

二. 原理解析

那么基于上面的案例,我们能明确的知道, Client 和 Dashboard 一定是有交互的,那么这个过程是怎么实现的呢?

👉 直接上原理 ,应付面试看这个就完事了

  • S1 : Sentinel 通过心跳上报自己的存在 -- SimpleHttpHeartbeatSender
  • S2 : Dashboard 接到请求后 , 拿到 Client 的 IP 和 端口号 存入 Map
  • S3 : Dashboard 基于端口信息 与 Client 会建立 Socket 连接,Dashboard 定时查询 Client 的各项信息 (Client 保存信息到 file 文件中)
  • S4 : Dashboard 保存信息到 Memory 内存 中

2.1 第一步 : 心跳流程

心跳流程的核心类为 :SimpleHttpHeartbeatSender ,在这个类中会发起一个 Http 请求到 Dashboard ,请求的接口为 : /registry/machine

// 1. 获取配置信息
public class TransportConfig {
    public static final String HEARTBEAT_DEFAULT_PATH = "/registry/machine";
}
C- TransportConfig # getHeartbeatApiPath


// 2. 发起 Http 请求
SimpleHttpRequest request = new SimpleHttpRequest(addrInfo, TransportConfig.getHeartbeatApiPath());
// --- 没什么东西,主要是版本以及当前开启的 Socket 端口 
request.setParams(heartBeat.generateCurrentMessage());
SimpleHttpResponse response = httpClient.post(request);

2.2 第二步 : Dashboard 接收到心跳

上面看到实际上会 HTTP 调用接口 ,调用到的是 MachineRegistryController 类, 看名字就知道,这个是用来注册机器节点的。

当调用到接口后 , 会保存这些信息 :

Sentinel Dashboard 交互最核心的内容,拿下!

然后首先传递到 AppManagement ,再传递到 MachineDiscovery (SimpleMachineDiscovery),最终存储到一个 Map 中

private final ConcurrentMap<String, AppInfo> apps = new ConcurrentHashMap<>();

2.3 第三步 : Client 存储访问信息

Sentinel 主要是本机单机运行的,他会将自己的流控信息存储到本地把配置发送到数据源 (Zookeeper 等)。

❓ 这里面总共涉及到3个核心的类 :

  • MetricWriter :用于写入指标数据的类。它提供了一些方法来将指标数据写入到指定的存储后端中
  • MetricsReader : 从指定的数据源读取指标文件
  • MetricSearcher : 从指定目录下找出所有的metric文件,并按照指定时间戳进行检索

📂 查找的路径如下 : C:\USER\logs\csp\service-metrics.log ,内容大致如下 :

1700483124000|2023-11-20 20:25:24|HelloWorld|224342|0|224341|0|0|0|0|0
1700483125000|2023-11-20 20:25:25|HelloWorld|75658|0|75659|0|0|0|0|0

关于内容和意义这里就不深入了,意义不大。

2.4 第四步 : Client 端建立 Socket 连接

  • 👉 1. 首先通过 SimpleHttpCommandCenter 建立连接 Socket
// 这里的端口就是之前上报 Dashboard 的端口
ServerSocket serverSocket = getServerSocketFromBasePort(port);
// 这里可以看出是通过一个线程池开启的 Socket 监听流程
executor.submit(new ServerThread(serverSocket));
  • 👉 2. 开启 Socket 后通过 HttpEventTask 进行持续的监听 : ServerThread
while (true) {
    // 一直保持接收
    socket = this.serverSocket.accept();
    HttpEventTask eventTask = new HttpEventTask(socket);
    bizExecutor.submit(eventTask);
}
  • 👉 3. 接收到 Command 的情况下调用对应的 Handler 处理 : HttpEventTask

// 通过  commandName 拿到对应的 Handler 
CommandHandler<?> commandHandler = SimpleHttpCommandCenter.getHandler(commandName);
// 处理 Handler 后生成对应的 Command 
CommandResponse<?> response = commandHandler.handle(request);
// 返回结果
handleResponse(response, printWriter);         

  • 👉 4. 调用 第三步的 Search 方法进行查询,查询到监控日志 : SendMetricCommandHandler
- 请求对象中会传递 startTime 和 endTime 进来,Client 就是基于这些参数进行查询
String startTimeStr = request.getParam("startTime");
String endTimeStr = request.getParam("endTime");
String maxLinesStr = request.getParam("maxLines");
String identity = request.getParam("identity");

// 查询第三步的日志记录
list = searcher.findByTimeAndResource(startTime, endTime, identity);
   

到这里 Client 端接收的流程就很清楚了,剩下的就是 Dashboard 的调用流程了!!

2.5 第五步 : 最重要的 Dashboard 请求数据查询

  • 前面已经知道了 ,Dashboard 知道了 Client 的 IP 和开启 Socket 的端口
  • Client 已经保存了当前的流控状态信息

这段逻辑的核心代码在 MetricFetcher 类中 :

  • S1 : 在初始化环节 会 Start() 一个 scheduleAtFixedRate 定时任务进行循环
  • S2 : 在定时任务 中调用 fetchAllApp 进行全量读取
  • S3 : 通过 AppManagement (第二步接收到的心跳数据)拿到所有的节点 App 信息
  • S4 : 调用 MetricFetcher # doFetchAppMetric 开始抓取指标信息
final String url = "http://" + machine.getIp() + ":" + machine.getPort() + "/" + METRIC_URL_PATH
    + "?startTime=" + startTime + "&endTime=" + endTime + "&refetch=" + false;
    
// http://192.168.0.14:8719/metric?startTime=1700484694000&endTime=1700484700000&refetch=false    

👉 当最终拿到结果后,把结果进行处理放入 Map , 最终在 writeMetric 方法存入 MetricsRepository

Sentinel Dashboard 交互最核心的内容,拿下!

// 默认实现是放在内存中 : 
public class InMemoryMetricsRepository implements MetricsRepository<MetricEntity> 

三. 补充知识点

3.1 关于 CommandHandler

Sentinel Dashboard 交互最核心的内容,拿下!

CommandHandler 是一个接口,它有大量的实现,每个实现都会有对应的功能,包括规则管理,上面说的数据上报等等

3.2 关于 Rule 的 Fetch

Dashboard 里面还有个重要的类为 :SentinelApiClient ,它主要的目的是与 Client 端关于规则的通信 :

  • S1 : 打开 Dashboard 控制台 , 触发接口调用 /machineResource.json
  • S2 : SentinelApiClient # executeCommand 基于对应的类型调用 Client
http://192.168.0.14:8719/metric?startTime=1700486200000&endTime=1700486206000&refetch=false

Sentinel Dashboard 交互最核心的内容,拿下!

格式和上面的一样,会调用到上面的 Handler, 至此流程全部串通❗❗❗

总结

就说这篇源码分析是不是很清晰吧

我想没看过代码都能了解得很清楚。

完结 🐼🐼🐼

转载自:https://juejin.cn/post/7303347466220781619
评论
请登录