前言:
Tcp/ip协议对网络编程的重要性,进行过网络开发的人员都知道,我们所编写的网络程序除了硬件,结构等限制,通过修改Tcp/ip内核参数也能得到很大的性能提升,
下面就列举一些Tcp/ip内核参数,解释它们的含义并通过修改来它们来优化我们的网络程序,主要是针对高并发情况。
这里网络程序主要指的是服务器端
1. fs.file-max
最大可以打开的文件描述符数量,注意是整个系统。
在服务器中,我们知道每创建一个连接,系统就会打开一个文件描述符,所以,文件描述符打开的最大数量也决定了我们的最大连接数
select在高并发情况下被取代的原因也是文件描述符打开的最大值,虽然它可以修改但一般不建议这么做,详情可见unp select部分。
2.net.ipv4.tcp_max_syn_backlog
Tcp syn队列的最大长度,在进行系统调用connect时会发生Tcp的三次握手,server内核会为Tcp维护两个队列,Syn队列和Accept队列,Syn队列是指存放完成第一次握手的连接,Accept队列是存放完成整个Tcp三次握手的连接,修改net.ipv4.tcp_max_syn_backlog使之增大可以接受更多的网络连接。
注意此参数过大可能遭遇到Syn flood攻击,即对方发送多个Syn报文端填充满Syn队列,使server无法继续接受其他连接
可参考此文http://tech.uc.cn/?p=1790
我们看下 man 手册上是如何说的:
The behavior of the backlog argument on TCP sockets changed with Linux 2.2. Now it specifies the queue length for com‐ pletely 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 /proc/sys/net/ipv4/tcp_max_syn_backlog. When syncookies are enabled there is no logical maximum length and this setting is ignored. See tcp(7) for more information. If the backlog argument is greater than the value in /proc/sys/net/core/somaxconn, then it is silently truncated to that value; the default value in this file is 128. In kernels before 2.4.25, this limit was a hard coded value, SOMAXCONN, with the value 128.
自 Linux 内核 2.2 版本以后,backlog 为已完成连接队列的最大值,未完成连接队列大小以 /proc/sys/net/ipv4/tcp_max_syn_backlog 确定,但是已连接队列大小受 SOMAXCONN 限制,为 min(backlog, SOMAXCONN)
3.net.ipv4.tcp_syncookies
修改此参数可以有效的防范上面所说的syn flood攻击
原理:在Tcp服务器收到Tcp Syn包并返回Tcp Syn+ack包时,不专门分配一个数据区,而是根据这个Syn包计算出一个cookie值。在收到Tcp ack包时,Tcp服务器在根据那个cookie值检查这个Tcp ack包的合法性。如果合法,再分配专门的数据区进行处理未来的TCP连接。
默认为0,1表示开启
4.net.ipv4.tcp_keepalive_time
Tcp keepalive心跳包机制,用于检测连接是否已断开,我们可以修改默认时间来间断心跳包发送的频率。
keepalive一般是服务器对客户端进行发送查看客户端是否在线,因为服务器为客户端分配一定的资源,但是Tcp 的keepalive机制很有争议,因为它们可耗费一定的带宽。
Tcp keepalive详情见Tcp/ip详解卷1 第23章
5.net.ipv4.tcp_tw_reuse
我的上一篇文章中写到了time_wait状态,大量处于time_wait状态是很浪费资源的,它们占用server的描述符等。
修改此参数,允许重用处于time_wait的socket。
默认为0,1表示开启
6.net.ipv4.tcp_tw_recycle
也是针对time_wait状态的,该参数表示快速回收处于time_wait的socket。
默认为0,1表示开启
7.net.ipv4.tcp_fin_timeout
修改time_wait状的存在时间,默认的2MSL
注意:time_wait存在且生存时间为2MSL是有原因的,见我上一篇博客为什么会有time_wait状态的存在,所以修改它有一定的风险,还是根据具体的情况来分析。
8.net.ipv4.tcp_max_tw_buckets
所允许存在time_wait状态的最大数值,超过则立刻被清楚并且警告。
9.net.ipv4.ip_local_port_range
表示对外连接的端口范围。
10.somaxconn
前面说了Syn队列的最大长度限制,somaxconn参数决定Accept队列长度,在listen函数调用时backlog参数即决定Accept队列的长度,该参数太小也会限制最大并发连接数,因为同一时间完成3次握手的连接数量太小,server处理连接速度也就越慢。服务器端调用accept函数实际上就是从已连接Accept队列中取走完成三次握手的连接。
Accept队列和Syn队列是listen函数完成创建维护的。
/proc/sys/net/core/somaxconn修改
上面每一个参数其实都够写一篇文章来分析了,这里我只是概述下部分参数,注意在修改Tcp参数时我们一定要根据自己的实际需求以及测试结果来决定。