目录
- 一、Sentinel介绍
- 二、Sentinel安装
- 三、Sentinel初体验
- 四、Sentinel流控规则
-
- [QPS限制 - 快速失败](#QPS限制 - 快速失败)
- [QPS限制 - Warm Up](#QPS限制 - Warm Up)
- [QPS限制 - 排队等待](#QPS限制 - 排队等待)
- [QPS限制 - 关联 - 快速失败](#QPS限制 - 关联 - 快速失败)
- [QPS限制 - 链路 - 快速失败](#QPS限制 - 链路 - 快速失败)
- [并发线程数 - 快速失败](#并发线程数 - 快速失败)
- 五、Sentinel熔断降级
- 六、Sentinel规则持久化
- 七、OpenFeign整合Sentinel
一、Sentinel介绍
首先附上官方文档地址
Sentinel是为了解决两个核心问题
-
流量控制
-
熔断降级
二、Sentinel安装
具体可参考官方文档
-
下载jar包,下载地址
-
执行命令java -jar sentinel-dashboard-1.8.7.jar启动sentinel服务,默认端口号为8080

-
登录,从 Sentinel 1.6.0 起,Sentinel 控制台引入基本的登录功能,默认用户名和密码都是 sentinel。

这就算启动成功了。
三、Sentinel初体验
- 项目中导入依赖
xml
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
- 在需要限流、降级的资源上添加@SentinelResource注解
思考:@SentinelResource注解需要打在什么样的资源上?
java
@GetMapping("/info")
@SentinelResource("info")
public String getInfo() {
return info;
}
- 在项目中添加dashboard配置
yml
spring:
cloud:
sentinel:
transport:
port: 8719
dashboard: localhost:8080
启动项目后调用一下资源,就可以在dashboard看到应用了
四、Sentinel流控规则
QPS限制 - 快速失败
设置单机阈值为1,代表每秒只能有一个请求命中该资源,第二个请求会直接失败


QPS限制 - Warm Up
预热时长代表十秒后预热到每秒支持10QPS,适用于冷启动。

QPS限制 - 排队等待
单机阈值为2代表每500ms处理一个资源请求,设置了超时时间为500ms意思是如果一个请求需要等待超过500ms就会直接报错。

QPS限制 - 关联 - 快速失败
首先,我们新加一个资源
java
@GetMapping("/dep")
@SentinelResource("dep")
public String getDep() {
return "dep";
}
添加关联规则 ,表示如果info所关联的资源dep超过了阈值,则info会被限制访问,访问dep不会报错,但访问info会报错。

QPS限制 - 链路 - 快速失败
链路模式表示从链路入口限流,具体参考文档
新添加一个common资源,从两个入口访问。
java
// resource
@Service
public class OrderServiceImpl implements OrderService {
@Override
@SentinelResource("common")
public String common() {
return "common";
}
}
// controller
@GetMapping("/aaa")
public String getAaa() {
return orderService.common();
}
@GetMapping("/bbb")
public String getBbb() {
return orderService.common();
}
但是目前所有的资源入口都是sentinel_spring_web_context,不能把aaa和bbb分开。

解决方案 添加如下配置,关闭聚合入口
yml
spring:
cloud:
sentinel:
web-context-unify: false
最外层的入口就变为了controller层的入口

此时添加链路限制

访问aaa时成功限流,访问bbb时则无限流。
并发线程数 - 快速失败
单机阈值设置为1,表示同时只能有一个线程处理该资源,可通过thread.sleep测试。

五、Sentinel熔断降级
熔断、降级介绍
要知道为什么需要熔断、降级,我们需要先了解一下服务雪崩。
服务雪崩:因为某一个服务出现问题,导致其他服务,甚至整个系统崩溃的情况,就可以称为服务雪崩。
- 降级:针对一些资源,提供一个降级方法,当这个资源出现一些问题时,可以快速失败,执行降级方法,返回托底数据。
- 熔断 :就是针对某个资源提供断路器,有Closed、Open、Half Open状态,是触发降级的手段之一

Closed:代表资源正常,可以访问。(默认状态)
Open:资源出现问题(错误率达到阈值),访问时直接快速失败,执行降级方法,返回托底数据
Half Open:尝试请求资源(Open状态持续5s后,将断路器修改为Half Open状态):
- 如果处理正常,状态修改为Closed。
- 如果处理失败,状态修改为Open。
熔断规则
添加测试代码:
java
@GetMapping("/circuit-breaker")
public String circuitBreaker(@RequestParam String value) throws InterruptedException {
switch (value) {
// 模拟超时
case "1":{
Thread.sleep(1000);
break;
}
// 模拟异常
case "2":{
int i = 1/0;
break;
}
}
return "circuit-breaker success";
}
-
慢调用比例 (SLOW_REQUEST_RATIO):选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。

多次调用后出现默认降级:

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

多次请求后由返回错误信息变为返回默认降级:

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

降级方法
使用@SentinelResource注解来绑定降级方法
- blockHandler:
- 对应处理BlockException的函数名称
- 函数访问范围需要时public
- 返回类型需要和原方法相匹配, 并且最后加一个额外的参数,类型为 BlockException
- 函数默认和原方法在同一个类中
java
@GetMapping("/circuit-breaker")
@SentinelResource(value = "circuit-breaker", blockHandler = "circuitBreakerFallback")
public String circuitBreaker(@RequestParam String value) throws InterruptedException {
switch (value) {
// 模拟超时
case "1": {
Thread.sleep(1000);
break;
}
// 模拟异常
case "2": {
int i = 1 / 0;
break;
}
}
return "circuit-breaker success";
}
// 必须是BlockException
public String circuitBreakerFallback(String value, BlockException ex) {
return "circuit-breaker fallback " + ex.getMessage();
}
普通异常不会处理:

添加限流规则

https://sentinelguard.io/zh-cn/docs/annotation-support.html
热点规则
Sentinel 利用 LRU 策略统计最近最常访问的热点参数,结合令牌桶算法来进行参数级别的流控。
- 添加测试代码
java
@GetMapping("/order/hot")
@SentinelResource(value = "hot")
public String hot(String userId, Integer type){
return "userId:" + userId + " type:" + type;
}
- 在sentinel dashboard界面添加新的热点规则


Note: 热点规则只支持基本参数类型,不支持复合结构类型。支持@PathVariable @PathParam两种参数方式。
授权规则
黑白名单根据资源的请求来源(origin)限制资源是否通过,若配置白名单则只有请求来源位于白名单内时才可通过;若配置黑名单则请求来源位于黑名单时不通过,其余的请求通过。
Note:通常用于只开放给gateway服务的接口资源
- sentinel通过RequestOriginParser获取origin的值并且没有默认实现,所以先添加RequestOriginParser实现类。
java
package com.hxd.sentinel;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
@Component
public class SentinelRequestOriginParser implements RequestOriginParser {
@Override
public String parseOrigin(HttpServletRequest request) {
String origin = request.getHeader("origin");
return origin == null ? "" : origin;
}
}
- 添加测试api
java
@GetMapping("/order/author")
@SentinelResource(value = "author")
public String author(){
return "author!";
}
- 添加授权规则,只有appA才能访问该资源

- 使用postman访问,并在请求头中添加origin:appA,访问成功。

系统规则
系统规则支持以下的阈值类型:
- Load(仅对 Linux/Unix-like 机器生效):当系统 load1 超过阈值,且系统当前的并发线程数超过系统容量时才会触发系统保护。系统容量由系统的 maxQps * minRt 计算得出。设定参考值一般是 CPU cores * 2.5。
- CPU usage(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0)。
- RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
- 线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
- 入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。
六、Sentinel规则持久化
通过官网可以得知我们可以通过两种方式修改规则:
- 通过 API 直接修改 (loadRules) (只接受内存态)
- 通过 DataSource 适配不同数据源修改**(对接任意配资源)**
DataSource 扩展常见的实现方式有:
- 拉模式:客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 RDBMS、文件,甚至是 VCS 等。这样做的方式是简单,缺点是无法及时获取变更;
- 推模式:规则中心统一推送,客户端通过注册监听器的方式时刻监听变化,比如使用 Nacos、Zookeeper 等配置中心。这种方式有更好的实时性和一致性保证。
推模式:使用 Nacos 配置规则
- 导入依赖
xml
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
- 在项目中添加配置
yml
spring:
sentinel:
datasource:
flow:
nacos:
data-id: ${spring.application.name}-flow.json
group-id: SENTINEL_GROUP
data-type: json
rule-type: flow
server-addr: ${spring.cloud.nacos.config.server-addr}
- 在nocas中添加配置文件
Note: JSON格式最外层需要加大括号,否则不生效。JSON中需要的配置属性可以在AbstractRule类中找。

七、OpenFeign整合Sentinel
- 开启配置
xml
feign.circuitbreaker.enabled=true
- 创建Fallback类
java
package com.hxd.client.fallback;
import com.hxd.client.StockClient;
import org.springframework.stereotype.Component;
@Component
public class StockClientFallback implements StockClient {
@Override
public String getStock() {
return "stock fallback method!";
}
}
- 在@FeignClient注解中指定fallback类
java
@FeignClient(value = "stock", fallback = StockClientFallback.class)
public interface StockClient {
@GetMapping("/test/stock")
String getStock();
}
