信号和 TIME_WAIT 对大并发服务器的影响
如果客户端主动关闭套接字(close),而服务器调用了一次write,服务器会接收一个 RST Segment(复位报文段,TCP传输层),如果服务器再次调用write,这个时候就会产生SIGPIPE信号,进程对SIGPIPE 信号的默认处理方式是关闭,因此在服务器程序中应忽略这个信号。
sigaction(SIGPIPE, IGN);
TIME_WAIT状态对大并发服务器的影响:
如果服务器主动断开连接(先于client调用close),服务端就会进入 TIME_WAIT 状态。
TIME_WAIT存在的原因:(1)、可靠的终止TCP连接;(2)、保证迟来的TCP报文段有足够的时间被识别并丢弃。
TIME_WAIT的存在时长为2MSL,在这段时间内,我们无法立即使用该连接占用的端口建立一个新连接。
应尽可能在服务器端避免TIME_WAIT 状态:
在协议的设计上应该让客户端主动断开连接,这样就把 TIME_WAIT 分散到大量的客户端。如果客户端不活跃了,一些客户端不断开连接,就会占用服务端的资源。服务端应有相应的机制来关闭不活跃的连接(close)。
服务端可通过设置socket选项SO_REUSEADDR来强制使用被处于TIME_WAIT状态的连接占用socket地址。
<span style="font-family: Arial, Helvetica, sans-serif;"> </span><span style="font-family: Arial, Helvetica, sans-serif;">/*代码示例*/</span>
<span style="white-space:pre"> </span>int reuse = 1;
<span style="white-space:pre"> </span>setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
经过setsockopt的设置后,即时socket处于TIME_WAIT 状态,与之绑定的socket地址也可以立即被重用。此外,我们可以通过修改内核参数 /proc/sys/net/ipv4/tcp_tw_recycle来快速回收被关闭的socket,从而使TCP 连接根本不进入TIME_WAIT状态,进而允许应用程序立即重用本地的socket地址。