Sentinel核心架构源码剖析(上)

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中的几个关键算法

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值