无论是Nginx、百度开源BFE还是其他4层/7层流量代理,套接字连接数上限都存在问题。
此最大连接数问题意味着七层流量代理连接到后端服务,而不是七层流量代理连接到客户端。
为了使客户端与服务端建立连接,客户端必须占用系统分配的端口号。 对于Linux系统,最大可用端口号为65535。
在第7层通信代理和后端服务之间的通信中,第7层通信代理属于客户端,因此第7层通信代理和后端服务之间的连接数有限。
对于长连接,连接数的理论上限为65535。 但是,由于某些系统进程占用一些端口号(如22个端口),因此上限将小于65535。
这种不可修复的缺陷只能在“低配置的多个实例”中增加连接数上限。
对于长连接,存在连接数上限问题,但对于短连接,是否存在此问题?
短链接是指在创建连接后启动一次,等待响应后立即关闭的连接。 但是,由于TCP协议中存在四次挥手的过程,因此连接关闭并不会立即释放端口。 此过程有一个时间窗口,在Linux上,默认大小为120秒。 在这样长时间的窗口中,如果请求数达到546QPS以上,则端口容易变得不可用。
要理解这个问题,首先需要了解TCP协议的四次挥手的过程。
1、客户端向服务端发送标识FIN=1的数据包,告诉服务端客户端不再发送会话数据。 此时,客户端的状态为FIN_WAIT_1。
2、服务端收到FIN请求后,向客户端发送ACK回复数据包,客户端收到ACK后,状态为FIN_WAIT_2,服务端状态为CLOSE_WAIT;
3、服务端向客户端发送指示FIN=1的分组,告知服务端不再发送会话数据。 发送成功后,服务端状态为LAST_ACK;
4、客户端收到FIN请求后向服务端发送ACK应答数据包,然后客户端状态为TIME_WAIT,服务端收到ACK后状态为CLOSED,客户端等待2MSL后关闭
挥手4次的过程中,客户端的TIME_WAIT状态持续2MSL才变为CLOSED。
最大消息传递期限(MSL )或消息的最大生存时间是任何消息在网络上生存的最长时间,并且如果超过该时间,则丢弃该消息。 因此,在2MSL期间,连接占用的端口将处于空闲状态,无法使用。 在Linux系统上,MSL的默认值为60秒,2MSL为120秒。
为什么TIME_WAIT要维持2MSL的时间呢?
第1、4次挥手是客户端向服务端发送ACK,发送完成后客户端直接关闭连接。 如果服务器端由于网络抖动而未收到ACK,则服务器端不会关闭连接。 在2MSL的等待时间内,如果服务器没有收到响应,服务器将继续发送FIN请求。
如果不等待2、2MSL,客户端关闭连接后端口可能会被重用。 在此端口上再次建立与服务器的连接时,前后两个连接四元(src IP端口,dec IP端口)相同,服务器将认为是上一个连接,数据包会发生干扰。