微服务架构相比单体架构,服务的调用从同一台机器内部的本地调用变成了不同机器之间的远程方法调用,但是这个过程也引入了两个不确定的因素: - 调用的执行是在服务提供者一端,即使服务消费者本身是正常的,服务提供者也可能由于诸如CPU、网络I/O、磁盘、内存、网卡等硬件原因导致调用失败,还有可能由于本身程序执行问题比如GC暂停导致调用失败 - 调用发生在两台机器之间,所以要经过网络传输,而网络的复杂性是不可控的,网络丢包、延迟以及随时可能发生的瞬间抖动都有可能造成调用失败。

所以要针对服务调用失败进行特殊处理。

超时

被微服务架构后,一次用户调用可能会被拆分成多系统间的服务调用,任何一次服务调用如果发生问题都可能会导致最后用户调用失败。而且在微服务架构下,一个系统的问题会影响所有调用这个系统所提供服务的服务消费者,会引起服务雪崩。

所以针对服务调用都要设置一个超时时间,以避免依赖的服务迟迟没有返回调用结果,把服务消费者拖死。 超时时间的设定不是越短越好: - 太短可能会导致有些服务调用还没有来得及执行完就被丢弃 - 太长有可能导致服务消费者被拖垮

合适的超时时间需要根据正常情况下,服务提供者的服务水平来决定。即按照服务提供者线上真实的服务水平,取P999或者P9999的值,也就是以99.9%或者99.99%的调用都在多少毫秒内返回为准。

重试

虽然设置超时时间可及时止损,但是服务调用结果毕竟失败,而大部分情况下,调用失败都是因为偶发的网络问题或者个别服务提供者节点有问题,若能换个节点再次访问说不定就成功。 假如一次服务调用失败的概率为1%,那么连续两次服务调用失败的概率就是0.01%,失败率降低到原来的1%。

所以,在实际服务调用时,经常还要设置一个服务调用超时后的重试次数。 假如某个服务调用的超时时间设置为100ms,重试次数设置为1,那么当服务调用超过100ms后,服务消费者就会立即发起第二次服务调用,而不会再等待第一次调用返回的结果了。

双发

假如一次调用不成功的概率为1%,那么连续两次调用都不成功的概率就是0.01%,根据这个推论,一个简单的提高服务调用成功率的办法就是每次服务消费者要发起服务调用的时候,都同时发起两次服务调用,一方面可以提高调用的成功率,另一方面两次服务调用哪个先返回就采用哪次的返回结果,平均响应时间也要比一次调用更快,这就是双发。

但是这样的话,一次调用会给后端服务两倍的压力,所要消耗的资源也是加倍的,所以一般情况下,这种“鲁莽”双发不可取。

更为聪明的双发,即“备份请求”(Backup Requests) 服务消费者发起一次服务调用后,在给定的时间内如果没有返回请求结果,那么服务消费者就立刻发起另一次服务调用。 注意该设定时间通常要比超时时间短得多,比如超时时间取P999,那么备份请求时间取的可能是P99或P90,因为若在P99或者P90时间内调用还没有返回结果,那么大概率可以认为这次请求属于慢请求,再次发起调用理论上返回要更快。

在实际线上服务运行时,P999由于长尾请求时间较长的缘故,可能要远远大于P99和P90。 比如一个服务的P999是1s,而P99只有200ms、P90只有50ms,这样的话,如果备份请求时间取的是P90,那么第二次请求等待的时间只有50ms。不过这里需要注意的是,备份请求要设置一个最大重试比例,以避免在服务端出现问题的时,大部分请求响应时间都会超过P90,导致请求量几乎翻倍,给服务提供者造成更大的压力。 经验是这个最大重试比例可设置成15%,一方面能尽量体现备份请求的优势,另一方面不会给服务提供者额外增加太大的压力。

熔断

前面讲得一些手段在服务提供者偶发异常时会很有效,但若服务提供者出现故障,短时间内无法恢复时,无论是超时重试还是双发不但不能提高服务调用的成功率,反而会因为重试给服务提供者带来更大的压力,从而加剧故障。

就需要服务消费者能够探测到服务提供者发生故障,并短时间内停止请求,给服务提供者故障恢复的时间,待服务提供者恢复后,再继续请求。这就好比一条电路,电流负载过高的话,保险丝就会熔断,以防止火灾的发生,所以这种手段就被叫作“熔断”。

熔断原理

熔断就是把客户端的每一次服务调用用断路器封装起来,通过断路器来监控每一次服务调用。如果某一段时间内,服务调用失败的次数达到一定阈值,那么断路器就会被触发,后续的服务调用就直接返回,也就不会再向服务提供者发起请求了。

熔断之后,一旦服务提供者恢复之后,服务调用如何恢复呢?这就牵扯到熔断中断路器的几种状态。 - Closed状态:正常情况下,断路器是处于关闭状态的,偶发的调用失败也不影响。 - Open状态:当服务调用失败次数达到一定阈值时,断路器就会处于开启状态,后续的服务调用就直接返回,不会向服务提供者发起请求。 - Half Open状态:当断路器开启后,每隔一段时间,会进入半打开状态,这时候会向服务提供者发起探测调用,以确定服务提供者是否恢复正常。如果调用成功了,断路器就关闭;如果没有成功,断路器就继续保持开启状态,并等待下一个周期重新进入半打开状态。

关于断路器的实现,最经典也是使用最广泛的莫过于Netflix开源的Hystrix了,下面我来给你介绍下Hystrix是如何实现断路器的。

Hystrix的断路器也包含三种状态:关闭、打开、半打开。Hystrix会把每一次服务调用都用HystrixCommand封装起来,它会实时记录每一次服务调用的状态,包括成功、失败、超时还是被线程拒绝。当一段时间内服务调用的失败率高于设定的阈值后,Hystrix的断路器就会进入进入打开状态,新的服务调用就会直接返回,不会向服务提供者发起调用。再等待设定的时间间隔后,Hystrix的断路器又会进入半打开状态,新的服务调用又可以重新发给服务提供者了;如果一段时间内服务调用的失败率依然高于设定的阈值的话,断路器会重新进入打开状态,否则的话,断路器会被重置为关闭状态。

其中决定断路器是否打开的失败率阈值可以通过下面这个参数来设定:

HystrixCommandProperties.circuitBreakerErrorThresholdPercentage() 而决定断路器何时进入半打开的状态的时间间隔可以通过下面这个参数来设定:

HystrixCommandProperties.circuitBreakerSleepWindowInMilliseconds() - 断路器实现的关键就在于如何计算一段时间内服务调用的失败率,那么Hystrix是如何做的呢? 滑动窗口算法

Hystrix通过滑动窗口来对数据进行统计,默认情况下,滑动窗口包含10个桶,每个桶时间宽度为1秒,每个桶内记录了这1秒内所有服务调用中成功的、失败的、超时的以及被线程拒绝的次数。当新的1秒到来时,滑动窗口就会往前滑动,丢弃掉最旧的1个桶,把最新1个桶包含进来。

任意时刻,Hystrix都会取滑动窗口内所有服务调用的失败率作为断路器开关状态的判断依据,这10个桶内记录的所有失败的、超时的、被线程拒绝的调用次数之和除以总的调用次数就是滑动窗口内所有服务的调用的失败率。

总结

微服务架构下服务调用失败的几种常见手段:超时、重试、双发以及熔断,实际使用时,具体选择哪种手段要根据具体业务情况来决定。

大部分的服务调用都需要设置超时时间以及重试次数,当然对于非幂等的也就是同一个服务调用重复多次返回结果不一样的来说,不可以重试,比如大部分上行请求都是非幂等的。至于双发,它是在重试基础上进行一定程度的优化,减少了超时等待的时间,对于长尾请求的场景十分有效。采用双发策略后,服务调用的P999能大幅减少,经过我的实践证明是提高服务调用成功率非常有效的手段。而熔断能很好地解决依赖服务故障引起的连锁反应,对于线上存在大规模服务调用的情况是必不可少的,尤其是对非关键路径的调用,也就是说即使调用失败也对最终结果影响不大的情况下,更加应该引入熔断。

参考

  • https://martinfowler.com/bliki/CircuitBreaker.html
  • https://github.com/Netflix/Hystrix/wiki/How-To-Use

设置失败重新发起_微服务架构下请求调用失败了怎么办!相关推荐

  1. 代码管理规范_微服务架构下代码管理规范

    当下对于代码的管理,主要采用GitLab或GitHub,然而使用git进行代码管理过程中,一般有四种开发模式,分别为主干开发主干发布,主干开发分支发布,分支开发主干发布,分支开发分支发布.四种开发模式 ...

  2. mysql 排名_微服务架构下,如何利用Mysql的limit配合orderby进行排名统计

    欢迎关注我的头条号:Wooola,10年Java软件开发及架构设计经验,专注于Java.Golang.微服务架构,致力于每天分享原创文章.快乐编码和开源技术. 前言 我们常用Mysql数据库的limi ...

  3. mysql微服务查询问题_微服务架构下,Mysql读写分离后,数据库CPU飙升卡壳问题解析...

    前言 最近系统(基于SpringCloud+K8s)上线,运维团队早上8点左右在群里反馈,系统登录无反应!我的第一反应是Mysql数据库扛不住了. 排查问题也是一波三折,有网络问题,也有mysql读写 ...

  4. 微服务跨数据库联合查询_微服务架构下,解决数据库跨库查询的一些思路

    加关注,不迷路! 前言 在服务做微服务改造后,原先单库join查询已经不能满足要求,每个拆分的微服务对应一个数据库实例,而且部署在不同的服务器上,那么解决"跨库查询"就势在必行了. ...

  5. 微服务 松耦合_超值干货:微服务架构下如何解耦,对于已经紧耦合下如何重构?...

    今天准备谈下微服务架构下各个微服务间如何解耦,以及对于已经紧耦合的微服务如何进行重构.要明白实际上微服务后续出现的诸多问题往往都是一开始微服务模块划分就不合理导致,对于具体的模块划分方法和原则,我总结 ...

  6. 分布式 java 应用:基础与实践_单集群数据超1000亿,微服务架构下分布式数据库应用实践...

    如今,大型企业的应用平台正在向微服务架构进行转型.在微服务架构下,应用程序和数据库等底层平台的关系将会被重构. 作为新一代分布式数据库,其架构与功能特性需要保证在与传统数据库全兼容的基础上,拥抱微服务 ...

  7. python微服务架构设计模式_微服务架构设计模式 PDF 电子书 百度云 网盘下载

    你还没有注册,无法下载本站所有资源,请立即注册! 您需要 登录 才可以下载或查看,没有帐号?立即注册 x java自学网(http://www.137zw.com)-java论坛,java电子书推荐: ...

  8. Re:从 0 开始的微服务架构--(四)如何保障微服务架构下的数据一致性--转

    原文地址:http://mp.weixin.qq.com/s/eXvoJew3bjFKzLLJpS0Otg 随着微服务架构的推广,越来越多的公司采用微服务架构来构建自己的业务平台.就像前边的文章说的, ...

  9. (转)如何保障微服务架构下的数据一致性?

    转自: https://cloud.tencent.com/developer/article/1459734 [1]写在前面 随着微服务架构的推广,越来越多的公司采用微服务架构来构建自己的业务平台. ...

最新文章

  1. (读书笔记).NET大局观-.NET语言(1)
  2. mysql的or能去重吗_mysql条件查询中AND与OR联合使用的注意事项!
  3. Android ADB被占用 重启 ADB方法
  4. AngularJS 2.0 学习记录(一)
  5. 把JavaScript代码写在css里
  6. 3、常用数据库访问接口简介
  7. 【谷歌】Google Chrome 浏览器中 font-size 12px 没有效果
  8. Storm精华问答 | 为什么这么多人用Spark而不用Storm?
  9. 你所不知道的Quartz特性
  10. 三大协议NetBEUI和 IPX/SPX TCP/IP
  11. 服务器系统怎么么安装手绘板驱动,wacom数位板如何使用?wacom数位板驱动安装教程!...
  12. ToLua(LuaFramework) -ToLua框架使用指南
  13. 逻辑清晰四个实用原则(金字塔原理)
  14. html单页模板wap,单页模板html
  15. 认识PaaS、SaaS、LaaS、aPaaS(一堆废话,谨慎进入)
  16. Android---WMS核心分析
  17. 用户画像(一):我对用户画像的理解
  18. 发票核验API 分享推荐
  19. [Discuz!] 头像HTML5上传 1.2 (saya_avatarupload)支持手机版
  20. You are pushing more GUIClips than you are popping. Make sure they are balanced(Unity Console错误提示)

热门文章

  1. 支付宝公布“五一”出境游报告:国人太能花钱了
  2. 继腾讯后 B站又获阿里投资!加速二次元电商商业化
  3. 为什么面试你要25K,测试总监只给你15K
  4. npm WARN stylus-loader@3.0.2 requires a peer of stylus@>=0.52.4 but none is installed. You must inst
  5. php-fpm的安装与测试
  6. Golang实践录:调用C++函数的优化
  7. 5u以太网用交换机连接电脑_干货丨如何用自己的电脑直接连接NUS打印机
  8. 95-30-018-Channel-AbstractNioByteChannel
  9. 【kafka】kafka 消费速度 小于 日志清理速度 (kafka数据被清理了)会发生什么 auto.offset.reset 参数
  10. 《Elasticsearch 源码解析与优化实战》样章-第 6 章 数据模型