下载安卓APP箭头
箭头给我发消息

客服QQ:3315713922

软件设计:设置默认的超时和重试是一个基础设施的基本素养

作者:编程一生     来源: https://www.cnblogs.com/xiexj/p/10702100.html点击数:1121发布时间: 2020-04-16 15:38:15

标签: java服务器软件设计

  软件设计是从软件需求规格说明书出发,根据需求分析阶段确定的功能设计软件系统的整体结构、划分功能模块、确定每个模块的实现算法以及编写具体的代码,形成软件的具体设计方案。

  设置默认的超时和重试是一个基础设施的基本素养

  What

  本篇应该是稳定性「三十六计」系列的一篇:超时重试。但是「设置默认的超时和重试是一个基础设施的基本素养」这句话我在我们组内三次开会的时候都说了。表达了我的一个理念。

  Why

  为什么一个基础设施要设置默认的超时和重试?想象下面一个场景。

  TCP协议里有一些基本的概念:MSL、TTL、RTT。

  MSL(MaximumSegmentLifetime)

  报文最大生存时间,它是任何报文在网络上存在的最长时间。超时报文就被丢弃。

  TTL(TimeToLive)

  生存时间,是由源主机设置初始值,经常存的是ip数据包可以经过的最大路由数,每经过一个处理路由数减1,当值为0则报文被丢弃。

  RTT(Round-triptime)

  客户端到服务器往返所花时间。

  嗯?不是很明白?这就对了。想象这些东西都没有默认值,需要我们自己去设置,是不是很头大?

  作为基础设施,自己应该是做过数据统计的、做过压测的。自己的性能是什么样的,怎么使用更为合理,基础设施的开发团队最为清楚,不应该将这种设置的责任交给调用方或者客户端来做,加大对基础设施的学习成本。

  再来讨论一个问题:为什么要超时和重试?

  长尾问题

软件设计:设置默认的超时和重试是一个基础设施的基本素养_java_服务器_软件设计_课课家

  如上图,随便找了一个调用的耗时。从上面可以看到平均耗时13.9ms,百分之99的耗时在30ms内,最大耗时有488ms。那对于超过100ms的请求来说,是不是在30ms内还不返回就直接丢弃这个请求重新发起一个,新请求有99%的概率在30ms内返回结果,从时间上更划算?

  而之所以对同一个请求性能差距很大,原因很多,常见的有服务过载和队列过长。

  死锁问题

  想象一个分布式锁,没有超时时间。万一释放锁时失败了,其他人永远不能获取这个锁。而如果有超时时间,锁过期后,其他的请求通过重试是可以获取到锁的。

  How

  怎么设置超时和重试。guava-trying是个不错的java实现。其实不管什么语言都不是难事,难的是超时和重试条件是什么,设置多少合理。

  超时和重试条件根据业务不同有差异。

  一般的超时条件可设置为TP95(95%的请求)的2倍。或者智能一点,根据大数据统计一下,用个机器学习算法看看怎么设置总体耗时最小。

  重试的一个比较好的实践是每次重试的时间间隔成指数级增长,并且根据集群情况设置合理上限。这样就避免本来服务已经过载了,短时间内大量重试造成多米诺骨牌效应(雪崩)。

  合理的上限相当重要,因为有些请求不应该再重试了。比如服务器过载时限流策略收到请求不会将请求交给执行层而是直接返回一个响应。而如果客户端判断:“我去,这么快就给我结果啦!太好了,下个请求继续给力哦~~”这种错误的正反馈循坏可能会成为资源耗尽的最后一根稻草。

  软件设计是把许多事物和问题抽象起来,并且抽象它们不同的层次和角度。将问题或事物分解并模块化使得解决问题变得容易,分解的越细模块数量也就越多,它的副作用就是使得设计者考虑更多的模块之间耦合度的情况。

赞(14)
踩(0)
分享到:
华为认证网络工程师 HCIE直播课视频教程