微服务组件 Sentinel(三)
一、整合 OpenFeign 进行降级#
1.1、引入依赖#
<dependencies>
<!-- Nacos 服务注册与发现 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--1.添加 openfeign 依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- sentinel 依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
</dependencies>
服务提供方的接口为
@RestController
@RequestMapping("/stock")
public class StockController {
@RequestMapping("/reduce2")
public String reduce2() {
int a = 1 / 0;
System.out.println("扣减库存!");
return "扣减库存:" + port;
}
}
1.2、加上 openfeign 接口的实现类#
@Component
public class StockFeignServiceFallback implements StockFeignService{
@Override
public String reduce2() {
return "降级了";
}
}
1.3、application.yml,启动 feign 对 sentinel 的整合#
feign:
sentinel:
# openfeign 整合 sentinel
enabled: true
1.4、在 openfeign 接口上配置 fallback 的实现类#
@FeignClient(value = "stock-server",path = "stock",contextId = "orderFeignSentinel",fallback = StockFeignServiceFallback.class)
public interface StockFeignService {
// 声明需要调用的 rest 接口对应的方法
@RequestMapping("/reduce2")
String reduce2();
}
启动服务,看到此时服务提供方和调用方都已注册到 nacos 了。
请求接口 http://localhost:8041/order/add
,发现针对远程服务进行了降级
二、热点参数限流(热点识别流控)#
热点即经常访问的数据,很多时候我们希望统计某个热点数据中访问频次最高的数据,并对其访问进行限制。常用的场景如热点商品的访问 / 操作控制,用户 / IP 防刷等。实现原理为热点淘汰策略(LRU)+ Token Bucket 流控。
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。
热点参数限流可以看做是一种特殊的流量控制, 仅对包含热点参数的资源调用生效。
准备接口
/**
* 热点规则,必须使用 @SentinelResource,是对参数 id 进行流控的
*/
@RequestMapping("/get/{id}")
@SentinelResource(value = "getById",blockHandler = "HotBlockHandler")
public String getById(@PathVariable("id")Integer id) {
System.out.println("正常访问");
return "正常访问";
}
public String HotBlockHandler(@PathVariable("id")Integer id,BlockException e) {
return "热点异常处理";
}
单机阈值:
1. 假设参数大部分值都是热点参数,那么单机阈值主要针对热点参数进行流控,后续额外对普通的参数值进行流控。
2. 假设大部值都是普通流量,则与上面相反。
配置热点参数规则注意:资源名必须是@SentinelResource(value="资源名")中配置的资源名,热点规则依赖于注解
假设这个参数,大部分情况下都是普通流量,只有少部分值是热点流量
先针对普通流量,QPS 设置为 10,然后进行编辑
然后对额外的热点流量进行流控设置,设置 QPS 为 2
发现,访问 id 为 2 时,只有超过 QPS 10 时,才会触发流控,但是访问 id 为 1 时,访问 QPS 超过 2 就出现流控了
三、系统规则#
在实际的生产环境中,可能会有如下问题
容量评估不到位,某个大流量接口限流配置不合理或没有配置,导致系统崩溃,来不及进行处理。
突然发现机器的Load和CPU usage等开始飚高,但却没有办法很快的确认到是什么原因造成的,也来不及处理。
当其中一-台机器挂了之后,本该由这台机器处理的流量被负载均衡到另外的机器上,另外的机器也被打挂了,引起系统雪崩。
这时,我们希望有个全局的兜底防护,即使缺乏容量评估也希望有一定的保护机制。即结合系统指标和服务容量,自适应动态调整流量
Sentinel 系统自适应限流从整体维度对应用入口流量进行控制,结合应用的Load、CPU 使用率、总体平均RT、入口 QPS 和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡, 让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。
- Load 自适应 (仅对 LinuxUnix-like 机器生效):系统的 load1 作为启发指标,进行自适应系统保护。当系统 load1 超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护 (BBR 阶段)。系统容量由系统的 maxQps * minRt 估算得出。设定参考值一般是 CPU cores * 2.5.
- CPU usage (1.5.0+ 版本) : 当系统 CPU 使用率超过阈值即触发系统保护 (取值范围 0.0-1.0) ,比较灵敏。
- 平均 RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
- 并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
- 入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。
可以看到系统负载基本在 15% 以上,设置系统保护为 cpu 阈值 20%
访问接口可以看到
四、规则持久化#
可以看到之前的无论是流控、降级、热点规则等,只要服务重启,就会丢失
sentinel 规则的推送有三种模式
推动模式 | 说明 | 优点 | 缺点 |
---|---|---|---|
原始模式 | API 将规则推送至客户端并直接更新到内存中,拓展写数据源(WritableDataSource) | 简单,无任何依赖 | 不保证一致性:规则保存在内存中,重启即消失,严重不建议用于生产环境 |
Pull 模式 | 拓展写数据源(WritableDataSource),客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 RDBMS,文件等 | 简单,无任何依赖,规则持久化 | 不保证一致性;实时性不保证,拉取过于频繁可能有性能问题 |
Push 模式 | 拓展读数据源(ReadableDataSource),规则中心统一推送,客户端通过注册监听的方式时刻监听变化,比如使用 Nacos、Zookeeper 等配置中心。这种方式有更好的实时性和一致性保证。生产环境一般采用 push 模式的数据源 | 规则持久化;一致性;快速 | 引入第三方依赖 |
4.1 原始模式#
如果不做任何修改,Dashboard 的推送虽则方式是通过 API 将规则推送至客户端并直接更新到内存中
这种做法的好处是简单,无依赖;坏处是应用重启,规则就会消失,仅用于简单测试,不能用于生产环境。
4.2、拉模式#
pull 模式的数据源 (如本地文件、RDBMS 等) 一般是可写入的。 使用时需要在客户端注册数据源:将对应的读数据源注册至对应的 RuleManager,将写数据源注册至 transport 的 WritableDataSourceRegistry 中。
4.3、推模式#
生产环境下一般更常用的是 push 模式的数据源。对于 push 模式的数据源,如远程配置中心 (ZooKeeper, Nacos, Apollo 等等), 推送的操作不应由 Sentinel 客户端进行,而应该经控制台统一进行管理,直接进行推送,数据源仅负责获取配置中心推送的配置并更新到本地。因此推送规则正确做法应该是配置中心控制台 / Sentinel 控制台→配置中心→Sentinel 数据源→Sentinel,而不是经 Sentinel 数据源推送至配置中心。这样的流程就非常清晰了
官方 demo:sentinel-demo-nacos-datasource
引入依赖
<dependencies>
<!--sentinel 启动器-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
</dependencies>
nacos 中创建如下配置
nacos 配置中心配置流控规则
系统规则
[
{
"resource": "order/flow",
"controlBehavior": 0,
"count": 2,
"grade": 1,
"limitApp": "default",
"strategy": 0
}
]
[
{
"avgRt": 10,
"highestSystemLoad": 5.0,
"maxTrhead": 10,
"qps": 20.0
}
]
application.yml 配置文件内容如下
server:
port: 8070
spring:
application:
name: order-sentinel
cloud:
sentinel:
transport:
dashboard: 192.168.33.62:8858
clientIp: 192.168.33.27
# 默认将调用链路收敛
web-context-unify: false
datasource:
# 可以自定义
flow-rule:
nacos:
server-addr: 192.168.33.62:8847
username: kunjuee
password: we753951.
data-id: order-sentinel-flow-rule
rule-type: flow
system:
nacos:
server-addr: 192.168.33.62:8847
username: kunjuee
password: we753951.
data-id: order-sentinel-system-rule
rule-type: system
流控规则
系统规则
本作品采用《CC 协议》,转载必须注明作者和本文链接