如何避免服务器端大量出现 TIME_WAIT的情况处理机制的说明:
目前正在做的服务器代码, 设计机制上要避免出现大量WAIT_WAIT,
TCP/IP连接, 谁先发起拆线, 谁就要socket TIME_WAIT(30秒-4分钟,取决于unix版本和设置)
我做的服务器代码, 目前只有一种情况下, 服务器端将主动发起拆线, 就是 读超时, 也是空闲超时.
服务器端读超时前, 服务器端长时间处于收态, 服务器端定时器任务在该socket上发shutdown receive, 关服务器端receive, EOF标志被附加到服务器端接收缓冲区的最后,
服务器端receive收完缓冲区的数据, 将收EOF,
客户端TCP/IP底层将收到EOF标志, 客户端send如果发包, 也检测Error_code收EOF, 则客户端立即能够知道 , 此包未发成功, 可立即发起双向拆线 , 重连, 重发, 对方先拆, 服务器端无TIME_WAIT.
客户端中间只有1个很小的窗口期属于不确定状态, 对此期间的send数据包, 客户端send只能确认数据包进入本地发送缓冲区, 无法确认数据包最终下落, 发送后, 进入收态, .
客户端如果send未发包, 则不能检测send通道EOF, 处于收态,
服务器端receive收完缓冲区的数据, 并处理发送完毕, 再接收 将收EOF, BOOST asio receive_handler error_code=2, 同时服务器端检测发现内部read_time_out_set标志, 将执行关闭服务器端send, 然后定时器等待, 此EOF标志被附加到服务器端发送缓冲区的最后, 客户端在收完缓冲区所有数据后, 客户端receive EOF, 客户端将发起双向拆线, 服务器端无TIME_WAIT
服务器端在延迟一段时间后, 99%以上的概率, 对方已经主动发起了拆线, 尤其是本地局域网,数据收发很快, 只有很小的概率, 数据和EOF未能在此期间发送到对方, 此时, 服务器端定时器发起主动拆线, 如果采用hard_close, 此时将清空所有缓冲区的数据, reset连接, 服务器端无TIME_WAIT, 满足高性能服务器的要求;
如果采用soft_close, 就是普通的拆线流程, 此时所有缓冲区的数据被保留, 服务器端主动发起拆线, 系统将进入TIME_WAIT(30秒-240秒,取决于*inx版本和设置), 此方式可满足高可靠服务器的要求.
定时器的间隔可以设的很小, 然后轮询计数, 检查TCP/IP底层is_socket_connected( int socket_handle ), 如果对方已经断开, 就可以不等到最大等待时长.
这里需要说明的是: 对于高可靠性设计原则的客户端, 需要在上述的"receive EOF, 客户端发起双向拆线"时, 增加 检查并确认, 是否收到响应包.并启动重连, 没有收到响应包, 要重连重发.做到不丢包.
对于普通客户端, 例如:linux telnet等, 都会在上面的过程中, 主动发起disconnect, 并 退出服务.
其余的所有情况都可以ASIO析构方式关闭, 或者close方式关闭. 因为都是对方主动拆的, TIME_WAIT在对方
|