服务保护
# Sentinel
Sentinel支持请求限流,服务熔断和服务降级,支持使用WEB页面控制台进行交互,控制台需要单独部署
Mavne依赖
<!-- Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- 其他依赖 可选项 -->
<!-- Sentinel数据持久化:Nacos -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
配置文件
spring:
cloud:
sentinel:
enabled: true # 是否启用Sentinel,默认为true
eager: false # 是否在项目启动后立即初始化Sentinel,默认为false
client-ip: 192.168.1.10 # 手动指定当前客户端IP,适用于容器化环境下IP识别的问题
http-method-specify: false # 将请求方法作为前缀,默认为false
transport: # Sentinel控制台配置
dashboard: localhost:8090 # Sentinel控制台地址
port: 8719 # 启用了Sentinel控制台后需要额外配置一个端口号用来与控制台进行交互,如果不配置会使用随机端口号
heartbeat-interval-ms: 1000 # 向控制台发送的心跳的时间间隔,默认1000ms
datasource: # 持久化数据源配置
flow: # 数据源名称,ds1 ds2 也可以 随便写
nacos: # 使用nacos作为数据源
server-addr: ${spring.cloud.nacos.server-addr}
username: ${spring.cloud.nacos.username}
password: ${spring.cloud.nacos.password}
dataId: ${spring.application.name}-flow.json
data-type: json # 配置文件类型
rule-type: flow # 规则类型
feign:
sentinel:
enabled: true # OpenFeigh启用Sentinel,默认为false
dubbo:
sentinel:
enabled: true # Dubbo启用Sentinel,默认为true
# Sentinel限流
# 流控规则flow
支持 QPS 和并发线程数两种方法进行限流,支持单节点以及集群节点设置限流阈值
流控模式分为三种:
1.直接:设置流控的资源一旦触发了限流阈值直接执行限流操作,简单直接
2.关联:设置流控检查关联的资源B,如果资源B达到了当前设置的流控,那么当前资源就会执行限流操作
3.链路:针对微服务调用链路生效,例如 C 设置了流控,A→B→C
会触发流控进行限制,不影响E→D→C
链路的执行
流控效果也分为三种:
1.快速失败:请求达到阈值时,超出的请求会被立即拒绝,抛出异常
2.Warm Up:服务启动或流量突然增大时,在设定的时间范围内慢慢增加阈值直至最大值,避免系统突然被大量请求压垮
3.排队等待:超出的请求会进行排队,当队列没有空余位置或者排队的请求达到超时时间会抛出异常
配置文件
[{
"resource": "/shop/getPage", // 资源名
"limitApp": "default", // 调用来源限制,default 表示不区分调用来源
"grade": 1, // 限流类型类型,0-并发线程数,1-QPS
"count": 10, // 限流阈值
"strategy": 0, // 流控模式,0-直接,1-关联,2-链路
"controlBehavior": 0, // 流控效果,0-快速失败,1-WarmUp预热模式,2-排队等待
"clusterMode": false, // 是否为集群模式
"clusterConfig": { // 集群配置,clusterMode=true时生效
"flowId": 12345, // 集群流控的唯一ID
"thresholdType": 0, // 集群阈值模式,0-单机均摊,1-总体阈值
"fallbackToLocalWhenFail": true // 失败退化
}
}]
# 熔断规则degrade
熔断是指某个服务请求超时或者抛出异常的次数达到设定好的阈值(一般是Sentinel控制台设置的阈值),会针对该微服务的请求快速响应一个失败的结果,防止由于单个微服务异常造成整体雪崩现象,属于微服务链路保护措施
# 系统保护system
# 授权规则authority
# 热点参数param-flow
# 网关流控gw-flow
# Sentinel降级
在 Sentinel 中默认每个接口都会被识别为一个资源,通过资源名称设置限流(QPS,线程,熔断等)超出的流量抛出异常后可以对这些请求进行降级处理
需要注意的是就算每个接口都被识别为一个资源,在使用降级的时候也需要手动生命资源名称,且不能与自动识别的资源名重复,如果一定要按照接口路径风格取名,建议启用sentinel.http-method-specify
配置防止名称重复
@Sentinel
注解的属性:
- value:资源名称
- blockHandler:限流或熔断后降级处理的方法名
- blockHandlerClass:限流或熔断后降级处理方法所在的类
- fallback:资源异常处理的降级方法
- fallbackClass:资源异常处理降级方法所在的类
- defaultFallback:默认异常处理的方法名,适用于全局异常处理
限流降级处理
@RestController
@RequestMapping("/order")
public class ShopOrderController {
@Resource
private IShopOrderService service;
@GetMapping("/getPage")
@SentinelResource(value = "/order/getPage", blockHandler = "getPageFallback")
public R<PageVO<ShopOrder>> getPage() {
return new R.Ok<>(service.getPage());
}
// 方法签名保持一致,在原本的参数列表中添加 BlockException 异常对象,用于接受限流异常信息
public R<PageVO<ShopOrder>> getPageFallback(BlockException ex) {
return new R.Ok<>(PageUtil.getEmptyResult());
}
}
熔断降级处理
@RestController
@RequestMapping("/order")
public class ShopOrderController {
@Resource
private IShopOrderService service;
@GetMapping("/getPage")
@SentinelResource(value = "/order/getPage", fallback = "getPageFallback")
public R<PageVO<ShopOrder>> getPage() {
return new R.Ok<>(service.getPage());
}
public R<PageVO<ShopOrder>> getPageFallback(Exception ex) {
return new R.Ok<>(PageUtil.getEmptyResult());
}
}
# 配置持久化
Sentinel 提供了三种数据推送规则:
原始模式:控制台操作通过 API 将规则推送至微服务接更新到内存中,简单快捷使用方便但不保证一致性,规则重启即消失,不建议用于生产环境 Pull模式:将规则写入RDBMS、文件等,简单无任何依赖,规则持久化,不保证一致性和实时性,拉取过于频繁也可能会有性能问题 Push模式:规则中心统一推送,客户端通过注册监听器的方式时刻监听变化,比如使用配置中心(Nacos),有更好的实时性和一致性保证,适用于生产环境
Sentinel Nacos 双向更新
默认微服务启动后会读取 Naoos 上预先配置好的 Sentinel 规则以实现持久化,Nacos 上的改动会实时更新到 Sentinel,但 Sentinel 控制台上的修改无法持久化到 Nacos 中,想要实现双向更新需要额外编写一个配置类
// TODO