文章目录
六、超时与重试机制——代理层超时与重试
1. 超时与重试机制简介
在实际开发过程中,未设置或设置不当的超时机制常常导致故障。例如,应用未设置超时可能导致请求响应缓慢,慢请求累积引发连锁反应,甚至引发应用雪崩。中间件或框架有时会在超时后进行重试(如设置重试两次),读操作通常适合重试,但写操作(如订单写入)大多不能重试。重试次数过多可能引发请求流量激增,模拟DDoS攻击,因此需要合理设置重试机制,并与熔断和快速失败机制配合。在代码审查时,务必检查超时与重试机制。
本章将从Web应用和服务化应用的角度,介绍如何设置超时与重试。系统层面的超时设置不在本文讨论范围内。
Web应用需要在以下链条中设置超时与重试机制:
- 代理层超时与重试:如Haproxy、Nginx、Twemproxy等,这些组件可以实现代理功能,如Haproxy和Nginx可实现负载均衡,Twemproxy实现Redis分片代理。需要设置代理与后端真实服务器之间的网络连接/读/写超时时间。
- Web容器超时:如Tomcat、Jetty等,提供HTTP服务运行环境的,需设置客户端与容器之间的网络连接/读/写超时时间,以及容器中默认的Socket网络连接/读/写超时时间。
- 中间件客户端超时与重试:如JSF(京东SOA框架)、Dubbo、JMQ(京东消息中间件)、CXF、Httpclient等,需设置客户端的网络连接/读/写超时时间与失败重试机制。
- 数据库客户端超时:如MySQL、Oracle,需分别设置JDBC连接、Statement的网络连接/读/写超时时间,事务超时时间,获取连接池连接等待时间。
- NoSQL客户端超时:如Mongo、Redis,需设置其网络连接/读/写超时时间,获取连接池连接等待时间。
- 业务超时:如订单取消任务、超时活动关闭,或者通过
Future#get(timeout, unit)
限制某接口的超时时间。 - 前端Ajax超时:浏览器通过Ajax访问时的网络连接/读/写超时时间。
本小节将讲解代理层超时与重试:
2. 代理层超时与重试
以下以Nginx和Twemproxy为例进行讲解。
2.1 Nginx
Nginx 是一个高性能的 Web 服务器和反向代理服务器,其超时设置对系统的稳定性和性能至关重要。以下是 Nginx 的主要超时设置及其实际配置示例:
2.1.1 客户端超时设置
客户端超时设置包括以下参数:
-
client_header_timeout
- 描述:设置读取客户端请求头的超时时间。
- 默认值:60 秒。
- 说明:如果客户端在此时间内未发送完请求头,Nginx 会返回 408(Request Timeout)状态码。
-
client_body_timeout
- 描述:设置读取客户端请求体的超时时间。
- 默认值:60 秒。
- 说明:此超时时间指的是两次成功读操作的间隔时间,而非发送整个请求体的时间。如果客户端在此时间内未发送请求体,Nginx 会返回 408(Request Timeout)状态码。
-
send_timeout
- 描述:设置发送响应到客户端的超时时间。
- 默认值:60 秒。
- 说明:此超时时间指的是两次成功写操作的间隔时间,而非发送整个响应的时间。如果在此时间内客户端未接收到任何响应,Nginx 会关闭连接。
-
keepalive_timeout
- 描述:设置 HTTP 长连接的超时时间。
- 参数:第一个参数为 Nginx 的长连接超时时间,第二个参数为响应头中的“Keep-Alive: timeout=time”设置,告知客户端长连接的超时时间。
- 默认值:第一个参数为 75 秒,第二个参数为 60 秒。
- 说明:长连接的超时设置需配合
keepalive_disable
和keepalive_requests
使用。keepalive_disable
用于禁用某些浏览器的长连接支持,默认禁用 MSIE6。keepalive_requests
设置一个客户端通过长连接可以发送的请求次数,默认值为 1000。
实践建议:
- 短连接服务:将超时时间设置得较短,以减少资源占用。
- 长时间操作:如文件上传,可以适当延长超时时间,以避免请求因超时被中断。
- 长连接配置:建议通过抓包工具确认配置是否生效,并根据实际需求调整
keepalive_timeout
、keepalive_disable
和keepalive_requests
的值。
配置示例
http {
# 设置全局超时参数
client_header_timeout 30s; # 客户端请求头超时设置为30秒
client_body_timeout 60s; # 客户端请求体超时设置为60秒
send_timeout 30s; # 响应发送超时设置为30秒
keepalive_timeout 65s 70s; # 长连接超时设置,第一个参数是Nginx的超时时间,第二个参数是客户端超时时间
# 其他设置
keepalive_requests 500; # 一个长连接中允许的最大请求数为500
keepal