💧 分布式流控组件 S e n t i n e l 快速入门 \color{#FF1493}{分布式流控组件 Sentinel 快速入门} 分布式流控组件Sentinel快速入门💧
🌷 仰望天空,妳我亦是行人.✨
🦄 个人主页——微风撞见云的博客🎐
🐳 《数据结构与算法》专栏的文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺
💧 《Java学习笔记》专栏的文章是本人在Java学习中总结的一些知识点~ 💐
🥣 《每天一点小知识》专栏的文章可以丰富你的知识库,滴水成河~ 🌊
🎐 《Redis》专栏的文章是在学习Redis时,整理的笔记与记录的思考~ 🥏
🥕 《RabbitMQ》专栏的文章是在学习尚硅谷课程时整理的笔记,方便复习巩固~ 🍑
🪁 希望本文能够给读者带来一定的帮助~🌸文章粗浅,敬请批评指正!🐥
Sentinel是阿里巴巴开源的分布式系统的流量控制组件,旨在保护分布式系统在高并发和故障情况下的稳定性。它提供了实时的流量控制、熔断降级、系统负载保护等功能,是微服务架构中不可或缺的一环。
💧Sentinel控制台是Sentinel的管理工具,可以帮助您监控和管理Sentinel的各种规则和限制。安装步骤如下:
💧注解@SentinelResource用于标记受Sentinel保护的资源,可以定义资源的限流和降级策略。
@SentinelResource(value = "protectedResource", blockHandler = "handleBlock", fallback = "handleFallback") public void protectedResource() { // 处理受保护的资源逻辑 } public void handleBlock(BlockException ex) { // 处理流控逻辑 } public void handleFallback(Throwable ex) { // 处理降级逻辑 }
💧在使用Sentinel之前,我们需要在应用程序中进行配置。例如,在Spring Cloud项目中,添加Sentinel的依赖,并配置相关参数。通常需要结合nacos一起使用:
com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery com.alibaba.cloud spring-cloud-starter-alibaba-sentinel
💧然后,在application.yml中配置Sentinel相关参数,这样,nacos8080 将会监控 8401服务
server: port: 8401 spring: application: name: cloudalibaba-sentinel-service cloud: nacos: discovery: server-addr: localhost:8848 #Nacos服务注册中心地址 sentinel: transport: dashboard: localhost:8080 #配置Sentinel dashboard地址 port: 8719 datasource: #<---------------------------关注点,添加Nacos数据源配置 ds1: nacos: server-addr: localhost:8848 dataId: cloudalibaba-sentinel-service groupId: DEFAULT_GROUP data-type: json rule-type: flow
💧添加几个方法用于测试
@RestController @Slf4j public class FlowLimitController { @GetMapping("/testA") public String testA() { /* try { TimeUnit.MILLISECONDS.sleep(800); } catch (InterruptedException e) { e.printStackTrace(); }*/ return "------testA"; } @GetMapping("/testB") public String testB() { log.info(Thread.currentThread().getName() + "\t" + "...testB"); return "------testB"; } @GetMapping("/testD") public String testD() { try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } log.info("testD 测试RT"); return "------testD"; } @GetMapping("/testE") public String testE() { log.info("testE 测试异常数"); int age = 10 / 0; return "------testE 测试异常数"; } @GetMapping("/testHotKey") @SentinelResource(value = "testHotKey", blockHandler/*兜底方法*/ = "deal_testHotKey") public String testHotKey(@RequestParam(value = "p1", required = false) String p1, @RequestParam(value = "p2", required = false) String p2) { //int age = 10/0; return "------testHotKey"; } /*兜底方法*/ public String deal_testHotKey(String p1, String p2, BlockException exception) { return "------deal_testHotKey,o(╥﹏╥)o"; //sentinel系统默认的提示:Blocked by Sentinel (flow limiting) } }
💧运行主启动类
@EnableDiscoveryClient @SpringBootApplication public class MainApp8401 { public static void main(String[] args) { SpringApplication.run(MainApp8401.class, args); } }
💧访问控制台:http://localhost:8080 ,默认账号密码均为: sentinel
💧由于Sentinel采用了懒加载机制,我们不访问URL的话是不会出现监控服务的
💧访问 http://localhost:8401/testA 多刷几次看看效果
💧刷新sentinel,观察结果
💧簇点链路部分可以看到我们访问过的URL对应的方法
💧流控规则用于限制资源的访问速率,防止系统被过多请求拖垮。例如,我们可以设置一个API在一分钟内最多只能处理100个请求:
💧添加流控规则
💧新增流控规则
💧再次访问 http://localhost:8401/testA 每秒点两次,直接限流
💧修改规则
💧修改代码
💧开两个线程,分别狂点
💧再次限流
💧当关联资源/testB的qps阀值超过1时,就限流/testA的Rest访问地址
💧使用postman 模拟连续密集访问testB
💧新建collection
💧点击Run 配置发送规则
💧此时访问testA,发现已经挂了,产生了连坐效应
💧预热冷启动,效果:刚开始点太快不行,等预热时间到了就可以正常访问
💧排队等待,一秒一个
💧服务降级是应对系统高并发时的一种保护措施。当资源的异常比例超过阈值时,系统将自动对该资源进行降级,避免系统崩溃。
💧测试代码:
💧新增降级规则
💧打开JMeter
💧添加线程组
💧点击运行
💧此时访问:http://localhost:8401/testE,服务已降级
💧停掉JMeter后,再次访问,不会降级,展示不友好的ERROR页面
💧异常数,时间要大于60s
💧快速请求五次testE,服务降级
💧热点key限流用于对一些热点资源进行限制,防止因某个热点资源过于频繁访问而导致系统故障。
何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的TopK数据,并对其访问进行限制。比如:
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。
Sentinel利用LRU策略统计最近最常访问的热点参数,结合令牌桶算法来进行参数级别的流控。热点参数限流支持集群模式。
💧自定义兜底降级方法,@SentinelResource
💧访问一下:http://localhost:8401/testHotKey
💧添加限流规则
💧连续点击两次:http://localhost:8401/testHotKey?p1=a,限流,走兜底方法
💧如果我们配置了限流规则,但不添加兜底方案,那么被触发限流机制后就会直接报500
💧添加“参数例外项”,即使我们触发了上面的限流,但如果这个参数值是我们特殊指定的,则会走特殊通道
💧我们疯狂访问:http://localhost:8401/testHotKey?p1=5,没有任何问题。
💧而把5改为3,则依然限流,走兜底方法
💧系统规则是Sentinel的全局配置,可以对整个系统的资源进行限制,例如线程数、CPU使用率等。
系统保护规则是从应用级别的入口流量进行控制,从单台机器的 load、CPU使用率、平均RT、入口QPS和并发线程数等几个维度监控应用指标,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。
系统保护规则是应用整体维度的,而不是资源维度的,并且仅对入口流量生效。入口流量指的是进入应用的流量( EntryType.IN ),比如 Web服务或Dubbo服务端接收的请求,都属于入口流量。系统规则支持以下的模式:
保护。当系统load1超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR阶段)。系统容量由系统的maxOps * minRt估算得出。设定参考值一般是cpu cores * 2.5。
💧测试限流,添加 RateLimitController 和 公共类
@RestController public class RateLimitController { @GetMapping("/byResource") @SentinelResource(value = "byResource", blockHandler = "handleException") public CommonResult byResource() { return new CommonResult(200, "按资源名称限流测试OK", new Payment(2020L, "serial001")); } public CommonResult handleException(BlockException exception) { return new CommonResult(444, exception.getClass().getCanonicalName() + "\t 服务不可用"); } @GetMapping("/rateLimit/byUrl") @SentinelResource(value = "byUrl") public CommonResult byUrl() { return new CommonResult(200, "按url限流测试OK", new Payment(2020L, "serial002")); } @GetMapping("/rateLimit/customerBlockHandler") @SentinelResource(value = "customerBlockHandler", blockHandlerClass = CustomerBlockHandler.class,//<-------- 自定义限流处理类 blockHandler = "handlerException2")//<----------- public CommonResult customerBlockHandler() { return new CommonResult(200, "按客戶自定义", new Payment(2020L, "serial003")); } }
@Data @AllArgsConstructor @NoArgsConstructor public class CommonResult{ private Integer code; private String message; private T data; public CommonResult(Integer code, String message){ this(code, message, null); } }
@Data @AllArgsConstructor @NoArgsConstructor public class Payment implements Serializable { private Long id; private String serial; }
访问http://localhost:8401/byResource
💧新增流控规则
💧连续快速访问,限流,走兜底方法
💧如果我们关闭服务,限流规则也随之消失(体现出临时性)
💧测试一下,没有兜底方法的
💧添加限流规则
💧如果没有写兜底方法blockHandler,则依然走系统默认兜底
💧创建CustomerBlockHandler类,自定义限流处理逻辑
/** * @Author: LiangXinRui * @Date: 2023/08/4/17:51 * @Description: */ import com.alibaba.csp.sentinel.slots.block.BlockException; import com.atguigu.springcloud.entities.CommonResult; public class CustomerBlockHandler { public static CommonResult handlerException(BlockException exception) { return new CommonResult(4444,"按客戶自定义,global handlerException----1"); } public static CommonResult handlerException2(BlockException exception) { return new CommonResult(4444,"按客戶自定义,global handlerException----2"); } }
💧测试这个方法
💧访问:http://localhost:8401/rateLimit/customerBlockHandler
💧新增流控规则
💧一秒访问两次:
希望本篇博客能够带你一步一步完成Sentinel的入门,从而在微服务架构中有效地保护系统的稳定性和可用性。
🐬初学一门技术时,总有些许的疑惑,别怕,它们是我们学习路上的点点繁星,帮助我们不断成长。
🐟积少成多,滴水成河。文章粗浅,希望对大家有帮助!
上一篇:spring6-IOC容器