活动策划公司网站,网站推广软件app,创建公司网站 教程,wordpress目标关键词文章目录 Sentinel流量控制流控模式流控效果 隔离和降级线程隔离熔断降级 授权规则和规则持久化 微服务雪崩问题#xff1a; 微服务中#xff0c;服务间调用关系错综复杂#xff0c;一个微服务往往依赖于多个其它微服务。服务D有 故障进而导致服务A有故障#xff0c;进而导… 文章目录 Sentinel流量控制流控模式流控效果 隔离和降级线程隔离熔断降级 授权规则和规则持久化 微服务雪崩问题 微服务中服务间调用关系错综复杂一个微服务往往依赖于多个其它微服务。服务D有 故障进而导致服务A有故障进而导致服务雪崩。 解决雪崩问题的常见方式有四种 超时处理设定超时时间请求超过一定时间没有响应就返回错误信息不会无休止等待仓壁模式限定每个业务能使用的线程数避免耗尽整个tomcat的资源因此也叫线程隔离。断路器模式由断路器统计业务执行的异常比例如果超出阈值则会熔断该业务拦截访问该业务的一切请求。流量控制限制业务访问的QPS避免服务因流量的突增而故障 什么是雪崩问题
微服务之间相互调用因为调用链中的一个服务故障引起整个链路都无法访问的情况。 可以认为
限流是对服务的保护避免因瞬间高并发流量而导致服务故障进而避免雪崩。是一种预防措施。
超时处理、线程隔离、降级熔断是在部分服务故障时将故障控制在一定范围避免雪崩。是一种补救措施。
Sentinel 流量控制
雪崩问题虽然有四种方案但是限流是避免服务因突发的流量而发生故障是对微服务雪崩问题的预防。
簇点链路当请求进入微服务时首先会访问DispatcherServlet然后进入Controller、Service、Mapper这样的一个调用链就叫做簇点链路。簇点链路中被监控的每一个接口就是一个资源。
默认情况下sentinel会监控SpringMVC的每一个端点Endpoint也就是controller中的方法因此SpringMVC的每一个端点Endpoint就是调用链路中的一个资源。
流控、熔断等都是针对簇点链路中的资源来设置的因此我们可以点击对应资源后面的按钮来设置规则
流控流量控制降级降级熔断热点热点参数限流是限流的一种授权请求的权限控制
流控模式
在添加限流规则时点击高级选项可以选择三种流控模式
直接统计当前资源的请求触发阈值时对当前资源直接限流也是默认的模式关联统计与当前资源相关的另一个资源触发阈值时对当前资源限流链路统计从指定链路访问到本资源的请求触发阈值时对指定链路限流
使用场景比如用户支付时需要修改订单状态同时用户要查询订单。查询和修改操作会争抢数据库锁产生竞争。业务需求是优先支付和更新订单的业务因此当修改订单业务触发阈值时需要对查询订单业务限流。
需求说明
在OrderController新建两个端点/order/query和/order/update无需实现业务配置流控规则当/order/ update资源被访问的QPS超过5时对/order/query请求限流 链路模式只针对从指定链路访问到本资源的请求做统计判断是否超过阈值。
需求有查询订单和创建订单业务两者都需要查询商品。针对从查询订单进入到查询商品的请求统计并设置限流。
步骤
在OrderService中添加一个queryGoods方法不用实现业务在OrderController中改造/order/query端点调用OrderService中的queryGoods方法在OrderController中添加一个/order/save的端点调用OrderService的queryGoods方法给queryGoods设置限流规则从/order/query进入queryGoods的方法限制QPS必须小于2 总结
•直接对当前资源限流
•关联高优先级资源触发阈值对低优先级资源限流。
•链路阈值统计时只统计从指定资源进入当前资源的请求是对请求来源的限流 流控效果
流控效果是指请求达到流控阈值时应该采取的措施包括三种
快速失败达到阈值后新的请求会被立即拒绝并抛出FlowException异常。是默认的处理方式。warm up预热模式对超出阈值的请求同样是拒绝并抛出异常。但这种模式阈值会动态变化从一个较小值逐渐增加到最大阈值。排队等待让所有的请求按照先后次序排队执行两个请求的间隔不能小于指定时长
排队等待 当请求超过QPS阈值时快速失败和warm up 会拒绝新的请求并抛出异常。
而排队等待则是让所有请求进入一个队列中然后按照阈值允许的时间间隔依次执行。后来的请求必须等待前面执行完成如果请求预期的等待时间超出最大时长则会被拒绝。 例如QPS 5意味着每200ms处理一个队列中的请求timeout 2000意味着预期等待时长超过2000ms的请求会被拒绝并抛出异常。
那什么叫做预期等待时长呢
比如现在一下子来了12 个请求因为每200ms执行一个请求那么
第6个请求的预期等待时长 200 * 6 - 1 1000ms第12个请求的预期等待时长 200 * 12-1 2200ms
总结
快速失败QPS超过阈值时拒绝新的请求warm up QPS超过阈值时拒绝新的请求QPS阈值是逐渐提升的可以避免冷启动时高并发导致服务宕机。排队等待请求会进入队列按照阈值允许的时间间隔依次执行请求如果请求预期等待时长大于超时时间直接拒绝
热点参数限流 之前的限流是统计访问某个资源的所有请求判断是否超过QPS阈值。而热点参数限流是分别统计参数值相同的请求判断是否超过QPS阈值 刚才的配置中对查询商品这个接口的所有商品一视同仁QPS都限定为5.
而在实际开发中可能部分商品是热点商品例如秒杀商品我们希望这部分商品的QPS限制与其它商品不一样高一些。那就需要配置热点参数限流的高级选项了
案例需求给/order/{orderId}这个资源添加热点参数限流规则如下
•默认的热点参数规则是每1秒请求量不超过2
•给102这个参数设置例外每1秒请求量不超过4
•给103这个参数设置例外每1秒请求量不超过10
注意事项热点参数限流对默认的SpringMVC资源无效需要利用SentinelResource注解标记资源 隔离和降级
限流是一种预防措施虽然限流可以尽量避免因高并发而引起的服务故障但服务还会因为其它原因而故障。
而要将这些故障控制在一定范围避免雪崩就要靠线程隔离舱壁模式和熔断降级手段了。
线程隔离调用者在调用服务提供者时给每个调用的请求分配独立线程池出现故障时最多消耗这个线程池内资源避免把调用者的所有资源耗尽。
熔断降级是在调用方这边加入断路器统计对服务提供者的调用如果调用的失败比例过高则熔断该业务不允许访问该服务的提供者了 可以看到不管是线程隔离还是熔断降级都是对客户端调用方的保护。需要在调用方 发起远程调用时做线程隔离、或者服务熔断。
而我们的微服务远程调用都是基于Feign来完成的因此我们需要将Feign与Sentinel整合在Feign里面实现线程隔离和服务熔断。
FeignClient整合Sentinel 修改OrderService的application.yml文件开启Feign的Sentinel功能
编写失败降级逻辑
业务失败后不能直接报错而应该返回用户一个友好提示或者默认结果这个就是失败降级逻辑。
给FeignClient编写失败后的降级逻辑
①方式一FallbackClass无法对远程调用的异常做处理
②方式二FallbackFactory可以对远程调用的异常做处理我们选择这种 总结 Sentinel支持的雪崩解决方案
线程隔离仓壁模式降级熔断
Feign整合Sentinel的步骤
在application.yml中配置feign.sentienl.enabletrue给FeignClient编写FallbackFactory并注册为Bean将FallbackFactory配置到FeignClient
线程隔离
线程隔离有两种方式实现
线程池隔离信号量隔离Sentinel默认采用 线程池隔离给每个服务调用业务分配一个线程池利用线程池本身实现隔离效果
信号量隔离不创建线程池而是计数器模式记录业务使用的线程数量达到信号量上限时禁止新的请求。 sentinel的线程隔离 总结
线程隔离的两种手段是
信号量隔离线程池隔离
信号量隔离的特点是
基于计数器模式简单开销小
线程池隔离的特点是
基于线程池模式有额外开销但隔离控制更强
熔断降级
熔断降级是解决雪崩问题的重要手段。其思路是由断路器统计服务调用的异常比例、慢请求比例如果超出阈值则会熔断该服务。即拦截访问该服务的一切请求而当服务恢复时断路器会放行访问该服务的请求。
状态机包括三个状态
closed关闭状态断路器放行所有请求并开始统计异常比例、慢请求比例。超过阈值则切换到open状态open打开状态服务调用被熔断访问被熔断服务的请求会被拒绝快速失败直接走降级逻辑。Open状态5秒后会进入half-open状态half-open半开状态放行一次请求根据执行结果来判断接下来的操作。 请求成功则切换到closed状态请求失败则切换到open状态
断路器熔断策略有三种慢调用、异常比例、异常数
授权规则和规则持久化
授权规则可以对请求方来源做判断和控制。
授权规则可以对调用方的来源做控制有白名单和黑名单两种方式。
白名单来源origin在白名单内的调用者允许访问黑名单来源origin在黑名单内的调用者不允许访问 案例
既然获取请求origin的方式是从reques-header中获取origin值我们必须让所有从gateway路由到微服务的请求都带上origin头。
这个需要利用之前学习的一个GatewayFilter来实现AddRequestHeaderGatewayFilter。
修改gateway服务中的application.yml添加一个defaultFilter
自定义异常结果 默认情况下发生限流、降级、授权拦截时都会抛出异常到调用方。异常结果都是flow limmiting限流。这样不够友好无法得知是限流还是降级还是授权拦截。
而如果要自定义异常时的返回结果需要实现BlockExceptionHandler接口 下面我们就在order-service定义一个自定义异常处理类
package cn.itcast.order.sentinel;import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;Component
public class SentinelExceptionHandler implements BlockExceptionHandler {Overridepublic 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;charsetutf-8);response.setStatus(status);response.getWriter().println({\msg\: msg , \status\: status });}
}规则持久化: 现在sentinel的所有规则都是内存存储重启后所有规则都会丢失。在生产环境下我们必须确保这些规则的持久化避免丢失。 规则是否能持久化取决于规则管理模式sentinel支持三种规则管理模式
原始模式Sentinel的默认模式将规则保存在内存重启服务会丢失。pull模式push模式