Linux TCP链接数修改

1、            文件数限制修改
(1)    vi /etc/security/limits.conf
*  soft nofile 10240
   *  hard nofile 10240
 
(2) vi /etc/pam.d/login
session required /lib/security/pam_limits.so
 
2、            网络端口限制修改
(1) vi /etc/rc.d/rc.local
/sbin/modprobe ip_conntrack  # 加载 ip_contrack 模块
# /sbin/sysctl –p              # 使 /etc/sysctl.conf 的配置生效,根据实际状况来决定是否添加此命令
 
[root@AS4U8 ~]# sysctl -a | grep "net.ipv4.ip"
net.ipv4.ip_conntrack_max = 16384
这代表将系统对最大跟踪的TCP链接数限制默认为16384。请注意,此限制值要尽可能小,以节省对内核内存的占用
 
(2) vi /etc/sysctl.conf
net.ipv4.ip_local_port_range = 1024 65000
net.ipv4.ip_conntrack_max = 10240
此限制值要尽可能小,以节省对内核内存的占用。
 
 
详细解说 :
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 <file_num>
   上述命令中,在<file_num>中指定要设置的单一进程容许打开的最大文件数。若是系统回显相似于“Operation notpermitted”之类的话,说明上述限制修改失败,其实是由于在<file_num>中指定的数值超过了Linux系统对该用户打开文件数的软限制或硬限制。所以,就须要修改Linux系统对用户的关于打开文件数的软限制和硬限制。
 
   第一步,修改/etc/security/limits.conf文件,在文件中添加以下行:
   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/security/limits.conf文件中读取配置来设置这些限制值。修改完后保存此文件。
 
   第三步,查看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链接处理的通信处理程序解除关于打开文件数量方面的系统限制。
 
二、修改网络内核对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)
   内核编译时默认设置的本地端口号范围可能过小,所以须要修改此本地端口范围限制。
   第一步,修改/etc/sysctl.conf文件,在文件中添加以下行:
   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链接数的限制,方法同修改内核对本地端口号范围的限制是相似的:
   第一步,修改/etc/sysctl.conf文件,在文件中添加以下行:
   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建立一个线程。可是,过多的线程又会因系统对线程的调度形成巨大开销。所以,在高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保证。linux

相关文章
相关标签/搜索