TCP keepalive 机制
一. TCP keep-alive 的起源
双方建立交互的连接,但是并不是一直存在数据交互,有些连接会在数据交互完毕后,主动释放连接,而有些不会,那么在长时间无数据交互的时间段内, 交互双方都有可能出现掉电、死机、异常重启等各种意外,当这些意外发生之后,这些 TCP 连接并未来得及正常释放,那么,连接的另一方并不知道对端的情况, 它会一直维护这个连接,长时间的积累会导致非常多的半打开连接,造成端系统资源的消耗和浪费,为了解决这个问题,在传输层可以利用 TCP 的保活报文来实现。
二. TCP keep-alive 存在的作用
2.1 探测连接的对端是否存活
在应用交互的过程中,可能存在以下几种情况: (1)客户端或服务器意外断电,死机,崩溃,重启。 (2)中间网络已经中断,而客户端与服务器并不知道。
利用保活探测功能,可以探知这种对端的意外情况,从而保证在意外发生时,可以释放半打开的 TCP 连接。
2.2 防止中间设备因超时删除连接相关的连接表
中间设备如防火墙等,会为经过它的数据报文建立相关的连接信息表,并为其设置一个超时时间的定时器,如果超出预定时间,某连接无任何报文交互的话, 中间设备会将该连接信息从表中删除,在删除后,再有应用报文过来时,中间设备将丢弃该报文,从而导致应用出现异常,这个交互的过程大致如下图所示:
这种情况在有防火墙的应用环境下非常常见,这会给某些长时间无数据交互但是又要长时间维持连接的应用(如数据库)带来很大的影响,为了解决这个问题,应用本身或 TCP 可以通过保活报文来维持中间设备中该连接的信息,(也可以在中间设备上开启长连接属性或调高连接表的释放时间来解决,但是,这个影响可能较大,有机会再针对这个做详细的描述,在此不多说)。
三. 常见应用故障场景
某财务应用,在客户端需要填写大量的表单数据,在客户端与服务器端建立 TCP 连接后,客户端终端使用者将花费几分钟甚至几十分钟填写表单相关信息,终端使用者终于填好表单所需信息后,点击“提交”按钮,结果,这个时候由于中间设备早已经将这个 TCP 连接从连接表中删除了,其将直接丢弃这个报文或者给客户端发送 RST 报文,应用故障产生,这将导致客户端终端使用者所有的工作将需要重新来过,给使用者带来极大的不便和损失。
四. TCP 保活报文交互过程
TCP 保活可能带来的问题
- 中间设备因大量保活连接,导致其连接表满:网关设备由于保活问题,导致其连接表满,无法新建连接(XX 局网闸故障案例)或性能下降严重
- 正常连接被释放:当连接一端在发送保活探测报文时,中间网络正好由于各种异常(如链路中断、中间设备重启等)而无法将该保活探测报文正确转发至对端时,可能会导致探测的一方释放本来正常的连接,但是这种可能情况发生的概率较小,另外,一般也可以增加保活探测报文发生的次数来减小这种情况发生的概率和影响
五. HTTP keep-alive
Httpd 守护进程,一般都提供了 keep-alive timeout 时间设置参数。比如 nginx 的 keepalive_timeout,和 Apache 的 KeepAliveTimeout
这个 keepalive_timout 时间值意味着:一个 http 产生的 tcp 连接在传送完最后一个响应后,还需要 hold 住 keepalive_timeout 秒后,才开始关闭这个连接。
当 httpd 守护进程发送完一个响应后,理应马上主动关闭相应的 tcp 连接,设置 keepalive_timeout 后,httpd 守护进程会想说:”再等等吧,看看浏览器还有没有请求过来”,
这一等,便是 keepalive_timeout 时间。如果守护进程在这个等待的时间里,一直没有收到浏览器发过来 http 请求,则关闭这个 http 连接。
- 在没有设置 keepalive_timeout 情况下,一个 socket 资源从建立到真正释放需要经过的时间是:建立 tcp 连接 + 传送 http 请求 + php 脚本执行 + 传送 http 响应 + 关闭 tcp 连接
- 设置了 keepalive_timout 时间情况下,一个 socket 建立到释放需要的时间是多了 keepalive_timeout 时间。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论