回顾
在前面的章节中:通过阐述sentinel简单使用、滑动窗口、核心流程源码分析把sentinel限流、熔断等主要功能说明清楚了,但我们在实际使用的过程中,不可能通过硬编码的方式设置规则,且规则也没法直观的维护,为此肯定是需要通过sentinel dashboard维护限流熔断规则
交互桥梁
在前面的章节中,也提到过。如果在单独的springboot项目中,想要和dashbaord做交互,需要引入如下依赖:
该依赖就是和dashbaord实现数据交互的桥梁,查看该模块的代码包情况:
其中重点需要关注的是:
com.alibaba.csp.sentinel.transport.command.SimpleHttpCommandCenter 服务端命令接收
com.alibaba.csp.sentinel.transport.heartbeat.SimpleHttpHeartbeatSender 维护心跳
源码分析
应用端
心跳:
在 SimpleHttpHeartbeatSender中有看到发送心跳的代码。但是:心跳是需要一直间隔发送的,此处只有发送的逻辑,未见间隔发送逻辑
所以肯定有个地方调用了该sendHeartbeat方法,跟踪代码,发现在:HeartbeatSenderInitFunc中有定时调度该方法:
再详细的分析调用接口地址和uri
uri:
至此,应用client到sentinel dashboard的心跳部分已经分析完成,既:
HeartbeartSenderInitFunc中定时调度HeartbeartSender#sendHeartbeat方法完成心跳功能,dashbaord的ip和端口是由应用启动时:-Dcsp.sentinel.dashboard.server参数指定的(具体的属性逻辑可以自己跟踪一下源码)
应用client端和dashbaord的命令交互
试想一下,在dashbaord上怎么获取到对应接入的应用的限流、熔断配置规则的?
在com.alibaba.csp.sentinel.transport.command.SimpleHttpCommandCenter中可以看到大量的关于网络通信的代码:
从代码中可以看到,CommandCentre中启动了一个本地服务器,用于监听连接。同样的,跟踪
com.alibaba.csp.sentinel.transport.command.SimpleHttpCommandCenter#start方法,发现在:
com.alibaba.csp.sentinel.transport.init.CommandCenterInitFunc#init方法完成初始化和调用,同时注意到:在正式调用start之前,做了一些初始化操作
处理器和请求类型的映射关系:
当接收到来自dashboard的http请求后会组装一个HttpEventTask,交由线程池处理:
最后根据请求类型,分配不同的处理完成处理过程:
以上是命令中心的核心逻辑。总结一下就是:
com.alibaba.csp.sentinel.transport.init.CommandCenterInitFunc#init调用com.alibaba.csp.sentinel.transport.command.SimpleHttpCommandCenter#beforeStart方法完成处理器注解名称和处理器的映射列表,然后启动BIO(依赖不同服务类型不同)的服务器监听
dashboard端
在应用client端有2个待处理的问题:
1 应用client发送的心跳到dashbaord如何处理的
2 client启动的tpc服务器,dashboard是怎么连接并发送请求到应用client端的?
心跳响应
在上面的client段心跳中,有提到过,请求的uri是:/registry/machine,在dashboard的源码中查找到对应的http接口:
接收到心跳信息之后是将数据存储在appManagement中
而AppManagement是MachineDiscovery的一个装饰器,真正干活的是:
com.alibaba.csp.sentinel.dashboard.discovery.SimpleMachineDiscovery
到这里心跳的逻辑已经梳理完成:
应用client端通过HeartbeatSenderInitFunc启动定时调度任务调用SimpleHttpHeartbeatSender#sendHeartbeat
方法往dashboard的/registry/machine接口请求,最终数据存储在com.alibaba.csp.sentinel.dashboard.discovery.SimpleMachineDiscovery的一个ConcurrentMap中完成数据统计
dashboard请求client的规则数据
通过跟踪dashboard的页面请求规则接口:/v2/flow/rules&/v1/flow/rules
最终数据请求委托给了:com.alibaba.csp.sentinel.dashboard.rule.FlowRuleApiProvider
而FlowRuleApiProvider最终真正获取数据是委托给了SentinelApiClient直连到对应的机器上完成规则内容获取的
一路跟踪最后来到发起http请求的入口:
到此,dashbaord想应用client端发送命令的过程总结一下:
CommandCenterInitFunc在初始化时,调用SimpleHttpCommandCenter#beforeStart方法完成处理器的初始化,最终组装成一个以处理器的CommandMapping注解的name属性为key,处理器为value的map对象。然后调用SimpleHttpCommandCenter#start()方法启动一个tcp服务器,监听tcp请求。dashbaord在获取规则内容时,通过com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient向应用client端发起http请求(应用client端的ip和端口通过心跳数据获取),完成整个过程
填坑
在第一章关于sentinel的简单使用中,有提到一个问题:为什么应用client端已经添加依赖,添加启动命令,并且启动成功之后,在dashboard的面板上无法看到对应的应用信息:
而且在做源码分析的时候也留了个坑:
在上面分析应用client端心跳时有提到:HeartbeatSenderInitFunc#init方法会启动定时调度功能完成心跳注册。而Env的这段静态代码块就是实现该功能的:
这里就是通过SPI机制,读取配置中实现了InitFunc接口的类完成初始化任务。间接的完成HeartbeatSenderInitFunc的处理化,从而往dashboard注册心跳。
而Env要运行静态代码块,是在SphU#entry方法触发的。 当然,如果你在启动应用时初始化一下Env类,肯定也是可以和dashboard完成心跳注册的:
以上:就是sentinel和dashbaord完成交互的全过程。关于sentinel的集群限流和数据持久化的问题,在关于sentinel运用的第五章中会完全解释。
创作不易,点赞、收藏、关注!