Sentinel哨兵框架

目录

什么是"雪崩效应"?

解决"雪崩"的常用4种解决方案

sentinel--介绍

sentinel--簇点链路

sentinel--流量控制--三种模式

sentinel--流量控制--三种效果

sentinel--流量控制--热点参数限流

sentinel--线程隔离模式(舱壁模式)

信号量隔离与线程池隔离的区别

sentinel--熔断模式--介绍

sentinel--熔断模式--三种统计方式

sentinel--访问授权

sentinel--自定义异常

sentinel--规则持久化


什么是"雪崩效应"?

"雪崩"是指在微服务的调用链路中,一个服务出现问题,会出现连锁反应,导致所有的依赖服务出现异常.

假如A服务调用B服务,B服务宕机,A服务的请求就会无响应,并占用A服务的资源,所有资源都被占用后,A服务也会宕机

解决"雪崩"的常用4种解决方案

请求超时模式:

        在请求一定时间无响应后返回请求失败,这样可以防止调用者的资源消耗

线程隔离(舱壁模式):

        在调用者调用微服务时,会创建指定数量的线程池,当微服务宕机时,只会影响到调用者一定数量的线程资源,

熔断模式:

        会在服务间创建一个断路器,由断路器进行监控服务调用的健康状态,若超过了设置的阈值,就会进行熔断,禁止对该微服务的调用,

流量控制模式:

        根据自定义策略限制对微服务访问的QPS, 以防瞬时高并发场景,导致微服务宕机

请求超时,线程隔离,熔断都属于补救策略,而流量控制属于预防策略

sentinel--介绍

sentinel是阿里巴巴开源出的一款微服务保护框架,它支持多种雪崩问题的补救与预防机制

与前期的Hystrix相比,sentinel更为完善

sentinel--簇点链路

当请求进入微服务时,首先会访问DispatcherServlet,然后进入Controller、Service、Mapper,这样的一个调用链就叫做簇点链路。簇点链路中被监控的每一个接口就是一个资源。

默认情况下sentinel会监控SpringMVC的每一个端点(Endpoint,也就是controller中的方法),因此SpringMVC的每一个端点(Endpoint)就是调用链路中的一个资源

sentinel--流量控制--三种模式

直接模式:

        统计当前资源的QPS,超过阈值将会直接响应失败,进行限流

关联模式:

        统计与当前资源相关的另一个资源的QPS,超过阈值将会对当前资源进行限流

链路模式:

        阈值统计时,只统计从指定资源进入当前资源的请求,是对请求来源的限流

直接模式简单暴力,适用于对单一资源的保护,

关联模式适用于有两个竞争关系的资源,且优先级不同,比如用户支付时需要修改订单状态,同时用户要查询订单。查询和修改操作会争抢数据库锁,产生竞争。业务需求是优先支付和更新订单的业务,因此当修改订单业务触发阈值时,需要对查询订单业务限流

链路模式适用于不同链路资源请求同一个资源, 比如查询订单和创建订单,都需要调用查询商品,可以针对查询订单请求查询商品进行链路模式流控, 用于保护创建订单的正常执行

sentinel--流量控制--三种效果

快速失败:

        达到阈值后,新的请求会被立即拒绝并抛出FlowException异常。是默认的处理方式。

warm up:

        预热模式,对超出阈值的请求同样是拒绝并抛出异常。但这种模式阈值会动态变化,刚开始是根据冷启动因子(3)来计算出初始值(阈值/冷启动因子),再逐渐增加到最大阈值。

排队等待:

        让所有的请求按照先后次序排队执行,两个请求的间隔不能小于指定时长

warm up适用于服务冷启动, 此时服务还未能承受最高并发,可以进行慢启动,

排队等待适用于需要对进行流量削峰填谷,能够解决瞬时高并发问题

sentinel--流量控制--热点参数限流

 前面是三种限流模式都是对同一资源的所有请求进行限流, 热点参数是对同一参数的请求进行限流,

适用于部分商品是热点商品,例如秒杀商品,我们希望这部分商品的QPS限制与其它商品不一样。那就需要配置热点参数限流的高级选项了

sentinel--线程隔离模式(舱壁模式)

sentinel默认的舱壁模式是线程信号量隔离:

        在微服务调用的时候,sentinel会创建一个线程计数器用于对调用者使用线程的记录,可以自定义线程阈值,

信号量隔离与线程池隔离的区别

线程池隔离:给每个服务调用业务分配一个线程池,利用线程池本身实现隔离效果

信号量隔离:不创建线程池,而是计数器模式,记录业务使用的线程数量,达到信号量上限时,禁止新的请求。

sentinel--熔断模式--介绍

熔断机制是调用断路器对微服务的异常比列,慢调用比例进行统计,超过阈值后会进行熔断, 不过断路器会根据指定熔断时间进行恢复尝试,若服务可用,断路器会解除熔断状态

closed:关闭状态,断路器放行所有请求,并开始统计异常比例、慢请求比例。超过阈值则切换到open状态

open:打开状态,服务调用被熔断,访问被熔断服务的请求会被拒绝,快速失败,直接走降级逻辑。Open状态5秒后会进入half-open状态

half-open:半开状态,放行一次请求,根据执行结果来判断接下来的操作。

        请求成功:则切换到closed状态
        请求失败:则切换到open状态

sentinel--熔断模式--三种统计方式

慢调用比例:

        业务的相应时长(RT)大于自定义时长的被称为慢调用, 若在指定时间内,慢调用的比例大于我们自定义的比例,则会触发熔断机制

异常比例;

        统计指定时间内的调用,如果调用次数超过指定请求数,并且出现异常的比例达到设定的比例阈值,则触发熔断。

异常数:

        统计指定时间内的调用,如果调用次数超过指定请求数,并且出现异常数超过指定异常数,则触发熔断。

sentinel--访问授权

sentinel的授权可以对请求方资源进行拦截与放行,类似于网关的作用,如果当服务器被绕过网关访问的时候,sentinel的授权就可以对服务进行保护, 有黑名单,白名单两种方式

黑名单: 禁止访问名单

白名单: 允许访问名单

 而流控应用名称(origin)是sentinel是通过RequestOriginParser这个接口获取的

public interface RequestOriginParser {
    /**
     * 从请求request对象中获取origin,获取方式自定义
     */
    String parseOrigin(HttpServletRequest request);
}

这个方法的作用就是从request对象中,获取请求者的origin值并返回。

默认情况下,sentinel不管请求者从哪里来,返回值永远是default,也就是说一切请求的来源都被认为是一样的值default。

因此,我们需要自定义这个接口的实现,让不同的请求,返回不同的origin

@Component
public class HeaderOriginParser implements RequestOriginParser {
    @Override
    public String parseOrigin(HttpServletRequest request) {
        // 1.获取请求头
        String origin = request.getHeader("origin");
        // 2.非空判断
        if (StringUtils.isEmpty(origin)) {
            origin = "blank";
        }
        return origin;
    }
}

既然获取请求origin的方式是从reques-header中获取origin值,我们必须让所有从gateway路由到微服务的请求都带上origin头

这个需要利用之前学习的一个GatewayFilter来实现,AddRequestHeaderGatewayFilter。

修改gateway服务中的application.yml,添加一个defaultFilter:

spring:
  cloud:
    gateway:
      default-filters:
        - AddRequestHeader=origin,gateway

这样,从gateway路由的所有请求都会带上origin头,值为gateway。而从其它地方到达微服务的请求则没有这个头。

sentinel--自定义异常

默认情况下,触发了sentinel的保护机制后返回的异常结果都是flowLimmiting,(限流)。这样不够友好,无法得知是限流还是降级还是授权拦截。 而如果要自定义异常时的返回结果,需要实现BlockExceptionHandler接口:

public interface BlockExceptionHandler {
    /**
     * 处理请求被限流、降级、授权拦截时抛出的异常:BlockException
     */
    void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception;
}

这个方法有三个参数:

- HttpServletRequest request:request对象
- HttpServletResponse response:response对象
- BlockException e:被sentinel拦截时抛出的异常

 我们就可以自定义一个异常类

@Component
public class SentinelExceptionHandler implements 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 + "}");
    }
}

sentinel--规则持久化

sentinel的开源版本,默认的规则是存储于内存中的,当服务重启的时候就会失效,所以需要对配置规则进行持久化操作

规则是否能持久化,取决于规则管理模式,sentinel支持三种规则管理模式:

- 原始模式:Sentinel的默认模式,将规则保存在内存,重启服务会丢失。
- pull模式 :控制台将配置的规则推送到Sentinel客户端,而客户端会将配置规则保存在本地文件或数据库中。以后会定时去本地文件或数据库中查询,更新本地规则。
- push模式:  控制台将配置规则推送到远程配置中心,例如Nacos。Sentinel客户端监听Nacos,获取配置变更的推送消息,完成本地配置更新。

一般我们使用push模式, 不过需要修改源码,

附上教程push模式到nacos

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值