1. sentinel客户端与服务端通信原理
2. 注解@SentinelResource核心源码剖析
3. Sentinel数据规则校验责任链设计模式详解
4. sentinel限流降级核心源码剖析
5. sentinel新版本熔断器核心源码剖析
6. sentinel资源授权与系统规则校验源码剖析
pom引入
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency>
application.yml配置
spring: application: #服务名,微服务用此名字注册服务并发现服务 name: deploy-order cloud: sentinel: transport: dashboard: localhost:8080
问题一 : sentinel客户端和服务端是如何进行通信的?
sentinel客户端启动时, 会提供 一系列的api url, 在这些api中就包含一个配置规则的url, 在sentinel服务端界面配置好的规则, 就会通过这个api推送给客服端,
(客户端项目启动, 可以访问 : localhost:端口/api来查看所有的api)
进行一下格式化
[
{
"url":"/cnode",
"desc":"get clusterNode metrics by id, request param: id={resourceName}"
},
{
"url":"/gateway/updateRules",
"desc":"Update gateway rules"
},
{
"url":"/setParamFlowRules",
"desc":"Set parameter flow rules, while previous rules will be replaced."
},
{
"url":"/gateway/getApiDefinitions",
"desc":"Fetch all customized gateway API groups"
},
{
"url":"/origin",
"desc":"get origin clusterNode by id, request param: id={resourceName}"
},
{
"url":"/tree",
"desc":"get metrics in tree mode, use id to specify detailed tree root"
},
{
"url":"/gateway/updateApiDefinitions",
"desc":""
},
{
"url":"/version",
"desc":"get sentinel version"
},
{
"url":"/gateway/getRules",
"desc":"Fetch all gateway rules"
},
{
"url":"/clusterNode",
"desc":"get all clusterNode VO, use type=notZero to ignore those nodes with totalRequest <=0"
},
{
"url":"/basicInfo",
"desc":"get sentinel config info"
},
{
"url":"/jsonTree",
"desc":"get tree node VO start from root node"
},
{
"url":"/getClusterMode",
"desc":"get cluster mode status"
},
{
"url":"/getParamFlowRules",
"desc":"Get all parameter flow rules"
},
{
"url":"/metric",
"desc":"get and aggregate metrics, accept param: startTime={startTime}&endTime={endTime}&maxLines={maxLines}&identify={resourceName}"
},
{
"url":"/setClusterMode",
"desc":"set cluster mode, accept param: mode={0|1} 0:client mode 1:server mode"
},
{
"url":"/systemStatus",
"desc":"get system status"
},
{
"url":"/getSwitch",
"desc":"get sentinel switch status"
},
{
"url":"/getRules",
"desc":"get all active rules by type, request param: type={ruleType}"
},
{
"url":"/api",
"desc":"get all available command handlers"
},
{
"url":"/setRules",
"desc":"modify the rules, accept param: type={ruleType}&data={ruleJson}"
},
{
"url":"/setSwitch",
"desc":"set sentinel switch, accept param: value={true|false}"
},
{
"url":"/clusterNodeById",
"desc":"get clusterNode VO by id, request param: id={resourceName}"
}
]
接下来就开始查看sentinel的源码
示例代码 :
/**
* Sentinel管控台结合@SentinelResource注解来实现服务限流以及熔断降级功能。
*
* blockHandler只负责sentinel控制台配置违规
* fallback只负责业务异常
*
* @param name
* @return
* @throws InterruptedException
*/
@GetMapping("test-sentinel-resource")
@SentinelResource(value = "/roder/create",
blockHandlerClass = MyBlockHandler.class,
blockHandler = "blockHandlerMethod",
fallback = "fallbackMethod")
public String testSentinelResource(@RequestParam(required = false) String name) throws InterruptedException {
Thread.sleep(100);
return "创建成功";
}
static class MyBlockHandler{
public String blockHandlerMethod(BlockException block){
return "这是一个限流降级方法";
}
}
public String fallbackMethod(){
return "这是一个熔断降级方法";
}
还是老规矩, 先查看sentinel自动装配的源码
可以看到这个就是一个切面类, 切点就是@SentinelResource这个注解,接下来仔细分析一下invokeResourceWithSentinel这个方法
进入主要方法
查看一下ProcessorSlots
最后拼接出来的链路是这样的
大家可能会好奇, 为啥NodeSelectorSlot在第一位, 这个因为这些类上都有一个
@SpiOrder()注解, 根据注解中的值来进行排序
责任链构建完成, 接下来我们回到最上层的方法
chain的子类很多, 根据我们查看源码的经验, 首先查看
DefaultProcessorSlotChain这个类
返回到上一次方法, 查看一下first是哪个类
看到fire, 在责任链中就知道快调用下一个方法了, 这个是看源码的经验, 进入fireEntry方法
transformEntry方法中, 调用责任链中第一个类的entry方法,
NodeSelectorSlot这个类是第一个类
NodeSelectorSlot查看这个类的entry方法, 也看不出所以然, 具体不知道想要做的是什么, 通过一个addChild像是拼接一个方法的请求路径
接下来再进入fireEntry方法, 同理的, 会进入责任链中的下一个类的entry方法,
具体是怎么跳转的和上面一下, 我们直接进入
ClusterBuilderSlot这个类的entry方法
这个entry还是没有发现他具体想要表达什么, 就继续向下看吧
LogSlot的entry方法
主要的作用是在异常的时候记录一些日志,继续向下看
StatisticSlot的entry方法
统计的entry方法, 在entry方法执行完成之后, 对一些数据进行统计, 先有一个印象, 后面会使用到
继续向下看
AuthoritySlot的entry方法
对应的是sentinel的授权规则, 这个方法也没有什么逻辑, 大家可以自己看一下
继续向下看,
SystemSlot的entry方法
对应的就是系统规则, 这个也不具体说明了,可以自己简单看一下
接下来就说一下最为关键的两个entry, 对应的是流控规则和降级规则
FlowSlot的entry方法
上面对应的集群配置按钮, 默认不勾选, 我们也先不查看集群配置
rule.getRater()方法返回
TrafficShapingController对象, 他们的子类包括上图, 对应sentinel可视化界面的以下几个按钮
默认是快速失败, 我们进入默认逻辑
说到这里, 这个entry就讲完了, 接下来看
DegradeSlot的entry方法
到这块断路器的源码解析就结束了, 大家可能会有疑惑, 现在熔断器 主要有三个状态, 关闭, 打开,半开, 到目前为止, 我们并没有看到状态之间的转换, 让我们回到最开始的方法来查看一下逻辑
到这里我们就可以猜到,状态的转变一定在DegradeSlot类的exit方法中, 我们看一下
对应的就是这些
我们进入慢调用比例的实现方法
还有一个异常的实现类, 大家可以自己看一下
到此, 源码讲解完毕
下一篇则会讲sentinel中的几个关键算法