1 写在前面

1.1 名词解释

consumer表示服务调用方

provider标示服务提供方,dubbo里面一般就这么讲。

下面的A调用B服务,一般是泛指调用B服务里面的一个接口。

1.2 拓扑图

大写字母表示不同的服务,后面的序号表示同一个服务部署在不同机器的实例。

2 从微观角度思考

2.1 超时(timeout)

在接口调用过程中,consumer调用provider的时候,provider在响应的时候,有可能会慢,如果provider 10s响应,那么consumer也会至少10s才响应。如果这种情况频度很高,那么就会整体降低consumer端服务的性能。

这种响应时间慢的症状,就会像一层一层波浪一样,从底层系统一直涌到最上层,造成整个链路的超时。

所以,consumer不可能无限制地等待provider接口的返回,会设置一个时间阈值,如果超过了这个时间阈值,就不继续等待。

这个超时时间选取,一般看provider正常响应时间是多少,再追加一个buffer即可。

2.2 重试(retry)

超时时间的配置是为了保护服务,避免consumer服务因为provider 响应慢而也变得响应很慢,这样consumer可以尽量保持原有的性能。

但是也有可能provider只是偶尔抖动,那么超时后直接放弃,不做后续处理,就会导致当前请求错误,也会带来业务方面的损失。

那么,对于这种偶尔抖动,可以在超时后重试一下,重试如果正常返回了,那么这次请求就被挽救了,能够正常给前端返回数据,只不过比原来响应慢一点。

重试时的一些细化策略:

重试可以考虑切换一台机器来进行调用,因为原来机器可能由于临时负载高而性能下降,重试会更加剧其性能问题,而换一台机器,得到更快返回的概率也更大一些。

2.2.1 幂等(idempotent)

如果允许consumer重试,那么provider就要能够做到幂等。

即,同一个请求被consumer多次调用,对provider产生的影响(这里的影响一般是指某些写入相关的操作) 是一致的。

而且这个幂等应该是服务级别的,而不是某台机器层面的,重试调用任何一台机器,都应该做到幂等。

2.3 熔断(circuit break)

重试是为了应付偶尔抖动的情况,以求更多地挽回损失。

可是如果provider持续的响应时间超长呢?

如果provider是核心路径的服务,down掉基本就没法提供服务了,那我们也没话说。 如果是一个不那么重要的服务,却因为这个服务一直响应时间长导致consumer里面的核心服务也拖慢,那么就得不偿失了。

单纯超时也解决不了这种情况了,因为一般超时时间,都比平均响应时间长一些,现在所有的打到provider的请求都超时了,那么consumer请求provider的平均响应时间就等于超时时间了,负载也被拖下来了。

而重试则会加重这种问题,使consumer的可用性变得更差。

因此就出现了熔断的逻辑,也就是,如果检查出来频繁超时,就把consumer调用provider的请求,直接短路掉,不实际调用,而是直接返回一个mock的值。

等provider服务恢复稳定之后,重新调用。

2.3.1 简单的熔断处理逻辑

目前我们框架有通过注解使用的熔断器,大家可以参考应用在项目中。

2.4 限流(current limiting)

上面几个策略都是consumer针对provider出现各种情况而设计的。

而provider有时候也要防范来自consumer的流量突变问题。

这样一个场景,provider是一个核心服务,给N个consumer提供服务,突然某个consumer抽风,流量飙升,占用了provider大部分机器时间,导致其他可能更重要的consumer不能被正常服务。

所以,provider端,需要根据consumer的重要程度,以及平时的QPS大小,来给每个consumer设置一个流量上线,同一时间内只会给A consumer提供N个线程支持,超过限制则等待或者直接拒绝。

2.4.1 资源隔离

provider可以对consumer来的流量进行限流,防止provider被拖垮。

同样,consumer 也需要对调用provider的线程资源进行隔离。 这样可以确保调用某个provider逻辑不会耗光整个consumer的线程池资源。

2.4.2 服务降级

降级服务既可以代码自动判断,也可以人工根据突发情况切换。

2.4.2.1 consumer 端

consumer 如果发现某个provider出现异常情况,比如,经常超时(可能是熔断引起的降级),数据错误,这是,consumer可以采取一定的策略,降级provider的逻辑,基本的有直接返回固定的数据。

2.4.2.2 provider 端

当provider 发现流量激增的时候,为了保护自身的稳定性,也可能考虑降级服务。

比如,1,直接给consumer返回固定数据,2,需要实时写入数据库的,先缓存到队列里,异步写入数据库。

3 从宏观角度重新思考

宏观包括比A -> B 更复杂的长链路。

长链路就是 A -> B -> C -> D这样的调用环境。

而且一个服务也会多机部署,A 服务实际会存在 A1,A2,A3 …

微观合理的问题,宏观未必合理。

下面的一些讨论,主要想表达的观点是:如果系统复杂了,系统的容错配置要整体来看,整体把控,才能做到更有意义。

3.1 超时

如果A给B设置的超时时间,比B给C设置的超时时间短,那么肯定不合理把,A超时时间到了直接挂断,B对C支持太长超时时间没意义。

R表示服务consumer自身内部逻辑执行时间,TAB表示consumer A开始调用provider B到返回的时间 。

那么那么TAB > RB + TBC 才对。

3.2 重试

重试跟超时面临的问题差不多。

B服务一般100ms返回,所以A就给B设置了110ms的超时,而B设置了对C的一次重试,最终120ms正确返回了,但是A的超时时间比较紧,所以B对C的重试被白白浪费了。

A也可能对B进行重试,但是由于上一条我们讲到的,可能C确实性能不好,每次B重试一下就OK,但是A两次重试其实都无法正确的拿到结果。

N标示设置的重试次数

修正一下上面section的公式,TAB > RB+TBC * N。

虽然这个公式本身没什么问题,但是,如果站在长链路的视角来思考,我们需要整体规划每个服务的超时时间和重试次数,而不是仅仅公式成立即可。

比如下面情况:

A -> B -> C。

RB = 100ms,TBC=10ms

B是个核心服务,B的计算成本特别大,那么A就应该尽量给B长一点的超时时间,而尽量不要重试调用B,而B如果发现C超时了,B可以多调用几次C,因为重试C成本小,而重试B成本则很高。 so …

3.3 熔断

A -> B -> C,如果C出现问题了,那么B熔断了,则A就不用熔断了。

3.4 限流

B只允许A以QPS<=5的流量请求,而C却只允许B以QPS<=3的qps请求,那么B给A的设定就有点大,上游的设置依赖下游。

而且限流对QPS的配置,可能会随着服务加减机器而变化,最好是能在集群层面配置,自动根据集群大小调整。

3.5 服务降级

服务降级这个问题,如果从整体来操作,

1,一定是先降级优先级地的接口,两权相害取其轻

2,如果服务链路整体没有性能特别差的点,比如就是外部流量突然激增,那么就从外到内开始降级。

3如果某个服务能检测到自身负载上升,那么可以从这个服务自身做降级。

3.6 涟漪

A -> B -> C,如果C服务出现抖动,而B没有处理好这个抖动,造成B服务也出现了抖动,A调用B的时候,也会出现服务抖动的情况。

这个暂时的不可用状态就想波浪一样从底层传递到了上层。

所以,从整个体系的角度来看,每个服务一定要尽量控制住自己下游服务的抖动,不要让整个体系跟着某个服务抖动。

3.7 级联失败(cascading failure)

系统中有某个服务出现故障,不可用,传递性地导致整个系统服务不可用的问题。

跟上面涟漪(自造词)的区别也就是严重性的问题。

涟漪描述服务偶发的不稳定层层传递,而级联失败基本是导致系统不可用。 一般,前者可能会因为短时间内恢复而未引起重视,而后者一般会被高度重视。

3.8 关键路径

关键路径就是,你的服务想正常工作,必须要完整依赖的下游服务链,比如数据库一般就是关键路径里面的一个节点。

尽量减少关键路径依赖的数量,是提高服务稳定性的一个措施。

数据库一般在服务体系的最底层,如果你的服务可以会自己完整缓存使用的数据,解除数据库依赖,那么数据库挂掉,你的服务就暂时是安全的。

3.9 最长路径

想要优化你的服务的响应时间,需要看服务调用逻辑里面的最长路径,只有缩短最长时间路径的用时,才能提高你的服务的性能。

dubbo 熔断,限流,降级的更多相关文章

  1. 限流降级神器,带你解读阿里巴巴开源 Sentinel 实现原理

    Sentinel 是阿里中间件团队开源的,面向分布式服务架构的轻量级高可用流量控制组件,主要以流量为切入点,从流量控制.熔断降级.系统负载保护等多个维度来帮助用户保护服务的稳定性. 大家可能会问:Se ...

  2. 阿里熔断限流Sentinel研究

    1. 阿里熔断限流Sentinel研究 1.1. 功能特点 丰富的应用场景:例如秒杀(即突发流量控制在系统容量可以承受的范围).消息削峰填谷.集群流量控制.实时熔断下游不可用应用等 完备的实时监控:S ...

  3. 微服务熔断限流Hystrix之流聚合

    简介 上一篇介绍了 Hystrix Dashboard 监控单体应用的例子,在生产环境中,监控的应用往往是一个集群,我们需要将每个实例的监控信息聚合起来分析,这就用到了 Turbine 工具.Turb ...

  4. Spring Cloud Alibaba系列(五)sentinel实现服务限流降级

    一.sentinel是什么 sentinel的官方名称叫分布式系统的流量防卫兵.Sentinel 以流量为切入点,从流量控制.熔断降级.系统负载保护等多个维度保护服务的稳定性.在Spring Clou ...

  5. SpringBoot进阶教程(六十八)Sentinel实现限流降级

    前面两篇文章nginx限流配置和SpringBoot进阶教程(六十七)RateLimiter限流,我们介绍了如何使用nginx和RateLimiter限流,这篇文章介绍另外一种限流方式---Senti ...

  6. Dubbo服务限流

    为了防止某个消费者的QPS或是所有消费者的QPS总和突然飙升而导致的重要服务的失效,系统可以对访问流量进行控制,这种对集群的保护措施称为服务限流. Dubbo中能够实现服务限流的方式较多,可以划分为两 ...

  7. 代理层Nginx限流(降级)预案

    典型服务架构介绍 预案适用场景 监控指标 操作手册 相关文档 操作方法 配置语法 配置样例 配置解释 注意事项 典型服务架构介绍 典型的互联网服务访问链路都是分层结构的,从流量入口,到应用层,到后端资 ...

  8. Envoy熔断限流实践(二)Rainbond基于RLS服务全局限流

    Envoy 可以作为 Sevice Mesh 微服务框架中的代理实现方案,Rainbond 内置的微服务框架同样基于 Envoy 实现.本文所描述的全局限速实践也是基于 Envoy 已有的方案所实现. ...

  9. Envoy熔断限流实践(一)基于Rainbond插件实现熔断

    Envoy 可以作为 Sevice Mesh 微服务框架中的代理实现方案,Rainbond 内置的微服务框架同样基于 Envoy 实现.本文所描述的熔断实践基于 Rainbond 特有的插件机制实现. ...

  10. 微服务熔断限流Hystrix之Dashboard

    简介 Hystrix Dashboard是一款针对Hystrix进行实时监控的工具,通过Hystrix Dashboard可以直观地看到各Hystrix Command的请求响应时间,请求成功率等数据 ...

随机推荐

  1. spring-data-redis HashOperations

    spring-data-redis HashOperations /** * 从散列中删除给定的多个元素 * @param key 不能为null 散列的名称 * @param hashKeys 需要 ...

  2. Dropout, DropConnect ——一个对输出,一个对输入

    Deep learning: Dropout, DropConnect from:https://www.jianshu.com/p/b349c4c82da3 Dropout 训练神经网络模型时,如果 ...

  3. vscode wechat settings.json

    // { // "window.zoomLevel": 0, // "editor.fontSize": 16, // "files.associat ...

  4. Python *Mix_w3

    1.基本数据类型(int,bool,str) int 整数 str 字符串. 一般不存放大量的数据 bool 布尔值. 用来判断. True, False list 列表.用来存放大量数据, []表示 ...

  5. iPhone手机更换自定义铃声

    ①首先将iPhone手机(iPhone5s)的数据线插入电脑USB接口中,然后打开iTunes(12.4.3.1)-->文件-->将文件添加到资料库 ②选中音乐文件-->点击编辑-- ...

  6. LeetCode Rotatelmage

    ---恢复内容开始--- You are given an n x n 2D matrix representing an image. Ratate the image by 90 degrees( ...

  7. 读取磁盘:LBA方式

    LBA简介 磁盘读取发展 IO操作读取硬盘的三种方式: chs方式 :小于8G (8064MB) LBA28方式:小于137GB LBA48方式:小于144,000,000 GB LBA方式访问使用了 ...

  8. 包的作用域(public、private)

    包的作用域一共有三种情况 修饰符public:标记为public的部分可以被任意的类使用: 修饰符private:标记为private的部分只能被定义他们的类使用: 没有指定修饰符的部分:这部分(类. ...

  9. spring中classpath

    http://blog.csdn.net/wlwlwlwl015/article/details/48134763 Maven 项目的 classpath 理解 applicationContext. ...

  10. man 命令帮助文件输出乱码

    man 命令重定向的时候有写控制字符再直接显示的时候没有问题, 但是重定向到文件中的时候,被解释错误,显示为 ^H 或者乱码 解决方法: man ps | col -b >a.txt 可以消除所 ...