微服务保护

1.雪崩问题及解决方案

雪崩问题

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

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

  • 超时处理:设定超时时间,请求超过一定时间没有响应就返回错误信息,不会无休止等待
  •  舱壁模式:限定每个业务能使用的线程数,避免耗尽整个tomcat的资源,因此也叫线程隔离。

  • 熔断降级:由断路器统计业务执行的异常比例,如果超出阈值则会熔断该业务,拦截访问该业务的一切请求。
  • 通俗讲就是:如果有请求的异常到达某一个限定的目标时,就会熔断该业务,拦截访问该业务一切请求。

 

  • 流量控制:限制业务访问的QPS,避免服务因流量突增而故障。
  • 通俗讲就是:如果有大批量请求访问服务,每次限定指定数量的请求访问该服务,避免因资源耗尽而产生故障。

 什么是雪崩问题?

  • 微服务之间相互调用,因为调用链路中一个服务故障,引起整个链路都无法访问的情况。

如何避免因瞬间高并发流量而导致服务故障?

  • 流量控制

如何避免因服务故障引起的雪崩问题?

  • 超时处理
  • 线程隔离
  • 熔断降级

服务保护技术对比

Sentinel

Hystrix

隔离策略

信号量隔离

线程池隔离/信号量隔离

熔断降级策略

基于慢调用比例或异常比例

基于失败比率

实时指标实现

滑动窗口

滑动窗口(基于 RxJava)

规则配置

支持多种数据源

支持多种数据源

扩展性

多个扩展点

插件的形式

基于注解的支持

支持

支持

限流

基于 QPS,支持基于调用关系的限流

有限的支持

流量整形

支持慢启动、匀速排队模式

不支持

系统自适应保护

支持

不支持

控制台

开箱即用,可配置规则、查看秒级监控、机器发现等

不完善

常见框架的适配

Servlet、Spring Cloud、Dubbo、gRPC 等

Servlet、Spring Cloud Netflix

2.安装Sentinel控制台

sentinel官方提供了UI控制台,方便我们对系统做限流设置。大家可以在GitHub下载。

 1.将其拷贝到一个非中心目录,然后允许命令:

2.然后访问:localhost:8080即可看到控制台页面,默认的账户和密码都是sentinel

 

 如果要修改Sentinel的默认端口、账户、密码、可以通过下列配置

配置项

默认值

说明

server.port

8080

服务端口

sentinel.dashboard.auth.username

sentinel

默认用户名

sentinel.dashboard.auth.password

sentinel

默认密码

举例说明

 引入qy163

要使用Sentinel肯定要结合微服务,这里我们使用SpringCloud实用篇中的qy163工程。

 2.1微服务整合Sentinel

我们在qy163-order中整合Sentinel,并且连接Sentinel的控制台

(1)引入依赖

<!--引入Sentinel依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

(2)配置控制台地址:

#Sentinel地址
spring.cloud.sentinel.transport.dashboard=localhost:8070

(3)访问微服务的任意端点,触发sentinel监控

3.限流规则 

3.1簇点链路

簇点链路:就是项目内的调用链路,链路中被监控的每个接口就是一个资源。默认情况下sentinel会监控SpringMVC的每一个端点(Endpoint),因此SpringMVC的每一个端点(Endpoint)就是调用链路中的一个资源。流控,熔断等都是针对簇点链路中的资源来设置的,因此我们可以点击对应资源后面的按钮来设置规则:

点击资源/order/getInfo后面的流控按钮,就可以弹出表单。表单中可以添加流控规则。

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

4.流控模式

在添加限流规则时,点击高级选项,可以选择三种流控模式:

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

4.1流控模式-关联 

  • 关联模式:统计与当前资源相关的另一个资源,触发阈值时,对当前资源限流
  • 实用场景:比如用户支付时需要修改订单状态,同时用户要查询订单。查询和修改操作会争抢数据库锁,产生竞争。业务需求是有限支付和更新订单的业务,因此当修改订单业务触发阈值时,需要对查询订单业务限流。

当/order/write资源访问量触发阈值时,就会对/read资源限流,避免影响/order/write资源。
总结:满足下面条件可以实用关联模式:

  • 两个有竞争关系的资源
  • 一个优先级较高,一个优先级较低

/order/write触发阈值

 /order/read资源限流

 4.3 流控模式 -- 链路

链路模式:只针对从指定链路访问到本资源的请求做统计,判断是否超过阈值。

例如有两条请求链路:

  • /order/write ----> /goods
  • /order/read ----> /goods

如果只希望统计从/order/read进入到/goods的请求,则可以这样配置:

从/order/read入口资源进入goods请求限流

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

  •  Sentinel默认只标记Controller中的访问为资源,如果要标记其他访问,需要利用@SentinelResource注解。
    @Override
    @SentinelResource("goods")
    public void queryGoods() {

    }
  • Sentinel默认会将Controller方法做context整合,导致链路模式的流控失效,需要修改application.properties,添加
#关闭context整合
spring.cloud.sentinel.web-context-unify=false

流控模式有哪些?

  • 直接:对当前资源限流
  • 关联:高优先级资源触发阈值,对低优先级资源限流。
  • 链路:阈值统计时,只统计从指定资源进入当前资源的请求,是对请求来源的限流

5.流控效果

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

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

 5.1流控效果-warm up

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

例如:我设置QPS的threshold为10,预热时间为5秒,那么初始阈值就是10/3,也就是3,然后再5秒后逐渐增长到10。

 给/order/write这个资源限流,最大QPS为10,利用warm up效果,预热时长为5秒

 5.2 流控效果 - 排队等待

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

在某一时刻,服务很忙,而其他时刻,服务很闲。

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

 给/orde/write这个资源设置限流,最大QPS为10,利用排队的流控效果,超时时长设置为5s

 下面测试:每秒有15个线程请求,最大每秒QPS为10 排队等待设置5秒 如果等待时间超过5秒请求被拒绝或抛出异常

 流控效果有哪些?

  • 快速失败:QPS超过阈值时,拒绝新的请求。
  • warm up:QPS超过阈值时,拒绝新的请求,QPS阈值是逐渐提升的,可以避免冷启动时高并发导致服务宕机。
  • 排队等待:请求会进入队列,按照阈值允许的时间间隔依次执行请求;如果请求预期等待时长大于超时时间,直接拒绝。

6.热点参数限流

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

配置示例:

代表的含义是:对hot这个资源的0号参数 (第一个参数)做统计,每1秒相同参数值的请求数不能超过2

如果参数值是102,每秒相同参数值请求数不能超过4,如果是参数值是103,每秒相同参数值请求数不能超过10

 

 注意:热点参数限流对默认的SpringMVC资源无效

7.隔离和降级

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

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

 7.1 Feign整合Sentinel

SpringCloud中,微服务调用都是通过OpenFeign来实现的,因此客户端(调用方)保护必须整合OpenFeign和Sentinel。

1. 修改微服务的配置文件,开启OpenFeign的Sentinel功能。

#开启OpenFeign和Sentinel功能
feign.sentinel.enabled=true

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

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

② 方式二:FallbackFactory:可以对远程调用的异常做处理。

7.2 熔断降级

步骤一:修改Feign.Sentinel.enable=true

#开启OpenFeign和Sentinel功能
feign.sentinel.enabled=true

步骤二:创建Feign接口的降级类,实现FallbackFactory

@Component //交给Spring容器管理
public class ProductFeignFactory implements FallbackFactory<ProductOpenFeign> {
    @Override
    public ProductOpenFeign create(Throwable throwable) {
        return new ProductOpenFeign() {
            @Override
            public Product getById(Integer pid) {
                Product product = new Product();
                product.setPid(-1);
                product.setPname("商品服务出现故障");
                return product;
            }
        };
    }
}

步骤二:@FeignClient(fallbackFactory = ProductFeignFactory.class)

//@FeignClient(value = "服务提供者的名字")
@FeignClient(value = "qy163-product",fallbackFactory = ProductFeignFactory.class)
@RequestMapping("product")
public interface ProductOpenFeign {

    //抽象方法一定要和服务提供者的接口方法一样
    @GetMapping("getById/{pid}")
    public Product getById(@PathVariable Integer pid);
}

当Product微服务出现异常时,会走降级逻辑

在productController类中制造一个除零异常

 测试:当通过order微服务远程调用product微服务出现异常时会走降级逻辑 并不会出现500

 总结:

Sentinel支持的雪崩解决方案:

  • 线程隔离(舱壁模式)
  • 熔断降级

7.3 线程隔离

线程隔离有两种方式实现:

  • 线程池隔离
  • 信号量隔离(Sentinel默认采用)

 7.4信号量隔离和线程池隔离的区别

信号量隔离:

  • 优点:轻量级,无额外开销
  • 缺点:不支持主动超时,不支持异步调用
  • 场景:高频调用 高扇出

线程池隔离:

  • 优点:支持主动超时 支持异步调用
  • 缺点:线程的额外开销比较大
  • 场景:低扇出

7.5 线程隔离(舱壁模式)

在添加限流规则时,可以选择两种阈值类型:

  •  QPS:就是每秒的请求数。
  • 线程数:是该资源能使用的tomcat线程数的最大值,也就是通过限制线程数量,实现舱壁模式。

线程隔离的两种手段是?

  • 信号量隔离 
  • 线程池隔离

信号量隔离的特点是?

  • 基于计数器模式,简单,开销小

线程池隔离的特点是?

  • 基于线程池模式,有额外开销,但隔离控制更强

8.熔断降级解决雪崩问题的重要手段:

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

8.1 熔断策略-慢调用

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

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

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

需求:

给productFeign的查询商品接口设置降级规则,慢调用的RT阈值为50ms,统计时间为1秒,最小请求数量为5,失败阈值比例0.4,熔断时长为5秒

8.2 熔断策略-异常比例、异常数 

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

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

例如:

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

 Sentinel熔断降级的策略有哪些?

  • 慢调用比例:超过指定时长的调用为慢调用,统计单位时长内慢调用的比例,超过阈值则熔断
  • 异常比例:统计单位时长内异常调用的比例,超过阈值则熔断
  • 异常数:统计单位时长内异常调用的次数,超过阈值则熔断

总结

  1. 流控效果:【1】快速失败 【2】预热模式 【3】排队等待
  2. 热点参数限流:粒度更新
  3. sentinel和openfeign
  4. 熔断降级:===流程===>通过异常比例 慢调用比例 异常数 当达到阈值,则会开启熔断,当到达熔断时长,半开状态,试着放行一个请求,如果请求成功则关闭熔断,否则继续开启熔

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值