微服务保护——sentinel

目录

1、初识Sentinel

1、雪崩问题

 2、使用Sentinel

 2、限流规则

1、入门

2、流控模式

 流控模式——关联

流控模式——链路

 3、流控效果

 流控效果——warm up

 流控效果——排队等候

 4、热点参数限流

 3、隔离和降级

1、FeignClient整合Sentinel

 2、线程隔离

 3、熔断降级

 熔断策略——慢调用

熔断策略——异常比例,异常数

 4、授权规则

1、授权规则

2、自定义异常结果

 5、规则持久化

1、规则管理模式

2、实现push模式


1、初识Sentinel

1、雪崩问题

微服务调用链路中的某个服务故障,引起整个链路中的所有微服务都不可用,这就是雪崩。

解决雪崩问题的常见方式有四种:

  • 超时处理:设定超时时间,请求超过一定时间没有响应就返回错误信息,不会无休止等待。 

  •  舱壁模式:限定每个业务能使用的线程数,避免耗尽整个tomcat的资源,因此也叫线程隔离

  •  熔断降级:由断路器统计业务执行的异常比例,如果超出阈值则会熔断该业务,拦截访问该业务的一切请求。

  •  流量控制:限制业务访问的QPS,避免服务因流量的突增而故障。

 2、使用Sentinel

启动:java -jar (jar包名)
localhost:8080
账号、密码:sentinel

 

java -jar sentinel-dashboard-1.8.1.jar -Dserver.port=8090

整合sentinel

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

 2、限流规则

1、入门

簇点链路:就是项目内的调用链路,链路中被监控的每个接口就是一个资源。默认情况下sentinel会监控SpringMVC的每一个端点(Endpoint),因此SpringMVC的每一个端点(Endpoint)就是调用链路中的一个资源。

流控、熔断等都是针对簇点链路中的资源来设置的,因此我们可以点击对应资源后面的按钮来设置规则:

 其含义是限制 /order/{orderId}这个资源的单机QPS1,即每秒只允许1次请求,超出的请求会被拦截并报错。

2、流控模式

  • 直接:统计当前资源的请求,触发阈值时对当前资源直接限流,也是默认的模式
  • 关联:统计与当前资源相关的另一个资源,触发阈值时,对当前资源限流(a、b,a到阈值,b限流)
  • 链路:统计从指定链路访问到本资源的请求,触发阈值时,对指定链路限流(a、b访问c,只统计a过来的请求)

 流控模式——关联

使用场景:比如用户支付时需要修改订单状态,同时用户要查询订单。查询和修改操作会争抢数据库锁,产生竞争。业务需求是有限支付和更新订单的业务,因此修改订单业务触发阈值时,需要对查询订单业务限流

 /write资源访问量触发阈值时,就会对/read资源限流,避免影响/write资源。

流控模式——链路

有查询订单和创建订单业务,两者都需要查询商品。针对从查询订单进入到查询商品的请求统计,并设置限流。

 

  • Sentinel默认只标记Controller中的方法为资源,如果要标记其它方法,需要利用@SentinelResource注解
  • Sentinel默认会将Controller方法做context整合,导致链路模式的流控失效,需要修改application.yml

 

 3、流控效果

流控效果是指请求达到流控阈值时应该采取的措施,包括三种:

  • 快速失败:达到阈值后,新的请求会被立即拒绝并抛出FlowException异常。是默认的处理方式
  • warm up:预热模式,对超出阈值的请求同样是拒绝并抛出异常。但这种模式阈值会动态变化,从一个较小值逐渐增加到最大阈值。
  • 队等待:让所有的请求按照先后次序排队执行,两个请求的间隔不能小于指定时长

 流控效果——warm up

warm up也叫预热模式,是应对服务冷启动的一种方案。请求阈值初始值是 threshold / coldFactor,持续指定时长后,逐渐提高到threshold值。而coldFactor的默认值是3.

例如,我设置QPSthreshold10,预热时间为5秒,那么初始阈值就是 10 / 3 ,也就是3,然后在5秒后逐渐增长到10.

 流控效果——排队等候

当请求超过QPS阈值时,快速失败和warm up 会拒绝新的请求并抛出异常。而排队等待则是让所有请求进入一个队列中,然后按照阈值允许的时间间隔依次执行。后来的请求必须等待前面执行完成,如果请求预期的等待时间超出最大时长,则会被拒绝。

例如:QPS = 5,意味着每200ms处理一个队列中的请求;timeout = 2000,意味着预期等待超过2000ms的请求会被拒绝并抛出异常

 4、热点参数限流

之前的限流是统计访问某个资源的所有请求,判断是否超过QPS阈值。而热点参数限流是分别统计参数值相同的请求,判断是否超过QPS阈值。

 热点参数限流对默认的SpringMVC资源无效,需要注解@SentinelResource

 hot这个资源的0号参数(第一个参数)做统计,每1相同参数值的请求数不能超过1,参数101例外

 3、隔离和降级

虽然限流可以尽量避免因高并发而引起的服务故障,但服务还会因为其它原因而故障。而要将这些故障控制在一定范围,避免雪崩,就要靠线程隔离(舱壁模式)和熔断降级手段了。

不管是线程隔离还是熔断降级,都是对客户端(调用方)的保护。

1、FeignClient整合Sentinel

SpringCloud中,微服务调用都是通过Feign来实现的,因此做客户端保护必须整合FeignSentinel

1.修改OrderServiceapplication.yml文件,开启FeignSentinel功能

2.FeignClient编写失败后的降级逻辑 

        ①方式一:FallbackClass,无法对远程调用的异常做处理

        ②方式二:FallbackFactory,可以对远程调用的异常做处理,我们选择这种

@Slf4j
public class UserFallbackFactory implements FallbackFactory<UserClient> {
    @Override
    public UserClient create(Throwable throwable) {
        // 创建UserClient接口实现类,实现其中的方法,编写失败降级的处理逻辑
        return new UserClient() {
            @Override
            public User findById(Long id) {
                // 记录异常信息
                log.error("查询用户异常",throwable);
                // 根据业务需求返回默认的数据,这里是空用户
                return new User();
            }
        };
    }
}

 

 

 

 2、线程隔离

 

  • QPS:就是每秒的请求数,在快速入门中已经演示过
  • 线程数:是该资源能使用用的tomcat线程数的最大值。也就是通过限制线程数量,实现舱壁模式

 

 3、熔断降级

 熔断降级是解决雪崩问题的重要手段。其思路是由断路器统计服务调用的异常比例、慢请求比例,如果超出阈值则会熔断该服务。即拦截访问该服务的一切请求;而当服务恢复时,断路器会放行访问该服务的请求。

 熔断策略——慢调用

断路器熔断策略有三种:慢调用、异常比例、异常数

慢调用:业务的响应时长(RT)大于指定时长的请求认定为慢调用请求。在指定时间内,如果请求数量超过设定的最小数量,慢调用比例大于设定的阈值,则触发熔断。例如:

 

RT超过500ms的调用是慢调用,统计最近10000ms内的请求,如果请求量超过10次,并且慢调用比例不低于0.5,则触发熔断,熔断时长为5秒。然后进入half-open状态,放行一次请求做测试。

熔断策略——异常比例,异常数

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

统计最近1000ms内的请求,如果请求量超过10次,并且异常比例不低于0.5,则触发熔断,熔断时长为5秒。然后进入half-open状态,放行一次请求做测试。 

 4、授权规则

1、授权规则

授权规则可以对调用方的来源做控制,有白名单和黑名单两种方式。

  • 白名单:来源(origin)在白名单内的调用者允许访问
  • 黑名单:来源(origin)在黑名单内的调用者不允许访问

我们尝试从request中获取一个名为origin请求头,作为origin的值:

@Component
public class HeaderParser implements RequestOriginParser {
    @Override
    public String parseOrigin(HttpServletRequest request) {
        //获取请求头
        String header = request.getHeader("origin");
        if(StringUtils.isEmpty(header)){
            header = "err";
        }
        return header;
    }
}

gateway配置中添加过滤:

2、自定义异常结果

默认情况下,发生限流、降级、授权拦截时,都会抛出异常到调用方。如果要自定义异常时的返回结果,需要实现BlockExceptionHandler接口: 

 

@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 + "}");
    }
}

 5、规则持久化

1、规则管理模式

一共有3种模式:

原始模式:控制台配置的规则直接推送到Sentinel客户端,也就是我们的应用。然后保存在内存中,服务重启则丢失(默认)。

pull模式:控制台将配置的规则推送到Sentinel客户端,而客户端会将配置规则保存在本地文件或数据库中。以后会定时去本地文件或数据库中查询,更新本地规则。

 push模式:控制台将配置规则推送到远程配置中心,例如NacosSentinel客户端监听Nacos,获取配置变更的推送消息,完成本地配置更新。

 

2、实现push模式

 push模式实现最为复杂,依赖于nacos,并且需要改在Sentinel控制台。整体步骤如下:

1.修改order-service服务,使其监听Nacos配置中心

        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>
spring:
  cloud:
    sentinel:
      datasource:
        flow:
          nacos:
            server-addr: localhost:8848 # nacos地址
            dataId: orderservice-flow-rules
            groupId: SENTINEL_GROUP
            rule-type: flow # 还可以是:degrade 降级、authority、param-flow

2.修改Sentinel-dashboard源码,配置nacos数据源

解压源码:

idea打开项目

 

 

 

 

 

 

3.修改Sentinel-dashboard源码,修改前端页面

4.重新编译、打包-dashboard源码

 启动:java -jar -Dnacos.addr=localhost:8888 ...(名称)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值