转载

Java面试-TCP连接及其优化

作为一个后端程序员,网络连接这块是一个绕不过的砍,当你在做服务器优化的时候,网络优化也是其中一环,那么作为网络连接中最基础的部分- TCP连接 你了解吗?今天我们来仔细看看这个部分。

<!-- more -->

TCP建立连接-三次握手

详解

Java面试-TCP连接及其优化

listen
SYN_SENT
SYN_RCVD
ESTABLISHED
ESTABLISHED

其中步骤2~4就是三次握手,那么为什么需要三次握手呢?为什么不是一次或者两次握手呢?

首先,我们需要知道,只有当服务器和客户端都能确保自己能够发消息和接收消息,这次网络通信才算成功的。

步骤2的作用是让服务器知道了自己是可以接收消息的。

步骤3的作用是让客户端知道自己发送消息和接收消息的功能是OK的,发送消息的能力是通过服务器返回的 ack=x+1 确认的,因为这个值基于当初客户端发送的消息 seq=x 。接收消息的能力是因为收到了服务器的返回。

步骤4的作用是让服务器端知道自己发送消息的能力是OK的(和步骤3类似)。

linux查看

linux服务器可以利用 netstat -anp | grep tcp 命令,查看服务器上各个端口和应用的连接状态。

你还可以通过修改linux的配置文件 /etc/sysctl.conf ,调整各个状态的数量

SYN_SENT 状态相关

  • 主动建立连接时,发SYN(步骤2)的重试次数
nct.ipv4.tcp_syn_rctries = 6
  • 建立连接时的本地端口可用范围
net.ipv4.ip_local_port_range = 32768 60999

SYN_RCVD 状态相关

  • SYN_RCVD 状态连接的最大个数
net.ipv4.tcp_max_syn_backlog
  • 被动建立连接时,发SYN/ACK(步骤3)重试次数
net.ipv4.tcp_synack_retries

说完了TCP建立连接,接下来,我们再来看看TCP正常断开连接的过程

TCP断开连接-四次挥手

详解

Java面试-TCP连接及其优化

FIN_WAIT1
CLOSE_WAIT
FIN_WAIT2
LAST_ACK
TIME_WAIT
CLOSED
CLOSED

其中,步骤2、3、5、6即为4次挥手。

TIME_WAIT 状态及其优化

看完之后,大家想必会有一个疑问,为什么 TIME_WAIT 状态需要保持2MSL?因为这可以保证至少一次报文的往返时间内,端口是不可复用的。

假设 TIME_WAIT 状态的持续时间很短,我们来模拟下面这种场景:

Java面试-TCP连接及其优化

TIME_WAIT

因此这也是 TIME_WAIT 状态需要保持2MSL的原因,如果这么长时间也没有收到报文,即使有正确的报文从客户端发出,也已经过期了,因此不会影响到之后的通信。

但这同样也会带来一个问题, TIME_WAIT 状态保持的时间较长,假设服务器端有大量 TIME_WAIT 状态的TCP连接,就相当于白白浪费掉大量的服务器资源(端口)。此时,我们可以通过修改以下配置进行服务器调优:

net.ipv4.tcp_tw_reuse = 1
TIME_WAIT
net.ipv4.tcp_timestamps = 1

其他状态的优化

CLOSE_WAIT 状态

如果服务器端有大量 CLOSE_WAIT 状态的连接,很有可能是应用进程出现bug,没有及时关闭连接。

FIN_WAIT1 状态

调整发送FIN报文的重试次数,0相当于8

net.ipv4.tcp_orphan_retries = 0

FIN_WAIT2 状态

调整保持在 FIN_WAIT2 状态的时间

net.ipv4.tcp_fin_timeout = 60

总结

看到这里,想必你应该对TCP连接有了一个大致的了解。现在服务器大多都用了nginx做了负载均衡,因此,我们可能需要在此基础上了解一些nginx相关的配置原理,这样应该会对我们的服务器性能调优会有更大的帮助。有兴趣的同学不妨可以去了解一下,如果有什么新发现想和作者探讨的,欢迎在下方留言。

有兴趣的话可以关注我的公众号,说不定会有意外的惊喜。

Java面试-TCP连接及其优化

原文  https://segmentfault.com/a/1190000020369089
正文到此结束
Loading...