Sentinel 是啥?

分布式系统的流量防卫兵

引用一下之前我画的图:

image.png

流量防卫兵 它具备了哪些能力?

image.png

Sentinel 的生态环境

随着 Alibaba 的 Java 生态建设,包括 Spring Cloud AlibabaRocketNacos等多项开源技术的贡献,目前Sentinel 对分布式的各种应用场景都有了良好的支持和适配,这也是为什么我们选择 Sentinel 学习的原因之一(学习成本低,应用场景多)

image.png

Sentinel 核心概念

1、资源

资源Sentinel 中的核心概念之一。最常用的资源是我们代码中的 Java 方法,一段代码,或者一个接口

Java方法:

@SentinelResource("HelloWorld")
public void helloWorld() {// 资源中的逻辑System.out.println("hello world");
}

一段代码:

        // 1.5.0 版本开始可以直接利用 try-with-resources 特性,自动 exit entry
try (Entry entry = SphU.entry("HelloWorld")) {// 被保护的逻辑System.out.println("hello world");} catch (BlockException ex) {// 处理被流控的逻辑System.out.println("blocked!");}

一个接口:

@RestController
public class TestController {@GetMapping("/test")public String test(){return "test";}
}

配合控制台使用:

image.png

2、规则

Sentinel 中的规则 提供给用户,针对不同的场景而制定不同的保护动作,规则的类型包括:

  • 流量控制规则

  • 熔断降级规则

  • 系统保护规则

  • 来源访问控制规则

  • 热点参数规则

本文主要会讲解 流量熔断系统保护这三个规则。

定义规则:

    private static void initFlowRules(){List<FlowRule> rules = new ArrayList<>();FlowRule rule = new FlowRule();//绑定资源rule.setResource("HelloWorld");//限流阈值类型rule.setGrade(RuleConstant.FLOW_GRADE_QPS);//数量级别rule.setCount(20);//添加到本地内存rules.add(rule);FlowRuleManager.loadRules(rules);}

限流规则重要属性说明:

 

Sentinel 限流

1、单机限流

1.1、引入依赖

在上一篇文章中,有提到过 RateLimiter  实现的单机限流, 这里介绍一下,使用 Sentinel 实现的单机限流

//项目中引入 sentinel-core 依赖
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-core</artifactId><version>1.8.1</version>
</dependency>

1.2、定义限流规则

定义保护规则:

    private static void initFlowRules(){List<FlowRule> rules = new ArrayList<>();FlowRule rule = new FlowRule();//绑定资源rule.setResource("HelloWorld");//限流阈值类型rule.setGrade(RuleConstant.FLOW_GRADE_QPS);//数量级别rule.setCount(20);//添加到本地内存rules.add(rule);FlowRuleManager.loadRules(rules);}

1.3、定义限流资源

根据上面描述的 资源划分, 我们这里主要将 代码块  定义为资源。

public static void main(String[] args) {// 配置规则.initFlowRules();while (true) {// 1.5.0 版本开始可以直接利用 try-with-resources 特性,自动 exit entrytry (Entry entry = SphU.entry("HelloWorld")) {// 被保护的逻辑System.out.println("hello world");} catch (BlockException ex) {// 处理被流控的逻辑System.out.println("blocked!");}}
}

1.4、运行结果

Demo 运行之后,我们可以在日志 ~/logs/csp/${appName}-metrics.log.xxx 里看到下面的输出:

image.png
➜  csp cat com-jaycekon-sentinel-demo-FlowRuleDemo-metrics.log.2021-07-03|--timestamp-|------date time----|-resource-|p |block|s |e|rt
1625294582000|2021-07-03 14:43:02|HelloWorld|20|1720|20|0|2|0|0|0
1625294583000|2021-07-03 14:43:03|HelloWorld|20|5072|20|0|0|0|0|0
1625294584000|2021-07-03 14:43:04|HelloWorld|20|6925|20|0|0|0|0|0
  • p 代表通过的请求

  • block 代表被阻止的请求

  • s 代表成功执行完成的请求个数

  • e 代表用户自定义的异常

  • rt 代表平均响应时长

Sentinel 的单机限流 ,和 RateLimiter 有什么区别呢?

附录:《Sentinel - 滑动窗口实现原理》

2、控制台限流

2.1、客户端接入控制台

超详细文档,参考:《Sentinel - 控制台》

Sentinel 提供一个轻量级的开源控制台,它提供机器发现以及健康情况管理、监控(单机和集群),规则管理和推送的功能。

下载Jar 包(21M),或者下载源码(4M) 后自行进行编译(不建议,编译花的时间比直接下载jar包还要久)

https://github.com/alibaba/Sentinel/releases

编译后,启动命令

java -Dserver.port=8000 -Dcsp.sentinel.dashboard.server=localhost:8000 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.1.jar


进入控制台

image.png

2.2、引入依赖

客户端需要引入 Transport 模块来与 Sentinel 控制台进行通信。您可以通过 pom.xml 引入 JAR 包

<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-transport-simple-http</artifactId><version>1.8.1</version>
</dependency>//重要的依赖,还是提前先写上吧,避免小伙伴找不到了
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-web-servlet</artifactId><version>1.8.1</version>
</dependency>

然后!!!烦了我一下午的地方来了!!在官方文档中,指出了需要引入对应的依赖配置 , 好家伙,那么重要的话,你如此轻描淡写,脑壳疼啊!!!

image.png

对应的适配依赖有

  • 云原生微服务体系

  • Web 适配

  • RPC 适配

  • HTTP client 适配

  • Reactive 适配

  • Reactive 适配

  • Apache RocketMQ

好家伙,基本上所有业务场景都覆盖到了!由于我的Demo 项目是基于 SpringBoot ,然后想看看 云原生微服务体系下的视频,好家伙,要用 SpringCloud , 想要了解的,可以参考:  《Spring-Cloud-Sentinel》

2.3、定义资源

@SpringBootApplication
@Configuration
@RestController
public class SpringBootSentinelApplication {public static void main(String[] args) {SpringApplication.run(SpringBootSentinelApplication.class, args);}@Beanpublic FilterRegistrationBean sentinelFilterRegistration() {FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>();registration.setFilter(new CommonFilter());registration.addUrlPatterns("/*");registration.setName("sentinelFilter");registration.setOrder(1);return registration;}@RequestMapping("/index")public String index(){return "hello index";}}

在概述中,我们有提到过,需要被保护的资源,可以是 一个代码块一个方法或者一个接口。这里通过 Filter 的 方式,将所有请求都定义为资源 (/*), 那么我们在请求的过程就会变成这样子:

image.png

2.4 运行结果

添加启动参数

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

参数说明:

  • server.port : 服务启动端口

  • csp.sentinel.dashboard.server : 状态上报机器ip:端口

  • project.name : 监控项目名称

image.png

运行结果:

2.5 限流配置

image.png

流控效果

  • 1、快速失败:直接失败

  • 2、Warm Up:预热模式,根据codeFactory的值(默认3),从阈值/codeFactory,经过预热时长,才达到设置的QPS阈值。比如设置QPS为90,设置预热为10秒,则最初的阈值为90/3=30,经过10秒后才达到90。

  • 3、排队等待:比如设置阈值为10,超时时间为500毫秒,当第11个请求到的时候,不会直接报错,而是等待500毫秒,如果之后阈值还是超过10,则才会被限流。

运行结果:

image.png

image.png

3、集群限流

讲了那么多,终于要到核心的 集群限流方案了, 在秒杀系统设计中,我们谈到很多场景都是以单机作为具体案例进行分析,如果我们的系统要扩容,那么如何做好限流方案。假设集群中有 10 台机器,我们给每台机器设置单机限流阈值为10 QPS,理想情况下整个集群的限流阈值就为100 QPS。不过实际情况下流量到每台机器可能会不均匀,会导致总量没有到的情况下某些机器就开始限流。因此仅靠单机维度去限制的话会无法精确地限制总体流量。而集群流控可以精确地控制整个集群的调用总量,结合单机限流兜底,可以更好地发挥流量控制的效果。

介绍一下集群限流的核心角色:

  • Token Client:集群流控客户端,用于向所属 Token Server 通信请求 token。集群限流服务端会返回给客户端结果,决定是否限流。

  • Token Server:即集群流控服务端,处理来自 Token Client 的请求,根据配置的集群规则判断是否应该发放 token(是否允许通过)。

在嵌入模式下的结构图:

image.png

在独立模式下的结构图:

image.png

内嵌模式,即 发Token 的操作,有其中某一个实例完成,其他 Client 通过向 Server 请求,获取访问许可。

独立模式,即作为独立的 token server 进程启动,独立部署,隔离性好,但是需要额外的部署操作。

3.1、阿里云AHAS

在上述示例代码中,使用了本地模式的 Demo, 在集群限流的场景,这里用一下 阿里云提供的 AHAS 服务。

控制台地址:https://ahas.console.aliyun.com/index?ns=default&region=public

引入依赖:

//sentinel ahas 依赖,包括了sentinel的使用依赖
<dependency><groupId>com.alibaba.csp</groupId><artifactId>ahas-sentinel-client</artifactId><version>1.8.8</version>
</dependency>

这里有个要注意的点, AHAS 的依赖,包含了 Sentinel ,所需要使用到的依赖,包括 sentinel-core,sentinel-web-servletsentinel-transport-simple-http

否则会出现 Spi 异常 , 如果对 Spi 不太了解,建议加群提问,嘿嘿~

com.alibaba.csp.sentinel.spi.SpiLoaderException

image.png

image.png

3.2、开启阿里云AHAS 服务

这里有官方的开通文档,我就不赘述了,文档地址

在应用防护这里找到 Lincense ,然后添加启动参数:

-Dserver.port=8092 -Dproject.name=jaycekon-sentinel -Dahas.license=d1e21b0c8f2e4d87b5ac460b118dc58d -Dcsp.sentinel.log.use.pid=true

image.png

由于我们要本地启动多实例, 因此需要修改服务的多个端口:

java -Dserver.port=8090 -Dproject.name=jaycekon-sentinel -Dahas.license=d1e21b0c8f2e4d87b5ac460b118dc58d  -Dcsp.sentinel.log.use.pid=true -jar sentinel-ahas-0.0.1-SNAPSHOT.jarjava -Dserver.port=8091 -Dproject.name=jaycekon-sentinel -Dahas.license=d1e21b0c8f2e4d87b5ac460b118dc58d  -Dcsp.sentinel.log.use.pid=true -jar sentinel-ahas-0.0.1-SNAPSHOT.jarjava -Dserver.port=8092 -Dproject.name=jaycekon-sentinel -Dahas.license=d1e21b0c8f2e4d87b5ac460b118dc58d  -Dcsp.sentinel.log.use.pid=true -jar sentinel-ahas-0.0.1-SNAPSHOT.jar

产生访问流量后,可以在大盘看到机器的链接状态:

http://localhost:8092/index

image.png

3.3、集群流控规则配置

image.png

这里有个两个概念:

  • 集群阀值:指的是,我们集群总体能通过的访问量,可能存在分配不均的情况(能避免单机误限)。

  • 退化单机:当 Token Server 访问超时,即无法从远端获取令牌时,回退到单机限流

测试限流, 只访问 http://localhost:8092/index

通过手刷(手速过硬~),触碰到限流的临界值,然后整体限流跟我们预期一致。

image.png

退化单机

在集群流控这里,有个 Token 请求超时时间,Client 请求 Server ,然后返回数据结果。整个流程会有网络请求的耗时,在上面的测试流程中,我将超时时间调大了,每次请求都能拿到Token, 通过修改请求超时时间,触发退化 单机限流

image.png

运行结果:

image.png

3.4、Server 角色转换

在内嵌模式下,通过 HTTP API的方式,将角色转换为 Serverclient

http://<ip>:<port>/setClusterMode?mode=<xxx>

其中 mode 为 0 代表 client,1 代表 server,-1 代表关闭。注意应用端需要引入集群限流客户端或服务端的相应依赖。

在独立模式下,我们可以直接创建对应的 ClusterTokenServer 实例并在 main 函数中通过 start 方法启动 Token Server。

 

Sentinel 熔断

秒杀系统 的案例中,一个完整的链路可能包含了 下订单支付物流对接等多个服务(实际上不止那么少)。在一个完整的链路中,各个系统通过 rpc/http的形式进行交互,在下面的链路图中,如果用户选择的 支付方式,存在延时过高服务不稳定,或服务异常等情况,会导致整个链路没办法完成。最终的结果就是,用户明明抢到了,但是没办法支付,导致订单丢失。

image.png

现代微服务架构都是分布式的,由非常多的服务组成。不同服务之间相互调用,组成复杂的调用链路。以上的问题在链路调用中会产生放大的效果。复杂链路上的某一环不稳定,就可能会层层级联,最终导致整个链路都不可用。因此我们需要对不稳定的弱依赖服务调用进行熔断降级,暂时切断不稳定调用,避免局部不稳定因素导致整体的雪崩熔断降级作为保护自身的手段,通常在客户端(调用端)进行配置。

1、熔断降级

添加测试代码

    @RequestMapping("/myError")public String error(){if (true){throw new RuntimeException("sentinel run error");}return "error";}

降级保护效果:

用户通过访问接口 /myError , 出现一次异常后,在接下来的10秒 ,都会走降级策略,直接返回。能够很好的保护服务端避免异常过多,占用机器资源。同时快速响应用户请求。

2、熔断策略

Sentinel 提供以下几种熔断策略:

  • 慢调用比例 (SLOW_REQUEST_RATIO):选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。

  • 异常比例 (ERROR_RATIO):当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。

  • 异常数 (ERROR_COUNT):当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。

 

总结

本文主要详细讲解了一下 如何通过 Sentinel 去实际接触 限流和熔断,对于限流的底层实现,后续会有专门的源码分析篇。对于熔断,本文也没有细说个究竟,下一篇文章会给大家带来,熔断是什么,在系统中到底是怎么实际使用,以及常见的熔断策略。

项目源码地址:https://github.com/jaycekon/SpringBoot
欢迎  Star  和 Fork

有道无术,术可成;有术无道,止于术

欢迎大家关注Java之道公众号

好文章,我在看❤️

限流神器Sentinel,不了解一下吗?相关推荐

  1. 阿里限流神器Sentinel夺命连环 17 问?,nginx请求转发原理

    阿里限流神器Sentinel夺命连环 17 问?,nginx请求转发原理 前沿技术精品 2021-11-17 10:43:04 阅读数:77 评论数:0 点赞数:0 收藏数:0 标签:Sentinel ...

  2. 后端技术:阿里开源的接口限流神器Sentinel介绍

    Sentinel是阿里巴巴开源的限流器熔断器,并且带有可视化操作界面. 在日常开发中,限流功能时常被使用,用于对某些接口进行限流熔断,譬如限制单位时间内接口访问次数:或者按照某种规则进行限流,如限制i ...

  3. 限流神器Sentinel与nacos数据双向同步

    sentinel与springcloud.spring cload alibaba 版本选择 版本参考: 版本说明 · alibaba/spring-cloud-alibaba Wiki · GitH ...

  4. 阿里巴巴开源限流系统 Sentinel 全解析

    今年下半年阿里开源了自研的限流系统 Sentinel,官方对 Sentinel 的介绍中用到了一系列高大山的名词诸如 限流.熔断降级.流量塑形.系统负载保护等,还有漂亮的形容词诸如 轻巧.专业.实时等 ...

  5. 分布式系统并发请求限流平台Sentinel功能特性调研-集成测试(中篇)

    摘 要 随着近些年系统稳定性要求越来越高,而系统限流则是其中提高系统稳定性的手段之一,而在众多限流平台中Sentinel凭着丰富功能特性和多次阿里双十一的线上实践,成为最热门限流平台之一,本文就Sen ...

  6. 阿里开源分布式限流框架 -Sentinel Go 0.3.0 发布,支持熔断降级能力

    作者 | 宿何  阿里巴巴高级开发工程师 Sentinel 是阿里巴巴开源的,面向分布式服务架构的流量控制组件,主要以流量为切入点,从限流.流量整形.熔断降级.系统自适应保护等多个维度来帮助开发者保障 ...

  7. Java限流之 —— Sentinel初识

    前言 在之前的篇章中,我们聊到了限流的常用解决方案,基于限流衍生出了一些适合在并发场景下的解决方案,常用的像单机模式下的guawa限流,基于原生的限流算法如漏桶.令牌桶等封装出限流逻辑,redis+l ...

  8. Alibaba限流组件——Sentinel核心概念与流量控制

    目录 1 Sentinel介绍 1.1 Sentinel是什么 1.2 组成 1.3 关键概念 2 Sentinel流量控制案例 2.1 引入依赖 2.2 使用Sentinel提供的API实现流量控制 ...

  9. 服务熔断与限流:Sentinel

    目录 第一章 Sentinel的介绍 1.1.Sentinel是什么 1.2.Sentinel的特性 1.3.Sentinel的对比 第二章 Sentinel的安装与运行 2.1.下载Sentinel ...

最新文章

  1. 【Qt】报错error: undefined reference to `vtable for的解决方法
  2. GCD BZOJ2818 [省队互测] 数学
  3. lisp填写明细表对话框_用AutoLisp定制acad的对话框
  4. SQL Server查询正在执行的存储过程并停止
  5. 老年痴呆与LDL-C 低密度脂蛋白
  6. 【线性代数本质】1:向量究竟是什么
  7. 【实习生笔试面试】腾讯2013实习生电话面试总结
  8. 连接数据库超时设置autoReconnect=true
  9. DB中字段为null,为空,为空字符串,为空格要怎么过滤取出有效值
  10. SQL文测试数据时,注意对0件的测试!!!【0件时,防止空指针异常!】
  11. 详解利用ShoeBox制作位图字体
  12. Python基础学习----异常
  13. 注册为linux系统服务,注册程序为Linux系统服务并设置成自启动
  14. 3DMAx Panda Directx Exporter 导出 X插件
  15. java list逆序_Java使用ListIterator逆序ArrayList
  16. SQL SERVER 变量赋值
  17. 常用工具类 Math:数学计算 Random:生成伪随机数 SecureRandom:生成安全的随机数 2020-2-13
  18. PHP 导出excel表格的3种方法
  19. Double_array trie
  20. 个人开发者之路----野蛮生长

热门文章

  1. mysql 归类函数_mysql常用的函数归类
  2. html自动年份版权,如何将html5日期输入限制在合理的年份
  3. linux系统脚本安装失败,ubuntu16.04下vim安装失败的原因分析及解决方案
  4. php tea 算法 源码,PHP教程:TEA算法实现
  5. python识图找图_利用python进行识别相似图片(二)
  6. (数据库系统概论|王珊)第一章绪论-第一节:数据库系统概论
  7. 七种寻址方式(寄存器相对寻址方式)
  8. SSM项目使用example查询时多次查询条件相同
  9. LeetCode 413 等差数列划分
  10. zip2john工具爆破zip文件