01
—
前言
前面的文章我们学习了Hystrix并和springboot项目进行了集成,实现服务的熔断降级、隔离措施。但是Hystrix对流量的控制不是很好,仅仅信号量也只能对指定的接口进行限流,至于保护机制Hystrix也只是达到指标进行熔断。那么,有没有一种中间件可以在兼容熔断降级的同时精准实现流量控制和负载保护呢?回答是当然有的,就是我们今天的主角Spring Cloud Alibaba Sentinel。
02
—
知识积累
Sentinel 是面向分布式服务架构的高可用流量防护组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定。
流量控制
Sentinel 可以针对不同的调用关系,按照指定的指标进行流程整形控制。而且整形的策略有直接拒绝、慢启动预热和匀速器三大模式,开发者可用根据自身需求选用策略实现流量的精准控制。
负载保护
Sentinel 可用提供精准的负载保护机制,如果被调用服务达到最大负载会将请求负载均衡到其他服务提供者上面,如果其他服务也达到了最大负载则会启动服务保护机制让请求流量和服务的负载达到平衡。
熔断降级
Sentinel 也是提供了基础的熔断降级功能,如果服务提供着抛出一次会直接降级走fallback逻辑,如果是配置指标则走blockhander逻辑。当然,如果服务集群达到最大负载会执行熔断功能,防止服务雪崩的发生。
官方文档
https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D
03
—
实战演练
部署sentinel-dashboard
下载jar包
https://github.com/alibaba/Sentinel/releases
直接jar包部署
nohup java -jar -Dserver.port=8109 sentinel-dashboard.jar &
docker-compose编排
有条件的可以直接使用dashboard镜像,如果pull缓慢则考虑自己构建镜像。
dockerfile
# this is sentinel-dashboard dockerfile # version 1.0 # 基础镜像 FROM openjdk:8-jre # 维护人 MAINTAINER senfel<187@sina.cn> #jar COPY ./sentinel-dashboard.jar /home/app.jar # 端口 EXPOSE 8109 # 执行命令启动jar ENTRYPOINT ["java","-jar","/home/app.jar"]
docker-compose.yml
version: '3.3' services: sentinel: build: ./ image: senfel/sentinel-dashboard container_name: sentinel-dashboard ports: - 8109:8109 environment: JVM_OPTS: -server -Xmx512M -Xms512M -XX:MaxMetaspaceSize=256M -XX:CompressedClassSpaceSize=50M -XX:ReservedCodeCacheSize=240M -XX:MaxDirectMemorySize=400M logging: driver: "json-file" options: max-size: "10m" max-file: "1" volumes: - "/home/test/demo/sentinel/logs:/root/logs" - "/home/test/demo/sentinel/logs:/app-logs" command: [ "--server.port=8109", "--logging.file.path=/app-logs" ]
构件并启动容器
docker-compose up -d --build
查看sentinel容器
docker ps | grep sentinel
springboot集成sentinel
基础架构搭建
持久化流量控制规则,其他规则只需要增加配置即可
sentinel持久化到nacos 不持久每次重启都会清除规则
增加maven依赖
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> <version>2.2.9.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!--sentinel持久化到nacos 不持久每次重启都会清除规则--> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> <version>1.8.0</version> </dependency>
增加bootstrap.yml配置 nacos自行搭建
server: port: 9999 spring: application: name: test-demo profiles: active: uat cloud: nacos: config: server-addr: 10.10.18.16:8848,10.10.18.16:2848,10.10.18.16:5848 username: nacos password: nacos file-extension: yaml discovery: server-addr: 10.10.18.16:8848,10.10.18.16:2848,10.10.18.16:5848 username: nacos password: nacos sentinel: transport: dashboard: 10.10.22.174:8109 port: 8719 datasource: ds1: nacos: server-addr: 10.10.18.16:8848,10.10.18.16:2848,10.10.18.16:5848 dataId: test-demo-sentinel.json data-type: json rule-type: flow username: nacos password: nacos #开启sentinel feign: sentinel: enabled: true circuitbreaker: enabled: true
nacos新增限流配置
流量控制
resource:资源名称
limitApp:来源应用
grade:阈值类型,0代表线程数,1代表QPS
count:单击阈值
strategy:流控模式,0代表直接,1代表关联,2代表链路
controlBehavior:流控效果,0代表快速失败,1代表Warm Up,2代表排队等待
clusterMode:是否集群
-其他规则大同小异这里不再累述
-nacos配置与本文无关不再累述
[ { "resource": "testFeign", "limitApp": "default", "grade": 1, "count": 1, "strategy": 0, "controlBehavior": 0, "clusterMode": false } ]
启动类开启feign与nacos
@SpringBootApplication @EnableDiscoveryClient @EnableFeignClients @Slf4j public class TestDemoApplication implements ApplicationRunner { public static void main(String[] args) { SpringApplication.run(TestDemoApplication.class, args); } }
测试用例
/** * testFeign * fallback只负责业务异常 * blockHandler只负责sentinel配置超标 * 两个都配置,如果都出错,会进入blockHandler * @param str * @author senfel * @date 2023/7/11 14:26 * @return java.lang.String */ @SentinelResource(value = "testFeign",blockHandler = "blockHandler",fallback = "handlerFallback") @GetMapping("/testFeign") public String testFeign(String str){ if(str.contains("y")){ throw new RuntimeException(); } return testMQService.testFeign(str); } /** * 异常阻塞处理 * @param str * @author senfel * @date 2023/7/11 14:44 * @return java.lang.String */ private String blockHandler(String str, BlockException blockException){ return "blockHandler"+"-"+str; } /** * 降级处理 * @param str * @author senfel * @date 2023/7/11 14:44 * @return java.lang.String */ private String handlerFallback(String str,Throwable throwable){ return "handlerFallback"+"-"+str; }
openfeign降级测试用例
/** * @author senfel * @version 1.0 * @date 2023/7/03 15:04 */ @Service @FeignClient(value = "test-demo",fallback = FallbackService.class) public interface TestService { /** * 测试sentinel */ @GetMapping("/feign") String feign(@RequestParam String str); } /** * FallbackService * @author senfel * @version 1.0 * @date 2023/7/3 15:26 */ @Service public class FallbackService implements TestService { @Override public String feign(String str) { return ">>>>>客户端服务降级>>>>>"; } }
sentinel控制台
postman请求后查看 http://10.10.22.174:8109/
自动加载配置的流量规则
sentinel验证
验证主动控制流量
127.0.0.1:9999/testFeign?str=fffffffffss
验证异常控制流量
127.0.0.1:9999/testFeign?str=fffffffffyy
验证客户端feign降级
127.0.0.1:9999/testFeign?str=fffffffffss
查看实时监控
04
—
延伸:系统自适应限流
系统规则
系统保护规则是从应用级别的入口流量进行控制,从单台机器的 load、CPU 使用率、平均 RT、入口 QPS 和并发线程数等几个维度监控应用指标,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。
系统保护规则是应用整体维度的,而不是资源维度的,并且仅对入口流量生效。入口流量指的是进入应用的流量(EntryType.IN),比如 Web 服务或 Dubbo 服务端接收的请求,都属于入口流量。
系统规则支持以下的模式:
Load 自适应(仅对 Linux/Unix-like 机器生效):系统的 load1 作为启发指标,进行自适应系统保护。当系统 load1 超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR 阶段)。系统容量由系统的 maxQps * minRt 估算得出。设定参考值一般是 CPU cores * 2.5。
CPU usage(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏。
平均 RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。
原理
我们把系统处理请求的过程想象为一个水管,到来的请求是往这个水管灌水,当系统处理顺畅的时候,请求不需要排队,直接从水管中穿过,这个请求的RT是最短的;反之,当请求堆积的时候,那么处理请求的时间则会变为:排队时间 + 最短处理时间。
配置页面
05
—
传
Sentinel实现流量控制、熔断降级、负载保护的实际使用个人觉得还是比较简单,只需要根据官方文章集成和配置使用即可。sentinel的流量控制和负载保护以及高性能都优于hystrix,并提供可视化控制台。如果在可用性和可靠性较高和重要的服务集群场景中,可以优先考虑sentinel。