稳定性三十六计-超时处理

简介: 稳定性三十六计-超时处理

引子


分布式系统调用的三态


在传统的单机系统中,调用一个函数,要么返回成功,要么返回失败。这就是两态系统(2-state system)。


在分布式系统中,由于系统是分布在不同机器上的。还可能有一种状态叫:超时。成功、失败和超时是分布式系统调用的三态。

BJxDAhKQQJ0EFHB10vXZEpDAUwTI7EVBR++zIp8a1xB6RR63eI0dmrf8cc1m85unLnrsWq1WLtrw2TkkIAEJpEZAAZfaijgfCUhAAhKQgAQkUELgX8l9b0tAAhKQgAQkIAEJJEZAAZfYgjgdCUhAAhKQgAQkUEZAAVdGyPsSkIAEJCABCUggMQIKuMQWxOlIQAISkIAEJCCBMgIKuDJC3peABCQgAQlIQAKJEVDAJbYgTkcCEpCABCQgAQ.png


为什么要超时处理


对于超时这种状态,长时间等待会影响用户体验,并发量大时还可能会因为线程池耗尽而不能响应其他请求。如果这个服务的调用方也是一个服务,那就有可能产生级联反应,导致其他服务不可用,最终产生雪崩效应。


FCAAAAAElFTkSuQmCC.png


 

超时处理的手段


超时处理的两个要点:判断什么时候超时和超时后怎么处理。


判断什么时候超时在无基础数据时可通过经验估算一个相对合理值。在服务上线后可依赖统计进行设置,比如设置99%的请求响应时间为超时时间。还可以通过人工智能进行调参来设置。


超时后一般采用快速失败,如果不是核心服务,可直接超时返回失败。如果是核心服务,可以设置相应的重试次数。

 

HTTP请求超时处理


HTTP请求一般会对两个阶段做超时处理:建立连接阶段、数据通信阶段。在apache的HttpClient实现中,添加了获取连接池阶段。


获取连接池阶段


因为建立连接需要IO、网络带宽等开销,需要池化处理,如果超过了连接池的最大值,则需要等待其他连接执行完释放资源。超时时间一般设置为1s之内。


建立建立阶段


HTTP请求需要“三次握手”,第一次握手客户端发送一个报文到服务器表示想和服务端建立连接。第二次握手是服务端接收到客户端的请求,返回带有同步和相应标记的客户端报文,询问客户端是否准备好。第三次握手是客户端再次响应服务端表示已经准备好。超时时间一般设置为1s到5s。


数据通信阶段


与目标url建立连接后,等待数据报文传输的时间。这个阶段又叫做socket通信阶段。这个阶段可能有两种类型的事件:读取和写入。超时时间一般设1s到5s。


FJrePqAAAAAElFTkSuQmCC.png


在以上三个阶段的任何一个阶段发生超时则立即终止等待返回失败,http请求一般会设置超时后有三次重试。为了进一步理解,可以借助HttpClient的调用代码来感受一下其使用


HttpParams httpParams = new BasicHttpParams();
    // 获取连接的最大等待时间1s,对应获取连接池阶段
    ConnManagerParams.setTimeout(httpParams, 1000);
    // 连接超时时间5s,对应建立建立阶段
    HttpConnectionParams.setConnectionTimeout(httpParams, 5000);
    // socket超时时间5s,对应数据通信阶段
    HttpConnectionParams.setSoTimeout(httpParams, 5000);
最近因为OkHttpClient比HttpClient更简单易用,使用的人多起来。借助OkHttpClient的调用代码来感受一下其使用
    OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
    // 连接超时时间5s,对应建立建立阶段
    httpClientBuilder.connectTimeout(config.getConnectionTimeout(), TimeUnit.MILLISECONDS);
    // 读取超时时间5s,对应数据通信阶段(将socket细分为读取和写入两种类型)
    httpClientBuilder.readTimeout(config.getReadTimeout(), TimeUnit.MILLISECONDS);
    // 写入超时时间5s,对应数据通信阶段(将socket细分为读取和写入两种类型)
    httpClientBuilder.writeTimeout(config.getReadTimeout(), TimeUnit.MILLISECONDS);


读取和写入都是socket阶段的一个证据是如果发生超时,曝出的异常是SocketTimeoutException

 

Mysql连接超时处理


客户端和Mysql连接也分为建立连接和数据通信两个阶段。目前mysql常用的版本是5.6和5.7。


和超时处理相关的参数汇总如下

 

参数名称 参数说明 缺省值 最低版本要求
connectTimeout

和数据库服务器简历socket连接时的超时

单位:毫秒。0表示永不超时

0 3.0.1
socketTimeout

socket操作(读写)超时

单位:毫秒。0表示永不超时

0 3.0.1
autoReconnect 当数据库连接异常中断时是否自动重连 false 1.1
maxReconnects autoReconnect=true时,重试连接的次数 3 1.1
failOverReadOnly 自动重连成功后,连接是否设置为只读 true 3.0.12
autoReconnectForPools 是否使用针对数据库连接池的重连策略 False 3.1.3

 

总结


慢就是错

相关文章
|
7月前
|
编译器 调度 C++
协程问题之机制保障中提到的早值班机制和稳定性周会机制分别是什么
协程问题之机制保障中提到的早值班机制和稳定性周会机制分别是什么
|
6月前
|
Java
软件交付质量问题之要提升发布成功率,如何实现
软件交付质量问题之要提升发布成功率,如何实现
|
9月前
|
消息中间件 监控 Java
接口请求重试策略:保障稳定性的必杀技
接口请求重试策略:保障稳定性的必杀技
421 0
|
9月前
|
运维 监控 Java
微服务心跳监测机制讲解与实现,与面试过程中如何回答这个问题
微服务心跳监测机制讲解与实现,与面试过程中如何回答这个问题
212 0
|
设计模式 缓存 架构师
【韧性设计】韧性设计模式:重试、回退、超时、断路器
【韧性设计】韧性设计模式:重试、回退、超时、断路器
|
消息中间件 缓存 运维
多版本并行,测试如何做好质量保障?
第一个是成本问题,单独搭建一套可用的测试环境,包括云服务器、缓存、消息队列和数据库,成本是很高的;
多版本并行,测试如何做好质量保障?
|
Dubbo Java 应用服务中间件
发布稳定性-优雅下线
最近负责的项目已经到达10万 QPS的大关了,这么高的QPS,对系统的稳定性要求也更高了。之前QPS小的时候,系统更新部署很简单,现在不行了,一部署起来,上游应用方就找过来了,说你这应用咋回事,怎么突然抖动厉害了。。。
261 0
发布稳定性-优雅下线
|
缓存 NoSQL 安全
并发-分布式锁质量保障
并发问题是电商系统最常见的问题之一,例如库存超卖、抽奖多发、券多发放、积分多发少发等场景;之所以会出现上述问题,是因为存在多机器多请求同时对同一个共享资源进行修改,如果不加以限制,将导致数据错乱和数据不一致性;解决并发问题的方式有很多,例如:队列、异步、响应式、锁都可以;由于当前互联网都是分布式系统,因此本文只针对使用较为广泛的分布式锁的方式来进行叙述如何进行质量保障
|
Java 数据库 索引
稳定性三十六计-幂等设计
为什么要幂等 世界上最遥远的距离是我终于鼓起勇气,对着马路对面的你大喊:“你愿意娶我吗?”我看到你面带灿烂的笑容,正回答的时候……一辆大卡车驶过,你的回答我没有听见。 因各种不可抗因素产生的没有收到响应,一个简单有效的方法就是重试。被重试的接口必须是幂等的。 幂等性是分布式系统设计中的一个重要概念,对超时处理、系统恢复等具有重要意义。
稳定性三十六计-幂等设计
|
NoSQL 测试技术 Linux
并发-分布式锁质量保障总结
并发问题是电商系统最常见的问题之一,例如库存超卖、抽奖多发、券多发放、积分多发少发等场景;之所以会出现上述问题,是因为存在多机器多请求同时对同一个共享资源进行修改,如果不加以限制,将导致数据错乱和数据不一致性;解决并发问题的方式有很多,例如:队列、异步、响应式、锁都可以;由于当前互联网都是分布式系统,因此本文只针对使用较为广泛的分布式锁的方式来进行叙述如何进行质量保障。
并发-分布式锁质量保障总结