问题描述
TCP会话中,首先发起关闭连接(调用 close() 系统调用)的一方在收到对端的 ACK\FIN+ACK 之后会进入到 TIME_WAIT 状态.服务器进入该该状态后,对于从相同的对端 ip 和端口的 tcp 发过来的数据包进行丢弃(Drop)处理.在 linux 系统中,该状态正常会持续1分钟的时间,该事件是硬编码的,不可以调整.
问题一:
此时如果有大量的并发客户端通过一个 SNAT 设备向服务器发起连接,由于客户端的 IP 经过 SNAT 设备,其源 IP 被修改为 NAT 设备的 ip 地址,由于NAT设备的端口有限, 此时就有可能导致 SYN 包被丢弃,连接建立不成功的问题.
问题二:
大量的并发客户端建立连接有断开连接,在服务端留下了大量的 TIME_WAIT 状态的 TCP 会话数据,需要清理,
通用方案零:增加 IP 和端口范围
最通用的解决方案是增加服务端对外开放的ip地址个数和端口个数!
解决方案一:使用 SO_LINGER
当你调用 close()
时,所有尚存在内核 buffer 中的数据将在后台继续发送,socket 将会进入到 TIME-WAIT
状态. 应用可以假设所有的数据将被安全送达.
这种行为被称为 socket lingering,应用可以通过设置 SO_LINGER 来改变或者关闭该机制.SO_LINGER使用如下结构:
struct linger {
int l_onoff; /* 0 = off, nozero = on */
int l_linger; /* linger time */
};
有下