Linux 内核参数--网络相关参数
TCP 建立连接时要经过 3 次握手,在客户端向服务器发起连接时,对于服务器而言,一个完整的连接建立过程,服务器会经历 2 种 TCP 状态:SYN_REVD, ESTABELLISHED
对应也会维护两个队列:
-
一个存放 SYN 的队列(半连接队列)
-
一个存放已经完成连接的队列(全连接队列)
当一个连接的状态是 SYN RECEIVED 时,它会被放在 SYN 队列中
当它的状态变为 ESTABLISHED 时,它会被转移到另一个队列。
所以后端的应用程序只从已完成的连接的队列中获取请求
如果一个服务器要处理大量网络连接,且并发性比较高,那么这两个队列长度就非常重要了。因为,即使服务器的硬件配置非常高,服务器端程序性能很好,但是这两个队列非常小,那么经常会出现客户端连接不上的现象,因为这两个队列一旦满了后,很容易丢包,或者连接被复位。所以,如果服务器并发访问量非常高,那么这两个队列的设置就非常重要了。
Linux backlog 参数意义
对于 Linux 而言,基本上任意语言实现的通信框架或服务器程序在构造 socket server 时,都提供了 backlog 这个参数,因为在监听端口时,都会调用系统底层 API: int listen(int sockfd, int backlog);
listen 函数中 backlog 参数的定义如下:
Now it specifies the queue length for completely established sockets waiting to be accepted,instead of the number of incomplete connection requests. The maximum length of the queue for incomplete sockets can be set using the tcp_max_syn_backlog sysctl. When syncookies are enabled there is no logical maximum length and this sysctl setting is ignored.If the socket is of type AF_INET, and the backlog argument is greater than the constant SOMAXCONN(128 default), it is silently truncated to SOMAXCONN.
backlog 参数描述的是服务器端 TCP ESTABELLISHED 状态对应的全连接队列长度。
ESTABLISHED列长度如何计算?
如果 backlog 大于内核参数 net.core.somaxconn,则以 net.core.somaxconn 为准,
即全连接队列长度 = min(backlog, 内核参数 net.core.somaxconn),net.core.somaxconn 默认为 128。
这个很好理解,net.core.somaxconn 定义了系统级别的全连接队列最大长度,
backlog 只是应用层传入的参数,不可能超过内核参数,所以 backlog 必须小于等于 net.core.somaxconn。
SYN_RECV队列长度如何计算?
半连接队列长度由内核参数 tcp_max_syn_backlog 决定,当使用 SYN Cookie 时(就是内核参数 net.ipv4.tcp_syncookies = 1),这个参数无效.
net.ipv4.tcp_max_syn_backlog 指内核允许最大的TCP连接请求,这个连接请求还没有真正的被客户端取走或消费。
如果tcp请求高于此参数值的设置,内核会直接放弃这些新的tcp连接请求。
tcp连接请求越高,消耗内存越大,内存充足的情况下,可以酌情提增加tcp_max_syn_backlog。
半连接队列的最大长度为 backlog、内核参数 net.core.somaxconn、内核参数 tcp_max_syn_backlog 的最小值。
即半连接队列长度 = min(backlog, 内核参数 net.core.somaxconn,内核参数 tcp_max_syn_backlog)。
这个公式实际上规定半连接队列长度不能超过全连接队列长度,但是tcp_syncooking默认是启用的,如果按上文的理解,那这个参数设置没有多大意义
其实,对于 Nginx/Tomcat 等这种 Web 服务器,都提供了 backlog 参数设置入口,当然它们都会有默认值,通常这个默认值都不会太大(包括内核默认的半连接队列和全连接队列长度)。如果应用并发访问非常高,只增大应用层 backlog 是没有意义的,因为可能内核参数关于连接队列设置的都很小,一定要综合应用层 backlog 和内核参数一起看,通过公式很容易调整出正确的设置
1、/proc/sys/net/ipv4/tcp_max_syn_backlog
/proc/sys/net/ipv4/tcp_max_syn_backlog 参数表示 设置SYN队列最大长度,默认值为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数,普通Web服务器建议设置为:
echo 8192 > /proc/sys/net/ipv4/tcp_max_syn_backlog
修改系统内核参数,可以编辑/etc/sysctl.conf去调整它。如:net.ipv4.tcp_max_syn_backlog = 2048,改完后执行sysctl -p 让修改立即生效。
2、 /proc/sys/net/core/netdev_max_backlog
/proc/sys/net/core/netdev_max_backlog 参数是用来设置每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数。默认值为1000.
echo 3000 > /proc/sys/net/core/netdev_max_backlog
3、 /proc/sys/net/core/rmem_max wmem_max
这两个参数可以 提高TCP 最大缓冲区大小。
rmem:表示接收套接字缓冲区大小的最大值
wmem:表示发送套接字缓冲区大小的最大值
echo 16777216 > /proc/sys/net/core/rmem_max
echo 16777216 > /proc/sys/net/core/wmem_max
4、/proc/sys/net/core/tcp_rmem tcp_wmem
这两个参数可以提高Linux 内核自动对Socket缓冲区进行优化的能力
tcp_rmem:用来配置读缓冲的大小第一个值为最小值,第二个值为 默认值,第三个值为最大值
tcp_wmem: 用来配置写缓冲的大小第一个值为最小值,第二个值为 默认值,第三个值为最大值
echo "4096 87380 16777216" > /proc/sys/net/core/tcp_rmem
echo "4096 87380 16777216" > /proc/sys/net/core/tcp_wmem
5、/proc/sys/net/core/somaxconn
/proc/sys/net/core/somaxconn 参数用来设置Socket监听的backlog上限。backlog是Socket监听队列,当一个请求尚未被处理或者建立时,他会进入backlog。当Server 处理请求较慢时,监听队列被塞满,新来的请求就会被拒绝。默认值为128.
echo 4096 > /proc/sys/net/core/somaxconn
6、net.ipv4.tcp_max_tw_buckets
表示系统同时保持TIME_WAIT套接字的最大数量,如果超过这个数值,TIME_WAIT套接字将立刻被清除并打印警告信息。 默认为180000,对于Apache、Nginx等服务器来说可以将其调低一点,如改为5000~30000,不通业务的服务器也可以给大一点,比如LVS、Squid。 此项参数可以控制TIME_WAIT套接字的最大数量,避免Squid服务器被大量的TIME_WAIT套接字拖死。
何为套接字(Socket)
套接字是通信的基石,是支持TCP/IP协议的路通信的基本操作单元。可以将套接字看作不同主机间的进程进行双间通信的端点。
表示方法: 套接字Socket=(IP地址:端口号),每一个传输层连接唯一地被通信两端的两个端点(即两个套接字)所确定