👈👈👈 欢迎点赞收藏关注哟
首先分享之前的所有文章 >>>> 😜😜😜
文章合集 : 🎁 juejin.cn/post/694164...
Github : 👉 github.com/black-ant
CASE 备份 : 👉 gitee.com/antblack/ca...
一. 前言
Sentinel 数据交互是集群环境中非常重要的一环。
之前已经了解了 Sentinel 的核心拦截逻辑以及 Dashboard 的原理。这一篇来了解下 Sentinel 集群见交互的流程。
Dashboard 使用
这里演示通过源码运行 Dashboard ,启动命令如下 :
java
-Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=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
java
// 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
类, 看名字就知道,这个是用来注册机器节点
的。
当调用到接口后 , 会保存这些信息 :
然后首先传递到 AppManagement
,再传递到 MachineDiscovery (SimpleMachineDiscovery
),最终存储到一个 Map 中
java
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 ,内容大致如下 :
java
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
java
// 这里的端口就是之前上报 Dashboard 的端口
ServerSocket serverSocket = getServerSocketFromBasePort(port);
// 这里可以看出是通过一个线程池开启的 Socket 监听流程
executor.submit(new ServerThread(serverSocket));
- 👉 2. 开启 Socket 后通过 HttpEventTask 进行持续的监听 :
ServerThread
java
while (true) {
// 一直保持接收
socket = this.serverSocket.accept();
HttpEventTask eventTask = new HttpEventTask(socket);
bizExecutor.submit(eventTask);
}
- 👉 3. 接收到 Command 的情况下调用对应的 Handler 处理 :
HttpEventTask
java
// 通过 commandName 拿到对应的 Handler
CommandHandler<?> commandHandler = SimpleHttpCommandCenter.getHandler(commandName);
// 处理 Handler 后生成对应的 Command
CommandResponse<?> response = commandHandler.handle(request);
// 返回结果
handleResponse(response, printWriter);
- 👉 4. 调用 第三步的 Search 方法进行查询,查询到监控日志 :
SendMetricCommandHandler
java
- 请求对象中会传递 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 开始抓取指标信息
java
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 中
java
// 默认实现是放在内存中 :
public class InMemoryMetricsRepository implements MetricsRepository<MetricEntity>
三. 补充知识点
3.1 关于 CommandHandler
CommandHandler 是一个接口,它有大量的实现,每个实现都会有对应的功能,包括规则管理,上面说的数据上报等等
3.2 关于 Rule 的 Fetch
Dashboard 里面还有个重要的类为 :SentinelApiClient ,它主要的目的是与 Client 端关于规则的通信 :
- S1 : 打开 Dashboard 控制台 , 触发接口调用
/machineResource.json
- S2 : SentinelApiClient #
executeCommand
基于对应的类型调用 Client
java
http://192.168.0.14:8719/metric?startTime=1700486200000&endTime=1700486206000&refetch=false
格式和上面的一样,会调用到上面的 Handler, 至此流程全部串通❗❗❗
总结
就说这篇源码分析是不是很清晰吧
我想没看过代码都能了解得很清楚。
完结 🐼🐼🐼