商城网站服务器,有限责任公司名字,wordpress 手机登录,360全景网站怎么做一、前言 接下来是开展一系列的 SpringCloud 的学习之旅#xff0c;从传统的模块之间调用#xff0c;一步步的升级为 SpringCloud 模块之间的调用#xff0c;此篇文章为第十四篇#xff0c;即介绍 SpringCloud Alibaba Sentinel 创建流控规则。
二、基本介绍 我们在 senti…一、前言 接下来是开展一系列的 SpringCloud 的学习之旅从传统的模块之间调用一步步的升级为 SpringCloud 模块之间的调用此篇文章为第十四篇即介绍 SpringCloud Alibaba Sentinel 创建流控规则。
二、基本介绍 我们在 sentinel 的管理界面上为我们的请求设置流量监控的规则有两种方式如下图 点击 号配置流控规则界面如下图接下来详细介绍下可以配置的标签 2.1 资源名 唯一名称默认请求路径。即工程里面 controller 层方法上面的请求路径。
2.2 针对来源 Sentinel 可以针对调用者进行限流填写微服务名默认 default (不区分来源)。
2.3 阈值类型 QPS每秒钟的请求数量当调用该 api 的 QPS 达到阀值的时候进行限流。 线程数当调用该 api 的线程数达到阀值的时候进行限流。
2.4 单机阈值 一个具体的数字为阀值类型所使用。
2.5 是否集群 不需要集群。
2.6 流控模式 1、直接api 达到限流条件时直接限流。 2、关联当关联的资源达到闻值时就限流自己 3、链路只记录指定链路上的流量指定资源从入口资源进来的流量如果达到闻值就进行限流[api 级别的针对来源]。
2.7 流控效果 1、快速失败: 直接失败抛异常 2、Warm Up根据 codeFactor 冷加载因子默认 3 的值从阀值 / codeFactor经过预热时长才达到设置的 QPS 阀值。 3、排队等待匀速排队让请求以匀速的速度通过闻值类型必须设置为 QPS否则无效。
三、流控模式
3.1 直接 接下来我们配置一个系统默认的流控规则即 QPS -直接-快速失败如下图表示 1s 内查询一次是没有问题的但是在 1s 内点击超过一次就直接快速失败报默认错误。 快速点击访问 http://localhost:8401/testB如下图可以看到第一次请求是没有任何问题的 但是当我们狂点的时候就会返回给我们限流的提醒了如下图 修改我们刚刚创建的流控规则将 QPS -直接-快速失败 模式修改为 并发线程数 -直接-快速失败 如下图 快速点击访问 http://localhost:8401/testB如下图可以看到一直没有报错信息 这是因为 QPS 和并发线程数是两种不同的流控效果即 QPS 有流控效果而并发线程数没有流控效果从上面配置时的两张图片对比就可以看的出来。 当有一堆请求发送过来时高并发场景QPS 流控就会将请求全部拦截在门外根本接触不到里面的路径而并发流控则是将请求放进来但是只能有一个请求得到处理其他的请求直接失败报错。 上面一直调用成功的原因是后台处理请求在一瞬间就完成了为了演示流控的效果我们修改下 FlowLimitController 的代码延长下 testB() 方法的处理时间代码如下
RestController
public class FlowLimitController {GetMapping(/testA)
public String testA(){return ------testA;}GetMapping(/testB)
public String testB(){try {Thread.sleep(800);} catch (InterruptedException e) {throw new RuntimeException(e);}return ------testB;}
} 打开两个浏览器窗口分别调用 http://localhost:8401/testB如下图第一次调用没有任何问题如下图 第二次调用就返回异常信息了点击的速度得快要不演示不出来如下 3.2 关联 当关联的资源达到阈值时就限流自己当与 A 关联的资源 B 达到阀值后就限流 A 自己举个简单的例子就是支付模块快爆炸了就限流下订单模块。 在 sentinel 的管理界面配置一个关联的限流规则如下当关联资源 /testB 的 qps 阀值超过 1 时就限流 /testA 的 Rest 访问地址当关联资源到阈值后限制配置好的资源名。 测试之前先把 FlowLimitController 的代码改回来如下
RestController
public class FlowLimitController {GetMapping(/testA)public String testA(){return ------testA;}GetMapping(/testB)public String testB(){return ------testB;}
} 为了演示模拟的效果我们需要使用 postman 进行并发密集访问 /testB打开 postman创建一个新的 collection如下图 接下来创建一个新的请求记得保存这个请求如下图 接下来配置运行的参数如下图 配置一个线程组包含 20 个线程每隔 0.3s 访问一次 然后调用 http://localhost:8401/testA 可以发现 testA 挂了如下图 3.3 链路 假设一个 controller 里面的两个服务都会调用同一个 service 层里面的服务这样就会形成两条链路但是由于 service 层的资源是有限的我们可以通过配置链路的流控模式来保证某一条链路一直可以正常使用但另一条链路可能就会多担待一点。 它和我们的关联模式有点像也是保证一个接口可以正常使用而牺牲了另外一个接口。接下来我们使用代码来演示下。 首先需要创建一个 service 层并编写一个方法这个方法是给 controller 层的两个方法提供服务的并在方法上添加 SentinelResource 注解这个注解用于标记需要被流量控制、熔断降级以及系统保护等功能覆盖的方法或类。这个注解允许开发者自定义资源名称并且可以配置异常处理逻辑和 fallback 函数。代码如下
package com.springcloud.service;import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.stereotype.Service;Service
public class FlowLimitService {SentinelResource(todoService)public void todoService(){System.out.println(....todoService....);}
}接下来需要在我们的配置文件里面添加一些配置配置文件里面默认采用的是聚合的方式我们这里改成 false采用展开的模式即我们有多少个链路都把它展示出来。 接下来修改 controller 类的代码让其调用 service 层的方法如下
RestController
public class FlowLimitController {ResourceFlowLimitService flowLimitService;GetMapping(/testA)public String testA(){flowLimitService.todoService();return ------testA;}GetMapping(/testB)public String testB(){flowLimitService.todoService();return ------testB;}
} 接下来打开 sentinel 的管理界面首先调用 testA 和 testB 服务如下图 如果我们没有在配置文件里面配置 web-context-unify: false 这个标签或者配置完了这个标签出现下面的这种情况。 原因可能是因为 spring-cloud-starter-alibaba-sentinel 版本太低将其改成下面的版本即可。
!-- 流量控制sentinel依赖--
dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-sentinel/artifactIdversion2.2.5.RELEASE/version
/dependency接下来配置链路的流控我们对 testA 的链路进行限流如下图 此时疯狂调用 http://localhost:8401/testB如下图没有任何反应可以正常返回 疯狂调用 http://localhost:8401/testA如果频率高一些就会报错如下图 证明我们的链路调用限流成功了。
四、流控效果
4.1 快速失败 这种流控效果上面我们做了大量的例子就是直接失败抛出异常如下图 4.2 Warm Up 预热 当流量突然增大的时候我们常常会希望系统从空闲状态到繁忙状态的切换的时间长一些。即如果系统在此之前长期处于空闲的状态我们希望处理请求的数量是缓步的增多经过预期的时间以后到达系统处理请求个数的最大值。Warm Up冷启动预热模式就是为了实现这个目的的。 这个场景主要用于启动需要额外开销的场景例如建立数据库连接等。 它有一个公式初始阈值 配置的阈值除以 codeFactor 默认值为 3 经过预热时长后才会达到配置的阈值。这样讲很抽象我们配置一个来展示下首先把 controller 代码恢复成原来的样子如下图
RestController
public class FlowLimitController {GetMapping(/testA)public String testA(){return ------testA;}GetMapping(/testB)public String testB(){return ------testB;}
} 配置预热的流控效果如下图我希望每秒钟可以承受 10 个 QPS但是我给你慢慢的预热起来由于冷加载默认因子是 310/3 3 那么一开始单机的阈值就是 3但是给了你一个缓冲预热的时间 5s让你 5s 内慢慢的从 3 过度到 10。 此时疯狂调用 http://localhost:8401/testB可以发现一开始有成功有失败但到后来就都是成功的了。 其使用场景是秒杀系统在开启的瞬间会有很多流量上来很有可能把系统打死预热方式就是把为了保护系统可慢慢的把流量放进来慢慢的把阀值增长到设置的阀值
4.3 排队等待 匀速排队方式会严格控制请求通过的间隔时间也即是让请求以均匀的速度通过对应的是漏桶算法。该方式的作用如下图所示 这种方式主要用于处理间隔性突发的流量例如消息队列。想象一下这样的场景在某一秒有大量的请求到来而接下来的几秒则处于空闲状态我们希望系统能够在接下来的空闲期间逐渐处理这些请求而不是在第一秒直接拒绝多余的请求。 注意匀速排队模式暂时不支持 QPS 1000 的场景。 修改下 controller 类的代码加一个日志打印的功能如下
RestController
Slf4j
public class FlowLimitController {GetMapping(/testA)public String testA(){return ------testA;}GetMapping(/testB)public String testB(){log.info(Thread.currentThread().getName()\ttestB);return ------testB;}
} 配置排队等待的流控效果如下图设置单机阈值为 1超时时间为 2s。 接下来使用 postman 进行多线程调用测试和 5.2.2 小节用的方式一样调用 collenction如下图 查看控制台的日志信息如下可以看到都是 1s 内调用一次很舒服 五、降级规则
5.1 简介 降级规则又称为熔断降级除了流量控制以外对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。一个服务常常会调用别的模块可能是另外的一个远程服务、数据库或者第三方 API 等。例如支付的时候可能需要远程调用银联提供的 API查询某个商品的价格可能需要进行数据库查询。然而这个被依赖服务的稳定性是不能保证的。如果依赖的服务出现了不稳定的情况请求的响应时间变长那么调用服务的方法的响应时间也会变长线程会产生堆积最终可能耗尽业务自身的线程池服务本身也变得不可用。 现代微服务架构都是分布式的由非常多的服务组成。不同服务之间相互调用组成复杂的调用链路。以上的问题在链路调用中会产生放大的效果。复杂链路上的某一环不稳定就可能会层层级联最终导致整个链路都不可用。因此我们需要对不稳定的弱依赖服务调用进行熔断降级暂时切断不稳定调用避免局部不稳定因素导致整体的雪崩。熔断降级作为保护自身的手段通常在客户端调用端进行配置。 本文档针对 Sentinel 1.8.0 及以上版本。1.8.0 版本对熔断降级特性进行了全新的改进升级请使用最新版本以更好地利用熔断降级的能力。 Sentinel 和 Hystrix 的原则是一致的当调用链路中某个资源出现不稳定例如表现为 timeout异常比例升高的时候则对这个资源的调用进行限制并让请求快速失败避免影响到其它的资源最终产生雪崩的效果。
5.2 熔断策略 熔点策略分为三种慢调用比例、异常比例和异常数三种。
5.3 慢调用比例 慢调用比例 (SLOW_REQUEST_RATIO)选择以慢调用比例作为阈值需要设置允许的慢调用 RT即最大的响应时间请求的响应时间大于该值则统计为慢调用。当单位统计时长statIntervalMs内请求数目大于设置的最小请求数目并且慢调用的比例大于阈值则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态HALF-OPEN 状态若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断若大于设置的慢调用 RT 则会再次被熔断。 在 FlowLimitController 类中新增一个测试方法 testD代码如下
RestController
Slf4j
public class FlowLimitController {GetMapping(/testA)public String testA() {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;}
} 在 sentinel 中配置降级规则如下图 设定允许的最大响应时间 RT 900ms统计最近 10000ms 内的请求若请求超过 5 次并且慢调用的比例超过 0.5则触发熔断熔断时长为 2s然后进入 half-open 状态放行一次请求做测试。 接下来我们使用 postman 进行测试使用 10 个线程调用我们的方法如下图 等 postman 调用结束后测试当前 testD 的状态如下图可以发现处于熔断状态了。 等到 2s 之后再次刷新浏览器可以看到又恢复正常了如下图 5.4 异常比例 异常比例 (ERROR_RATIO)当单位统计时长statIntervalMs内请求数目大于设置的最小请求数目并且异常的比例大于阈值则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态HALF-OPEN 状态若接下来的一个请求成功完成没有错误则结束熔断否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0]代表 0% - 100%。 修改 FlowLimitController 类中的测试方法 testD代码如下 GetMapping(/testD)public String testD() {log.info(testD 测试异常调用);int age 10 / 0;return ------testD;} 在 sentinel 中配置降级规则如下图 统计最近 10000ms 内的请求若请求超过 5 次并且异常的比例超过 0.5则触发熔断熔断时长为 3s然后进入 half-open 状态放行一次请求做测试。 我们先在浏览器访问一下方法如下可以看到返回的是错误的界面。 接下里我们使用 postman 进行测试使用 10 个线程调用我们的方法如下图 调用结束后再次在浏览器访问 testD可以看到返回的是限流的界面如下图 等到 3s 之后再次访问可以看到又出现了错误的界面如下 5.5 异常数 异常数 (ERROR_COUNT)当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态HALF-OPEN 状态若接下来的一个请求成功完成没有错误则结束熔断否则会再次被熔断。 在 FlowLimitController 类中的新增测试方法 testE代码如下 GetMapping(/testE)public String testE() {log.info(testE 测试异常数);int age 10 / 0;return ------testE;} 在 sentinel 中配置降级规则如下图 统计最近 10000ms 内的请求若请求超过 5 次并且异常数超过 5 个则触发熔断熔断时长为 3s然后进入 half-open 状态放行一次请求做测试。 在浏览器多次访问 testE可以发现前五次返回的页面如下 等到第六次返回的就是流控的界面了如下 六、热点参数限流
6.1 简介 何为热点热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据并对其访问进行限制。比如 1、商品 ID 为参数统计一段时间内最常购买的商品 ID 并进行限制。 2、用户 ID 为参数针对一段时间内频繁访问的用户 ID 进行限制 热点参数限流会统计传入参数中的热点参数并根据配置的限流阈值与模式对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制仅对包含热点参数的资源调用生效。
6.2 案例演示 在 FlowLimitController 类中的新增两个方法代码如下SentinelResource 注解我们在 上面提到过用于标记需要被流量控制、熔断降级以及系统保护等功能覆盖的方法或类。 它里面有个 blockHandler 属性用于指定兜底的方法兜底方法分为系统默认和客户自定义两种在之前的案例中限流出问题后都是用 sentinel 系统默认的提示Blocked by Sentinel (flow limiting)。这次我们指定兜底的方法为下面的 deal_testHotKey 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) {return ------testHotKey;}public String deal_testHotKey (String p1, String p2, BlockException exception){// sentinel系统默认的提示Blocked by Sentinel (flow limiting)return ------deal_testHotKey,o(╥﹏╥)o;} 接下里我们在 sentinel 中配置热点规则如下 限流模式只支持 QPS 模式固定写死了。SentinelResource 注解的方法参数索引0 代表第一个参数1 代表第二个参数以此类推。单机阀值以及统计窗口时长表示在此窗口时间超过阀值就限流。 上面配置的规则为1s 的 QPS 为 1超过就限流限流后调用 dealHandler testHotKey 支持方法。 在浏览器访问http://localhost:8401/testHotKey怎么点击都不会出现限流的效果因为并没有传输参数。 在浏览器访问http://localhost:8401/testHotKey?p1a如果 1s 点击一下就会出现下面的现象 如果点击频繁就会出现限流的效果如下 在浏览器访问http://localhost:8401/testHotKey?p2b随便点也不会出现限流的效果因为我们没有对第二个参数进行配置所以不用限流如下 6.3 特殊情况 上述案例演示了第一个参数 p1当 QPS 超过 1s 点击一次后马上被限流但是我们期望当 p1 参数是某个特殊值时它的限流值和平时不一样比如说当 p1 的值等于 5 时它的阈值可以达到 200那么我们该如何配置呢 修改我们刚才配置的 sentinel 热点规则打开参数例外项需要注意的是参数类型必须是基本类型或者 String如下图 在浏览器访问http://localhost:8401/testHotKey?p15可以看到无论点击多么频繁都不会出现限流的现象如下图 在浏览器访问http://localhost:8401/testHotKey?p14可以看到超过 1s 点击一次就会出现限流的现象如下图当 p1 不等于 5 的时候阈值就是平常的 1。 6.4 异常情况 修改 FlowLimitController 类手动添加一个异常试试如下 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){// sentinel系统默认的提示Blocked by Sentinel (flow limiting)return ------deal_testHotKey,o(╥﹏╥)o;} 在浏览器访问http://localhost:8401/testHotKey可以看到直接就报错了如下图 这是因为 SentinelResource 处理的是 Sentinel 控制台配置的违规情况有 blockHandler 方法配置的兜底处理。而 int age 10/0这个是 java 运行时报出的运行时异常 RunTimeExceptionSentinelResource 不管。 总结起来就是 SentinelResource 主管配置出错运行出错该走异常走异常。
七、系统规则
7.1 简介 系统规则又称为系统自适应限流是从应用级别的入口流量进行控制从单台机器的 load、CPU 使用率、平均 RT、入口 QPS 和并发线程数等几个维度监控应用指标让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。前面我们所配置的限流都是方法级别的限流而系统规则则是对整个应用进行限流的操作。 系统保护规则是应用整体维度的而不是资源维度的并且仅对入口流量生效。入口流量指的是进入应用的流量比如 Web 服务或 Dubbo 服务端接收的请求都属于入口流量。
7.2 分类 1、Load 自适应仅对 Linux/Unix-like 机器生效系统的 load1 作为启发指标进行自适应系统保护。当系统 load1 超过设定的启发值且系统当前的并发线程数超过估算的系统容量时才会触发系统保护BBR 阶段。系统容量由系统的 maxQps * minRt 估算得出。设定参考值一般是 CPU cores * 2.5。 2、CPU usage1.5.0 版本当系统 CPU 使用率超过阈值即触发系统保护取值范围 0.0-1.0比较灵敏。 3、平均 RT当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护单位是毫秒。 4、并发线程数当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。 5、入口 QPS当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。
7.3 案例演示 在 sentinel 控制台新增一个入口 QPS 的系统规则如下图 在浏览器访问 http://localhost:8401/testB当 1s 点击一下时效果如下图没有任何问题 当频繁点击时就会出现限流的效果如下图