名词解释
簇点链路: 就是项目中的调用链路,链路中被监控的每一个接口就是一个资源,默认情况下sentinel会监控springmvc的每个接口,每个接口就是一个资源。
阈值类型
1.QPS: 每秒可以允许的请求数量,如果超过了就会报错
2.并发线程数: 是该资源能使用的tomcat线程数的最大值,也就是通过限制线程数量,实现舱壁模式
流控模式
1.直接 统计当前资源的请求,触发阈值时针对当前资源直接限流,也是默认模式
2.关联 统计与当前资源相关的另外一个资源,触发阈值时,当前资源限流 (比较适合的场景是: 两个有竞争关系的资源,一个优先级高,一个优先级低。
比如说支付服务和查询服务,很明显支付服务的优先级更高,需要保证支付服务正常,如果很多用户在支付,很多用户在查询,就可以给查询服务
增加关联模式的流控,当支付服务达到阈值的时候,直接限流查询服务,让查询服务暂时不可用,来保证支付服务的正常进行)
3.链路 统计从指定链路访问到本资源的请求,触发阈值时,对指定链路限流(
比如,有查询订单和创建订单两个业务,这两个业务都需要查询商品,但是商品服务肯定是有请求上限的。
两条链路1. 查询订单-->查询商品 2.创建订单-->查询商品
为了保证创建订单可以正常进行,就需要对查询订单进入到查询商品的请求做统计,并设置限流
模拟一个实现的步骤:
1.在一个service中创建一个方法,当做是查询商品的方法queryGoods
2.在controller中创建两个方法,queryOrder,createOrder
2.给queryGoods设置流控规则,queryOrder进去的查询,qps阈值小于2
注意1: 这里的queryGoods也是一个资源,我们在不使用远程调用的时候演示需要给它标注这个注解@SentinelResource("goods"),来表明它是一个资源
我们就可以给它设置限流,因为sentinel默认将springmvc的接口认定为一个资源,使用这个注解我们可以将其他的方法设置为一个资源,如果小伙伴
门写了一个微服务,中有查询商品的controller就不需要这样做了。
注意2:sentinel默认会将controller中的方法做context整合,导致链路模式的流控失效,需要修改配置文件,添加配置:
cloud.sentinel.web-context-unify: false #关闭context整合
)
流控效果
流控效果是指达到流控阈值之后应该采取的措施
1.快速失败 : 达到阈值之后,新的请求会被里积极拒绝并抛出FlowException异常,是默认的处理方式
2.warm up : 预热模式,对超出阈值的请求同样拒绝并抛出FlowException异常,但是这种模式阈值会动态变化,从一个较小值逐渐增加到最大阈值(
默认coldFactor为3,即请求QPS从(阈值/3)开始,经过多少预热时长才逐步升至设定的QPS阈值
案例: 阈值为15,预热时长为5。
系统初始化的阈值为 15/3约等于5,即阈值刚开始为5,然后过了5秒阈值才慢慢升高恢复到15
适合处理秒杀等业务,访问量忽然增加,导致项目出现故障。
)
3.排队等待 : 让所有的请求按照先后次序排队执行,两个请求的间隔不能小于指定时长(
当请求超过阈值时,快速失败和warm up会拒绝新的请求并抛出异常,而排队等待是让所有请求进入到一个队列中,然后按照阈值允许的时间间隔依次执行,
后来的请求必须等待前面执行完成,如果请求预期的等待时间超出最大时长,则会被拒绝
匀速排队,让请求以均匀的速度通过,阈值类型必须设置为QPS,否则无效。
适合处理消息队列,这一秒过来很多消息需要处理,下一秒没有消息,又出现不用任何操作的情况。设置为匀速排队,可以将
大量过来的请求按照每秒间隔来处理。
例如: 请求的QPS等于5(每秒处理5个请求),意味着每200毫秒处理一个请求,如果timeout设置为1000,那第六个请求过来不会进入队列,则会直接
抛出异常,也就是说队列中最多有5个请求,因为第六个请求进来会等待1200毫秒,超过了设定的最大超时时间1000,所以不会进入队列,则会抛出异常
)
热点规则(热点参数)
之前的限流是统计访问某个资源的所有请求,判断是否超过QPS阈值,而热点参数限流是分别统计参数值相同的请求,判断是否超过QPS阈值(
注意: 热点参数限流对默认的springMVC资源无效,需要通过@SentinelResource标注要设置的限流的资源
)
熔断降级
熔断降级是解决雪崩问题的重要手段,其思路是由断路器统计服务调用的异常比例,慢请求比例,如果超出阈值则会熔断该服务。即拦截该服务的一切请求,
而当服务回复时,断路器会放心访问该服务的请求。
熔断策略
1.慢调用(业务的响应时长(RT)大于指定时长的请求认定为慢调用请求,在指定的时间内,如果请求数量超过设定的最小数量,慢调用比例大于设定的阈值,则触发熔断
例如: 最大RT为500ms 比例阈值为0.5 熔断时长为5s 最小请求数为10 统计时长为10000ms
解读: RT超过500ms的调用是慢调用,统计最近10000ms内的请求,如果请求数量超过10次,并且慢调用比例不低于0.5,则触发熔断,
熔断时长为5s,然后进入half-open状态,放行一次请求做测试.
)
2.异常比例或异常数
(统计指定时间内的调用,如果调用次数超过指定请求数,并且出现异常的比例达到设定的比例阈值(或超过指定异常数)则触发熔断。
例如: 熔断策略配置为异常数或者异常比例 阈值配置为0.5 熔断时长配置为5s 最小请求数配置为10 统计时长配置为1000ms
解读: 统计最近1000ms内的请求,如果请求数量超过10次,并且异常比例不低于0.5(如果选择异常数量的话就是不低于设置的这个异常数量),则触发熔断,熔断时长为5s,然后进入half-open状态,
放行一次请求做测试
)
授权规则
授权规则可以对调用方的来源做控制,有白名单和黑名单两种方式
白名单: 来源在白名单内的调用者允许访问
黑名单: 来源在黑名单内的调用者不允许访问
例如: 我们限定只允许从网关来的请求访问,那么流控名称中就填写网关的名称
自定义异常结果
默认情况下,发生限流,降级,授权拦截时,都会抛出异常到调用方,如果要自定义异常返回结果需要实现BlockExceptionHandler接口
示例代码:
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
String msg = "未知异常";
int status = 429;
if (e instanceof FlowException) {
msg = "请求被限流了";
} else if (e instanceof ParamFlowException) {
msg = "请求被热点参数限流";
} else if (e instanceof DegradeException) {
msg = "请求被降级了";
} else if (e instanceof AuthorityException) {
msg = "没有权限访问";
status = 401;
}
response.setContentType("application/json;charset=utf-8");
response.setStatus(status);
response.getWriter().println("{\"msg\": " + msg + ", \"status\": " + status + "}");
}
持久化规则
结合nacos实现配置持久化
参照: https://www.jianshu.com/p/6563b7793223 的配置可以实现