前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一文详解分布式熔断降级平台 Aegis!

一文详解分布式熔断降级平台 Aegis!

作者头像
孙玄@奈学教育
发布2021-02-12 16:02:19
9960
发布2021-02-12 16:02:19
举报
文章被收录于专栏:架构之美架构之美

- 前言 -

分布式场景中,若服务不稳定,会导致调用方服务也不可用,从而造成雪崩效应。

因此,我们要对在原服务不可用时,进行熔断降级处理。

- 分析 -

熔断降级可以服务端限流、网关限流、客户端限流。

1. 客户端限流:在调用方法发起请求时检查是否达到阈值。若达到阈值,不发起调用请求。

  • 优点:可以在服务消费端直接控制流量出口,减少不必要请求的发起。
  • 缺点:客户端需要感知服务运行指标和容灾规则。每个业务方需要重复开发。

2. 服务端限流:服务提供方自定义容灾逻辑,在收到请求后再根据当前状态判断是否走 fallback 逻辑。

  • 优点:容灾规则、阈值完全封装在服务提供者。对调用方无感知。
  • 缺点:若服务提供者都挂了,无法进行容灾。

3. 网关限流:原本直接调用提供者的请求都由网关层代理转发。容灾规则的配置、降级逻辑都封装在网关层。

  • 优点:客户端、服务端都无需感知容灾逻辑。
  • 缺点:多了一次网络请求、rt 变大。

大部分情况下,我们都是选择服务端限流。但客户端对数据平台的接口是强依赖的。若搜索应用挂了,客户端还是需要看到数据。相比高可用,略微的 rt 变大是可以接受的,所以启动一个数据容灾网关。

- 技术选型 -

现在了解到的开源容灾框架有 Hystrix、Sentinel 两种。

Hystrix:常用于 SpringCloud 的一个熔断降级组件。主要功能是不同服务之间的资源隔离、失败降级。底层实现是 Rxjava。它提供两种资源隔离的模式:信号量隔离和线程池隔离。一般使用线程池隔离。耗费一定资源,但相比之下支持超时和异步执行。听起来可以覆盖大部分场景,但它不支持更高要求的流控,如qps的控制。所以需要单独采用令牌漏桶来做流量控制。

Sentinel:阿里开源的分布式流量控制组件。支持流控、熔断降级、系统保护等。所有的资源都对应一个资源名称以及一个 Entry。每一个 Entry 创建的时候,同时也会创建一系列插件(系统保护插件:SystemSlot、流控插件:FlowSlot、熔断降级插件 LDegradeSlot 等)。

每个插件会监控自己职责范围内的指标。NodeSelectorSlot 将各个资源的调用路径以树状存储,用于限流降级。调用者通过创建上下文、请求token来执行方法。若没有抛出 BlockException,表示请求成功。它支持并发数 QPS 的流量控制、也支持熔断降级。

对比:

1. Hystrix 的熔断都围绕线程池展开。更适合做资源隔离,但单个应用有多个服务时线程池开销会造成浪费。hystrix是单个超时立即熔断,控制力度更细。多个微服务的场景可以考虑用这种。

2. Sentinel 是基于并发数。支持的场景也更复杂,开销小,适合在保证服务稳定的情况下提高吞吐量。但它的超时是5次请求的平均响应时间。并不是很严格。但对于大多数场景而言可以接受

- 接入方式 -

Sentinel 支持 API 和注解两种接入方式。作为容灾网关,之后可以会接很多接口。为了接入简单、对代码无侵入。需要使用注解的方式。但是原生的 @SentinelResource 有几个问题:

1. 只能指定资源名称、fallback方法。用户还是需要通过 API 创建容灾规则。

2. 而且 fallback 方法入参要加上 BlockException。这样的接入方式不是很优雅。

3. 流控异常 FlowException 的方法要另外指定。

于是基于 Sentinel 封装了一层自定义注解 @AegisResource

@AegisResource(value = "hello",limitThread = 0,timeOut = 100,failRate = 0.5,timeWindows = 100,fallback = "exceptionHandler")

参数说明:

value:资源名称,默认为方法名;

limitThread:最大线程数,默认-1,即不启用;

timeOut:接口超时时间,默认-1,即不启用;

failRate:失败率,默认-1,即不启用;

timeWindows:触发降级但持续时间,默认100;

fallback:降级方法,必须指定。

- 接入 DEMO -

代码语言:javascript
复制
    /**
      * 保护的方法
      * @return
      */
    @GetMapping("resourcetest")
    @AegisResource(value = "hello",limitThread = 0,timeOut = 100,failRate = 0.5,timeWindows = 100,fallback = "exceptionHandler")
    public String hello() {
        return "ok";
    }

    /**
      * 降级的方法
      * @return
      */
    public String exceptionHandler() {
        // Do some log here.
        return "Oops, error occurred at " ;
    }

新接口只需写好希望执行的方法和降级方法,然后在希望执行的方法上加入@AegisResource(fallBack=“fallback的方法名”)就可以无侵式入地进行容灾。切面定义了默认容灾阈值。也可以在对应属性上设置自定义的阈值。

- 后期规划 -

容灾网关可以满足当前的需求,同时,目前也有开源的控制台,可以查看服务调用大盘,动态调整容灾规则。缺点是指标的搜集是http方式,容灾规则、运行指标也没有持久化存储。后期如果需要,可以借助现有的开源控制台进行二次开发。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-01-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 架构之美 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档