Linux下TCP最⼤连接数受限问题
⼀、⽂件数限制修改
1、⽤户级别
查看Linux系统⽤户最⼤打开⽂件限制:
# ulimit -n
1024
(1) vi /etc/f
mysql soft nofile 10240
mysql hard nofile 10240
其中mysql指定了要修改哪个⽤户的打开⽂件数限制。
可⽤'*'号表⽰修改所有⽤户的限制;soft或hard指定要修改软限制还是硬限制;10240则指定了想要修改的新的限制值,即最⼤打开⽂件数(请注意软限制值要⼩于或等于硬限制)。
(2) vi /etc/pam.d/login
session required /lib/security/pam_limits.so
这是告诉Linux在⽤户完成系统登录后,应该调⽤pam_limits.so模块来设置系统对该⽤户可使⽤的各种资源数量的最⼤限制(包括⽤户可打开的最⼤⽂件数限制)。
⽽pam_limits.so模块就会从/etc/f⽂件中读取配置来设置这些限制值。
2、Linux系统级别
查看Linux系统对同时打开⽂件数的硬限制:
# sysctl -a|grep file-max
fs.file-max = 65535
这表明这台Linux系统最多允许同时打开(即包含所有⽤户打开⽂件数总和)65535个⽂件,是Linux系统级硬限制,所有⽤户级的打开⽂件数限制都不会超过这个数值。
通常这个系统级硬限制是Linux系统在启动时根据系统硬件资源状况计算出来的最佳的最⼤同时打开⽂件
数限制。
(1) vi /f
fs.file-max = 1000000
⽴即⽣效:
# sysctl -p
⼆、⽹络端⼝限制修改
查看Linux系统最⼤追踪TCP连接数量:
# sysctl -a | grep ipv4.ip_conntrack_max
net.ipv4.ip_conntrack_max = 20000
这表明系统将对最⼤跟踪的TCP连接数限制默认为20000。
查看Linux系统端⼝范围:
# sysctl -a | grep ipv4.ip_local_port_range
net.ipv4.ip_local_port_range = 1024 30000
注意:
每个TCP客户端连接都要占⽤⼀个唯⼀的本地端⼝号(此端⼝号在系统的本地端⼝号范围限制中),如果现有的TCP客户端连接已将所有的本地端⼝号占满。将不能创建新的TCP 连接。
(1) vi /f
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.ip_conntrack_max = 20000
如果按上述端⼝范围进⾏设置,则理论上单独⼀个进程最多可以同时建⽴60000多个TCP客户端连接。
如果按上述参数进⾏设置,则理论上单独⼀个进程最多可以同时建⽴20000多个TCP客户端连接。
备注:
对mysql⽤户可同时打开⽂件数设置为10240个;
将Linux系统可同时打开⽂件数设置为1000000个(⼀定要⼤于对⽤户的同时打开⽂件数限制);
将Linux系统对最⼤追踪的TCP连接数限制为20000个(但是,建议设置为10240;因为对mysql⽤户的同时打开⽂件数已经限制在10240个;且较⼩的值可以节省内存);
将linux系统端⼝范围配置为1024~30000(可以⽀持60000个以上连接,不建议修改;默认已经⽀持20000个以上连接);
综合上述四点,TCP连接数限制在10140个。
这10240个⽂件中还得除去每个进程必然打开的标准输⼊,标准输出,标准错误,服务器监听 socket,进程间通讯的unix域socket等⽂件。
因此,当需要对TCP连接数进⾏调整时只需要调整ulimit参数。
Linux下查看tcp连接数及状态命令:
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
web服务器和cache服务器,⾼并发下,socket最⼤连接数限制调整:
1,修改⽤户进程可打开最⼤⽂件数限制。
即时⽣效:ulimit -n xxx
永久⽣效:
echo "ulimit -HSn 65536" >> /etc/rc.local
echo "ulimit -HSn 65536" >> /root/.bash_profile
ulimit -HSn 65536
2,修改⽹络内核对最⼤tcp连接数限制。
/f
⼀、
在Linux平台上,⽆论编写客户端程序还是服务端程序,在进⾏⾼并发TCP连接处理时,最⾼的并发数量都要受到系统对⽤户单⼀进程同时可打开⽂件数量的限制(这是因为系统为每个TCP连接都要创建⼀个socket句柄,每个socket句柄同时也是⼀个⽂件句柄)。例如:⼀个redis程序,只启动⼀个进程,则只
能打开1024个⽂件(默认1024)(1024个tcp连接=1024个socket连接句柄=1024个⽂件句柄),
可使⽤ulimit命令查看系统允许当前⽤户进程打开的⽂件数限制:
$ ulimit -n
  1024
这表⽰当前⽤户的每个进程最多允许同时打开1024个⽂件,这1024个⽂件中还得除去每个进程必然打开的标准输⼊,标准输出,标准错误,服务器监听 socket,进程间通讯的unix域socket等⽂件,那么剩下的可⽤于客户端socket连接的⽂件数就只有⼤概1024-10=1014个左右。也就是说缺省情况下,基于Linux的通讯程序最多允许同时1014个TCP并
对于想⽀持更⾼数量的TCP并发连接的通讯处理程序,就必须修改Linux对当前⽤户的进程同时打开的⽂件数量:
软限制(soft limit):是指Linux在当前系统能够承受的范围内进⼀步限制⽤户同时打开的⽂件数;
硬限制(hardlimit):是根据系统硬件资源状况(主要是系统内存)计算出来的系统最多可同时打开的⽂件数量。
通常软限制⼩于或等于硬限制
修改单个进程打开最⼤⽂件数限制的最简单的办法就是使⽤ulimit命令:
  [speng@as4 ~]$ ulimit -n
  上述命令中,在中指定要设置的单⼀进程允许打开的最⼤⽂件数。如果系统回显类似于"Operation notpermitted"之类的话,说明上述限制修改失败,实际上是因为在中指定的数值超过了Linux系统对该⽤户打开⽂件数的软限制或硬限制。因此,就需要修改Linux系统对⽤户的关于打开⽂件数的软限制和硬限制。
  第⼀步,修改/etc/f⽂件,在⽂件中添加如下⾏:
  speng soft nofile 10240
  speng hard nofile 10240
  其中speng指定了要修改哪个⽤户的打开⽂件数限制,可⽤'*'号表⽰修改所有⽤户的限制;
  soft或hard指定要修改软限制还是硬限制;10240则指定了想要修改的新的限制值,即最⼤打开⽂件数(请注意软限制值要⼩于或等于硬限制)。修改完后保存⽂件。
  第⼆步,修改/etc/pam.d/login⽂件,在⽂件中添加如下⾏:
  session required /lib/security/pam_limits.so 这是告诉Linux在⽤户完成系统登录后,应该调⽤pam_limits.so模块来设置系统对该⽤户可使⽤的各种资源数量的最⼤限制(包括⽤户可打开的最⼤⽂件数限制),⽽pam_limits.so模块就会从/etc/f⽂件中读取配置来设置这些限制值。修改完后保存此⽂件。
  第三步,查看Linux系统级的最⼤打开⽂件数限制,使⽤如下命令:
  [speng@as4 ~]$ cat /proc/sys/fs/file-max
  12158
  这表明这台Linux系统最多允许同时打开(即包含所有⽤户打开⽂件数总和)12158个⽂件,是Linux系统级硬限制,所有⽤户级的打开⽂件数限制都不应超过这个数值。通常这个系统级硬限制是Linux系统在启动时根据系统硬件资源状况计算出来的最佳的最⼤同时打开⽂件数限制,如果没有特殊需要,不应该修改此限制,除⾮想为⽤户级打开⽂件数限制设置超过此限制的值。linux所有命令都无法使用
  修改此硬限制的⽅法是修改/etc/rc.local脚本,在脚本中添加如下⾏:
  echo 22158 > /proc/sys/fs/file-max
  这是让Linux在启动完成后强⾏将系统级打开⽂件数硬限制设置为22158.修改完后保存此⽂件。
  完成上述步骤后重启系统,⼀般情况下就可以将Linux系统对指定⽤户的单⼀进程允许同时打开的最⼤⽂件数限制设为指定的数值。如果重启后⽤ ulimit-n命令查看⽤户可打开⽂件数限制仍然低于上述步骤中设置的最⼤值,这可能是因为在⽤户登录脚本/etc/profile中使⽤ulimit -n命令已经将⽤户可同时打开的⽂件数做了限制。由于通过ulimit-n修改系统对⽤户可同时打开⽂件的最⼤数限制时,新修改的值只能⼩于或等于上次 ulimit-n设置的值,因此想⽤此命令增⼤这个限制值是不可能的。
  所以,如果有上述问题存在,就只能去打开/etc/profile脚本⽂件,在⽂件中查是否使⽤了ulimit-n限制了⽤户可同时打开的最⼤⽂件数量,如果到,则删除这⾏命令,或者将其设置的值改为合适的值,然后保存⽂件,⽤户退出并重新登录系统即可。通过上述步骤,就为⽀持⾼并发TCP连接处理的通讯处理程序解除关于打开⽂件数量⽅⾯的系统限制。
⼆、修改⽹络内核对TCP连接的有关限制
  在Linux上编写⽀持⾼并发TCP连接的客户端通讯处理程序时,有时会发现尽管已经解除了系统对⽤户同时打开⽂件数的限制,但仍会出现并发TCP连接数增加到⼀定数量时,再也⽆法成功建⽴新的TCP连接的现象。出现这种现在的原因有多种。
  第⼀种原因可能是因为Linux⽹络内核对本地端⼝号范围有限制。此时,进⼀步分析为什么⽆法建⽴TCP连接,会发现问题出在connect()调⽤返回失败,查看系统错误提⽰消息是"Can't assign requestedaddress".同时,如果在此时⽤tcpdump⼯具监视⽹络,会发现根本没有TCP连接时客户端发SYN包的⽹络流量。这些情况说明问题在于本地Linux系统内核中有限制。
  其实,问题的根本原因在于Linux内核的TCP/IP协议实现模块对系统中所有的客户端TCP连接对应的本地端⼝号的范围进⾏了限制(例如,内核限制本地端⼝号的范围为1024~32768之间)。当系统中某⼀时刻同时存在太多的TCP客户端连接时,由于每个TCP客户端连接都要占⽤⼀个唯⼀的本地端⼝号(此端⼝号在系统的本地端⼝号范围限制中),如果现有的TCP客户端连接已将所有的本地端⼝号占满,则此时就⽆法为新的TCP客户端连接分配⼀个本地端⼝号了,因此系统会在这种情况下在connect()调⽤中返回失败,并将错误提⽰消息设为"Can't assignrequested address".
  有关这些控制逻辑可以查看Linux内核源代码,以linux2.6内核为例,可以查看tcp_ipv4.c⽂件中如下函数:
  static int tcp_v4_hash_connect(struct sock *sk)
  请注意上述函数中对变量sysctl_local_port_range的访问控制。变量sysctl_local_port_range的初始化则是在tcp.c⽂件中的如下函数中设置:
  void __init tcp_init(void)
  内核编译时默认设置的本地端⼝号范围可能太⼩,因此需要修改此本地端⼝范围限制。
  第⼀步,修改/f⽂件,在⽂件中添加如下⾏:
  net.ipv4.ip_local_port_range = 1024 65000
  这表明将系统对本地端⼝范围限制设置为1024~65000之间。请注意,本地端⼝范围的最⼩值必须⼤于或等于1024;⽽端⼝范围的最⼤值则应⼩于或等于65535.修改完后保存此⽂件。
  第⼆步,执⾏sysctl命令:
  [speng@as4 ~]$ sysctl -p
  如果系统没有错误提⽰,就表明新的本地端⼝范围设置成功。如果按上述端⼝范围进⾏设置,则理论上单独⼀个进程最多可以同时建⽴60000多个TCP客户端连接。
  第⼆种⽆法建⽴TCP连接的原因可能是因为Linux⽹络内核的防⽕墙对最⼤跟踪的TCP连接数有限制。此时程序会表现为在 connect()调⽤中阻塞,如同死机,如果⽤tcpdump⼯具监视⽹络,也会发现根
本没有TCP连接时客户端发SYN包的⽹络流量。由于防⽕墙在内核中会对每个TCP连接的状态进⾏跟踪,跟踪信息将会放在位于内核内存中的conntrackdatabase中,这个数据库的⼤⼩有限,当系统中存在过多的TCP连接时,数据库容量不⾜,IP_TABLE⽆法为新的TCP连接建⽴跟踪信息,于是表现为在
connect()调⽤中阻塞。此时就必须修改内核对最⼤跟踪的TCP连接数的限制,⽅法同修改内核对本地端⼝号范围的限制是类似的:
  第⼀步,修改/f⽂件,在⽂件中添加如下⾏:
  net.ipv4.ip_conntrack_max = 10240
  这表明将系统对最⼤跟踪的TCP连接数限制设置为10240.请注意,此限制值要尽量⼩,以节省对内核内存的占⽤。
  第⼆步,执⾏sysctl命令:
  [speng@as4 ~]$ sysctl -p
  如果系统没有错误提⽰,就表明系统对新的最⼤跟踪的TCP连接数限制修改成功。如果按上述参数进⾏设置,则理论上单独⼀个进程最多可以同时建⽴10000多个TCP客户端连接。
使⽤⽀持⾼并发⽹络I/O的编程技术在Linux上编写⾼并发TCP连接应⽤程序时,必须使⽤合适的⽹络I/O技术和I/O事件分派机制。可⽤的I/O技术有同步I/O,⾮阻塞式同步I/O(也称反应式I/O),以及异步I/O.在⾼TCP并发的情形下,如果使⽤同步I/O,
  但是,过多的线程⼜会因系统对线程的调度造成巨⼤开销。因此,在⾼TCP并发的情形下使⽤同步 I/O是不可取的,这时可以考虑使⽤⾮阻塞式同步I/O或异步I/O.⾮阻塞式同
步I/O的技术包括使⽤select(),poll(),epoll等机制。异步I/O的技术就是使⽤AIO.
  从I/O事件分派机制来看,使⽤select()是不合适的,因为它所⽀持的并发连接数有限(通常在1024个以内)。如果考虑性能,poll()也是不合适的,尽管它可以⽀持的
较⾼的TCP并发数,但是由于其采⽤"轮询"机制,当并发数较⾼时,其运⾏效率相当低,并可能存在I/O事件分派不均,导致部分TCP连接上的I/O出现"饥饿"现象。⽽如果使⽤
epoll或AIO,则没有上述问题(早期Linux内核的AIO技术实现是通过在内核中为每个 I/O请求创建⼀个线程来实现的,这种实现机制在⾼并发TCP连接的情形下使⽤其实也有严重
的性能问题。但在最新的Linux内核中,AIO的实现已经得到改进)。
  综上所述,在开发⽀持⾼并发TCP连接的Linux应⽤程序时,应尽量使⽤epoll或AIO技术来实现并发的TCP连接上的I/O控制,这将为提升程序对⾼并发TCP连接的⽀持提供
有效的I/O保证。
内核参数f的优化
  /f 是⽤来控制linux⽹络的配置⽂件,对于依赖⽹络的程序(如web服务器和cache服务器)⾮常重要,RHEL默认提供的最好调整。
  推荐配置(把原/f内容清掉,把下⾯内容复制进去):
cp /f /f.bak
echo ""> /f
vim /f
net.ipv4.ip_local_port_range = 1024 65535
p_rmem = 4096 87380 16777216
p_wmem = 4096 65536 16777216
p_fin_timeout = 10
p_tw_recycle = 1
p_timestamps = 0
p_window_scaling = 0
p_sack = 0
p_no_metrics_save = 1
p_syncookies = 0
p_max_orphans = 262144
p_max_syn_backlog = 262144
p_synack_retries = 2
p_syn_retries = 2
  这个配置参考于cache服务器varnish的推荐配置和SunOne服务器系统优化的推荐配置。
  不过varnish推荐的配置是有问题的,实际运⾏表明"p_fin_timeout = 3"的配置会导致页⾯经常打不开;并且当⽹友使⽤的是IE6浏览器时,访问⽹站⼀段时间后,
所有⽹页都会打不开,重启浏览器后正常。可能是国外的⽹速快吧,我们国情决定需要调整"p_fin_timeout = 10",在10s的情况下,⼀切正常(实际运⾏结论)。
  修改完毕后,执⾏:
sysctl -p /f
sysctl -w ute.flush=1
  命令⽣效。为了保险起见,也可以reboot系统。
  调整打开最⼤⽂件句柄数(单个进程最⼤tcp连接数=单个进程最⼤socket连接数):
  linux系统优化完⽹络必须调⾼系统允许打开的⽂件数才能⽀持⼤的并发,默认1024是远远不够的。
  执⾏命令:
  Shell代码
echo "ulimit -HSn 65536" >> /etc/rc.local
echo "ulimit -HSn 65536" >> /root/.bash_profile
ulimit -HSn 65535
1、修改⽤户进程可打开⽂件数限制
在Linux平台上,⽆论编写客户端程序还是服务端程序,在进⾏⾼并发TCP连接处理时,最⾼的并发数量都要受到系统对⽤户单⼀进程同时可打开⽂件数量的限制(这是因为系统
为每个TCP连接都要创建⼀个socket句柄,每个socket句柄同时也是⼀个⽂件句柄)。可使⽤ulimit命令查看系统允许当前⽤户进程打开的⽂件数限制:
[speng@as4 ~]$ ulimit -n
1024
这表⽰当前⽤户的每个进程最多允许同时打开1024个⽂件,这1024个⽂件中还得除去每个进程必然打开的标准输⼊,标准输出,标准错误,服务器监听 socket,进程间通讯的
unix域socket等⽂件,那么剩下的可⽤于客户端socket连接的⽂件数就只有⼤概1024-10=1014个左右。也就是说缺省情况下,基于Linux的通讯程序最多允许同时1014个TCP并
发连接。
对于想⽀持更⾼数量的TCP并发连接的通讯处理程序,就必须修改Linux对当前⽤户的进程同时打开的⽂件数量的软限制(soft limit)和硬限制(hardlimit)。其中软限制是指Linux在
当前系统能够承受的范围内进⼀步限制⽤户同时打开的⽂件数;硬限制则是根据系统硬件资源状况(主要是系统内存)计算出来的系统最多可同时打开的⽂件数量。通常软限制⼩
于或等于硬限制。
修改上述限制的最简单的办法就是使⽤ulimit命令:
[speng@as4 ~]$ ulimit -n
上述命令中,在中指定要设置的单⼀进程允许打开的最⼤⽂件数。如果系统回显类似于“Operation notpermitted”之类的话,说明上述限制修改失败,实际上是因为在中指定的数
值超过了Linux系统对该⽤户打开⽂件数的软限制或硬限制。因此,就需要修改Linux系统对⽤户的关于打开⽂件数的软限制和硬限制。
第⼀步,修改/etc/f⽂件,在⽂件中添加如下⾏:
speng soft nofile 10240
speng hard nofile 10240
其中speng指定了要修改哪个⽤户的打开⽂件数限制,可⽤’*'号表⽰修改所有⽤户的限制;soft或hard指定要修改软限制还是硬限制;10240则指定了想要修改的新的限制值,即
最⼤打开⽂件数(请注意软限制值要⼩于或等于硬限制)。修改完后保存⽂件。
session required /lib/security/pam_limits.so
这是告诉Linux在⽤户完成系统登录后,应该调⽤pam_limits.so模块来设置系统对该⽤户可使⽤的各种资源数量的最⼤限制(包括⽤户可打开的最⼤⽂件数限制),⽽pam_limits.so 模块就会从/etc/f⽂件中读取配置来设置这些限制值。修改完后保存此⽂件。
第三步,查看Linux系统级的最⼤打开⽂件数限制,使⽤如下命令:
[speng@as4 ~]$ cat /proc/sys/fs/file-max
12158
这表明这台Linux系统最多允许同时打开(即包含所有⽤户打开⽂件数总和)12158个⽂件,是Linux系统级硬限制,所有⽤户级的打开⽂件数限制都不应超过这个数值。通常这个系统级硬限制是Linux系统在启动时根据系统硬件资源状况计算出来的最佳的最⼤同时打开⽂件数限制,如果没有特殊需要,不应该修改此限制,除⾮想为⽤户级打开⽂件数限制设置超过此限制的值。修改此硬限制的⽅法是修改/etc/rc.local脚本,在脚本中添加如下⾏:
echo 22158 > /proc/sys/fs/file-max
这是让Linux在启动完成后强⾏将系统级打开⽂件数硬限制设置为22158。修改完后保存此⽂件。
完成上述步骤后重启系统,⼀般情况下就可以将Linux系统对指定⽤户的单⼀进程允许同时打开的最⼤⽂件数限制设为指定的数值。如果重启后⽤ ulimit-n命令查看⽤户可打开⽂件数限制仍然低于上述步骤中设置的最⼤值,这可能是因为在⽤户登录脚本/etc/profile中使⽤ulimit -n命令已经将⽤户可同时打开的⽂件数做了限制。由于通过ulimit-n修改系统对⽤户可同时打开⽂件的最⼤数限制时,新修改的值只能⼩于或等于上次 ulimit-n设置的值,因此想⽤此命令增⼤这个限制值是不可能的。所以,如果有上述问题存在,就只能去打开/etc/profile脚本⽂件,在⽂件中查是否使⽤了ulimit-n限制了⽤户可同时打开的最⼤⽂件数量,如果到,则删除这⾏命令,或者将其设置的值改为合适的值,然后保存⽂件,⽤户退出并重新登录系统即可。
通过上述步骤,就为⽀持⾼并发TCP连接处理的通讯处理程序解除关于打开⽂件数量⽅⾯的系统限制。
2、修改⽹络内核对TCP连接的有关限制(参考对⽐下篇⽂章“优化内核参数”)
在Linux上编写⽀持⾼并发TCP连接的客户端通讯处理程序时,有时会发现尽管已经解除了系统对⽤户同时打开⽂件数的限制,但仍会出现并发TCP连接数增加到⼀定数量时,再也⽆法成功建⽴新的TCP连接的现象。出现这种现在的原因有多种。
第⼀种原因可能是因为Linux⽹络内核对本地端⼝号范围有限制。此时,进⼀步分析为什么⽆法建⽴TCP连接,会发现问题出在connect()调⽤返回失败,查看系统错误提⽰消息是“Can’t assign requestedaddress”。同时,如果在此时⽤tcpdump⼯具监视⽹络,会发现根本没有TCP连接时客户端发SYN包的⽹络流量。这些情况说明问题在于本地Linux系统内核中有限制。其实,问题的根本原因在于Linux内核的TCP/IP协议实现模块对系统中所有的客户端TCP连接对应的本地端⼝号的范围进⾏了限制(例如,内核限制本地端⼝号的范围为1024~32768之间)。当系统中某⼀时刻同时存在太多的TCP客户端连接时,由于每个TCP客户端连接都要占⽤⼀个唯⼀的本地端⼝号(此端⼝号在系统的本地端⼝号范围限制中),如果现有的TCP客户端连接已将所有的本地端⼝号占满,则此时就⽆法为新的TCP客户端连接分配⼀个本地端⼝号了,因此系统会在这种情况下在connect()调⽤中返回失败,并将错误提⽰消息设为“Can’t assignrequested address”。有关这些控制逻辑可以查看Linux内核源代码,以linux2.6内核为例,可以查看tcp_ipv4.c⽂件中如下函数:static int tcp_v4_hash_connect(struct sock *sk)
请注意上述函数中对变量sysctl_local_port_range的访问控制。变量sysctl_local_port_range的初始化则是在tcp.c⽂件中的如下函数中设置:
void __init tcp_init(void)
内核编译时默认设置的本地端⼝号范围可能太⼩,因此需要修改此本地端⼝范围限制。
第⼀步,修改/f⽂件,在⽂件中添加如下⾏:
net.ipv4.ip_local_port_range = 1024 65000
这表明将系统对本地端⼝范围限制设置为1024~65000之间。请注意,本地端⼝范围的最⼩值必须⼤于或等于1024;⽽端⼝范围的最⼤值则应⼩于或等于65535。修改完后保存此⽂件。
第⼆步,执⾏sysctl命令:
[speng@as4 ~]$ sysctl -p
如果系统没有错误提⽰,就表明新的本地端⼝范围设置成功。如果按上述端⼝范围进⾏设置,则理论上单独⼀个进程最多可以同时建⽴60000多个TCP客户端连接。
第⼆种⽆法建⽴TCP连接的原因可能是因为Linux⽹络内核的IP_TABLE防⽕墙对最⼤跟踪的TCP连接数有限制。此时程序会表现为在 connect()调⽤中阻塞,如同死机,如果⽤tcpdump⼯具监视⽹络,也会发现根本没有TCP连接时客户端发SYN包的⽹络流量。由于 IP_TABLE防⽕墙在内核中会对每个TCP连接的状态进⾏跟踪,跟踪信息将会放在位于内核内存中的conntrackdatabase中,这个数据库的⼤⼩有限,当系统中存在过多的TCP连接时,数据库容量不⾜,IP_TABLE⽆法为新的TCP连接建⽴跟踪信息,于是表现为在connect()调⽤中阻塞。此时就必须修改内核对最⼤跟踪的TCP连接数的限制,⽅法同修改内
核对本地端⼝号范围的限制是类似的:
第⼀步,修改/f⽂件,在⽂件中添加如下⾏:
net.ipv4.ip_conntrack_max = 10240
这表明将系统对最⼤跟踪的TCP连接数限制设置为10240。请注意,此限制值要尽量⼩,以节省对内核内存的占⽤。
第⼆步,执⾏sysctl命令:
[speng@as4 ~]$ sysctl -p
如果系统没有错误提⽰,就表明系统对新的最⼤跟踪的TCP连接数限制修改成功。如果按上述参数进⾏设置,则理论上单独⼀个进程最多可以同时建⽴10000多个TCP客户端连接。
3、使⽤⽀持⾼并发⽹络I/O的编程技术
在Linux上编写⾼并发TCP连接应⽤程序时,必须使⽤合适的⽹络I/O技术和I/O事件分派机制。
可⽤的I/O技术有同步I/O,⾮阻塞式同步I/O(也称反应式I/O),以及异步I/O。在⾼TCP并发的情形下,如
果使⽤同步I/O,这会严重阻塞程序的运转,除⾮为每个TCP连接的I/O创建⼀个线程。但是,过多的线程⼜会因系统对线程的调度造成巨⼤开销。因此,在⾼TCP并发的情形下使⽤同步 I/O是不可取的,这时可以考虑使⽤⾮阻塞式同步I/O或异步I/O。⾮阻塞式同步I/O的技术包括使⽤select(),poll(),epoll等机制。异步I/O的技术就是使⽤AIO。
从I/O事件分派机制来看,使⽤select()是不合适的,因为它所⽀持的并发连接数有限(通常在1024个以内)。如果考虑性能,poll()也是不合适的,尽管它可以⽀持的较⾼的TCP并发数,但是由于其采⽤“轮询”机制,当并发数较⾼时,其运⾏效率相当低,并可能存在I/O事件分派不均,导致部分TCP连接上的I/O出现“饥饿”现象。⽽如果使⽤epoll或AIO,则没有上述问题(早期Linux内核的AIO技术实现是通过在内核中为每个 I/O请求创建⼀个线程来实现的,这种实现机制在⾼并发TCP连接的情形下使⽤其实也有严重的性能问题。但在最新的Linux内核中,AIO的实现已经得到改进)。
综上所述,在开发⽀持⾼并发TCP连接的Linux应⽤程序时,应尽量使⽤epoll或AIO技术来实现并发的TCP连接上的I/O控制,这将为提升程序对⾼并发TCP连接的⽀持提供有效的I/O保证。
内核参数f的优化
/f 是⽤来控制linux⽹络的配置⽂件,对于依赖⽹络的程序(如web服务器和cache服务器)⾮常重要,RHEL默认提供的最好调整。
推荐配置(把原/f内容清掉,把下⾯内容复制进去):
net.ipv4.ip_local_port_range = 1024 65536
p_rmem=4096 87380 16777216
p_wmem=4096 65536 16777216
p_fin_timeout = 10
p_tw_recycle = 1
p_timestamps = 0
p_window_scaling = 0
p_sack = 0
p_no_metrics_save=1
p_syncookies = 0
p_max_orphans = 262144
p_max_syn_backlog = 262144
p_synack_retries = 2
p_syn_retries = 2
这个配置参考于cache服务器varnish的推荐配置和SunOne 服务器系统优化的推荐配置。
不过varnish推荐的配置是有问题的,实际运⾏表明“p_fin_timeout = 3”的配置会导致页⾯经常打不开;并且当⽹友使⽤的是IE6浏览器时,访问⽹站⼀段时间后,所有⽹页都会打不开,重启浏览器后正常。可能是国外的⽹速快吧,我们国情决定需要调整“p_fin_timeout = 10”,在10s的情况
下,⼀切正常(实际运⾏结论)。
修改完毕后,执⾏:
/sbin/sysctl -p /f
/sbin/sysctl -w ute.flush=1
命令⽣效。为了保险起见,也可以reboot系统。
调整⽂件数:
linux系统优化完⽹络必须调⾼系统允许打开的⽂件数才能⽀持⼤的并发,默认1024是远远不够的。
执⾏命令:
Shell代码
echo ulimit -HSn 65536 >>/root/.bash_profile ulimit -HSn 65536

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。