原文:
https://blog.csdn.net/qq_33573235/article/details/79288658

1
ulimit -n
1024

这表示当前用户的每个进程最多允许同时打开1024个文件,这1024个文件中还得除去每个进程必然打开的标准输入,标准输出,标准错误,服务器监听 socket,进程间通讯的unix域socket等文件,那么剩下的可用于客户端socket连接的文件数就只有大概1024-10=1014个左右。

2
第一步,修改/etc/sysctl.conf文件,在文件中添加如下行:
net.ipv4.ip_local_port_range = 1024 65000

这表明将系统对本地端口范围限制设置为1024~65000之间。请注意,本地端口范围的最小值必须大于或等于1024;而端口范围的最大值则应小于或等于65535。修改完后保存此文件。

第二步,执行sysctl命令:

[speng@as4 ~]$ sysctl -p
如果系统没有错误提示,就表明新的本地端口范围设置成功。如果按上述端口范围进行设置,则理论上单独一个进程最多可以同时建立60000多个TCP客户端连接。

总结:综上所述,在开发支持高并发TCP连接的Linux应用程序时,应尽量使用epoll或AIO技术来实现并发的TCP连接上的I/O控制,这将为提升程序对高并发TCP连接的支持提供有效的I/O保证。

这个配置参考于cache服务器varnish的推荐配置和SunOne 服务器系统优化的推荐配置。
varnish调优推荐配置的地址为:http://varnish.projects.linpro.no/wiki/Performance
不过varnish推荐的配置是有问题的,实际运行表明“net.ipv4.tcp_fin_timeout = 3”的配置会导致页面经常打不开;并且当网友使用的是IE6浏览器时,访问网站一段时间后,所有网页都会打不开,重启浏览器后正常。可能是国外的网速快吧,我们国情决定需要调整“net.ipv4.tcp_fin_timeout = 10”,在10s的情况下,一切正常(实际运行结论)。

推荐配置(把原/etc/sysctl.conf内容清掉,把下面内容复制进去):

net.ipv4.ip_local_port_range = 1024 65536
net.core.rmem_max=16777216
net.core.wmem_max=16777216
net.ipv4.tcp_rmem=4096 87380 16777216
net.ipv4.tcp_wmem=4096 65536 16777216
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_window_scaling = 0
net.ipv4.tcp_sack = 0
net.core.netdev_max_backlog = 30000
net.ipv4.tcp_no_metrics_save=1
net.core.somaxconn = 262144
net.ipv4.tcp_syncookies = 0
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2

修改完毕后,执行:

/sbin/sysctl -p /etc/sysctl.conf
/sbin/sysctl -w net.ipv4.route.flush=1

命令生效。为了保险起见,也可以reboot系统。

详细解释

vi /etc/sysctl.conf
net.core.netdev_max_backlog = 30000 每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目
net.core.somaxconn = 262144 用来限制监听(LISTEN)队列最大数据包的数量,超过这个数量就会导致链接超时或者触发重传机制
net.core.rmem_default = 8388608 接收套接字缓冲区大小的默认值(以字节为单位)
net.core.wmem_default = 8388608 发送套接字缓冲区大小的默认值(以字节为单位)
net.core.rmem_max=16777216 接收套接字缓冲区大小的最大值(以字节为单位)
net.core.wmem_max=16777216 发送套接字缓冲区大小的最大值(以字节为单位)
net.ipv4.ip_local_port_range = 1024 65536 用于向外连接的端口范围
net.ipv4.tcp_mem = 786432 1048576 1572864 确定 TCP 栈应该如何反映内存使用,此处分别为3G、4G、6G;每个值的单位都是内存页(通常是 4KB)。第一个值是内存使用的下限。第二个值是内存压力模式开始对缓冲区使用应用压力的上限。第三个值是内存上限。在这个层次上可以将报文丢弃,从而减少对内存的使用。

net.ipv4.tcp_rmem=4096 87380 16777216 TCP接收缓冲区,3个字段分别是min,default,max。Min:为TCP socket预留用于接收缓冲的内存数量,即使在内存出现紧张情况下TCP socket都至少会有这么多数量的内存用于接收缓冲。
  Default: 为TCP socket预留用于接收缓冲的内存数量,默认情况下该值影响其它协议使用的 net.core.wmem中default的值。该值决定了 在tcp_adv_win_scale、tcp_app_win和tcp_app_win的 默认值情况下,TCP 窗口大小为65535。
  Max:为TCP socket预留用于接收缓冲的内存最大值。该值不会影响 net.core.wmem中max的值
net.ipv4.tcp_wmem=4096 65536 16777216 TCP发送缓冲区,3个字段分别是min,default,max。Min:为TCP socket预留用于发送缓冲的内存最小值。每个TCP socket都可以使用它。
  Default:为TCP socket预留用于发送缓冲的内存数量,默认情况下该值会影响其它协议使用的net.core.wmem中default的 值,一般要低于net.core.wmem中default的值。
  Max:为TCP socket预留用于发送缓冲的内存最大值。该值不会影响net.core.wmem_max

net.ipv4.tcp_fin_timeout = 10 如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。对端可以出错并永远不关闭连接,甚至意外当机。缺省值是60 秒
net.ipv4.tcp_tw_recycle = 1 开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭
net.ipv4.tcp_tw_reuse = 1 表示是否允许重新应用处于TIME-WAIT状态的socket用于新的TCP连接。

net.ipv4.tcp_max_tw_buckets = 6000 系统在同时所处理的最大timewait sockets 数目。如果超过此数的话,time-wait socket 会被立即砍除并且显示警告信息。之所以要设定这个限制,纯粹为了抵御那些简单的 DoS 攻击,千万不要人为的降低这个限制,不过,如果网络条件需要比默认值更多,则可以提高它(或许还要增加内存)

net.ipv4.tcp_timestamps = 0 时间戳可以避免序列号的卷绕。一个1Gbps 的链路肯定会遇到以前用过的序列号。时间戳能够让内核接受这种“异常”的数据包。这里需要将其关掉。

net.ipv4.tcp_window_scaling = 1 支持更大的TCP窗口. 如果TCP窗口最大超过65535(64KB), 必须设置该数值为1。

net.ipv4.tcp_sack = 1 表示是否启用有选择的应答(Selective Acknowledgment),这可以通过有选择地应答乱序接收到的报文来提高性能(这样可以让发送者只发送丢失的报文段);(对于广域网通信来说)这个选项应该启用,但是这会增加对 CPU 的占用
net.ipv4.tcp_no_metrics_save=1 默认情况下一个tcp连接关闭后,把这个连接曾经有的参数比如慢启动门限snd_sthresh,拥塞窗口snd_cwnd 还有srtt等信息保存到dst_entry中, 只要dst_entry 没有失效,下次新建立相同连接的时候就可以使用保存的参数来初始化这个连接.通常情况下是关闭的。

net.ipv4.tcp_keepalive_time = 1200 当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟

net.ipv4.tcp_syncookies = 1 当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭

net.ipv4.tcp_max_orphans = 262144 系统中最多有多少个TCP 套接字不被关联到任何一个用户文件句柄上。如果超过这个数字,孤儿连接将即刻被复位并打印出警告信息。这个限制仅仅是为了防止简单的DoS 攻击,不能过分依靠它或者人为地减小这个值,更应该增加这个值(如果增加了内存之后)。

net.ipv4.tcp_max_syn_backlog = 262144 表示那些尚未收到客户端确认信息的连接(SYN消息)队列的长度,默认为1024,加大队列长度为262144,可以容纳更多等待连接的网络连接数。

net.ipv4.tcp_synack_retries = 2 为了打开对端的连接,内核需要发送一个SYN 并附带一个回应前面一个SYN 的ACK。也就是所谓三次握手中的第二次握手。这个设置决定了内核放弃连接之前发送SYN+ACK 包的数量。

net.ipv4.tcp_syn_retries = 2 在内核放弃建立连接之前发送SYN 包的数量

web服务器收到了大量的连接,在启用了iptables的情况下,iptables会把所有的连接都做链接跟踪处理,这样iptables就会有一个链接跟踪表
net.ipv4.netfilter.ip_conntrack_tcp_timeout_established=1800 链接跟踪表保存时间,单位:秒
net.ipv4.netfilter.ip_conntrack_max=131070 链接跟踪表最大数目

kernel.sysrq = 0 允许按住Alt + PrtSc键打印内核信息,除非是调试,一般要关闭此功能
kernel.core_uses_pid = 1 控制core文件的文件名中是否添加pid作为扩展。文件内容为1,表示添加pid作为扩展名,生成的core文件格式为core.xxxx;为0则表示生成的core文件同一命名为core
kernel.msgmnb = 65536 每个消息队列的最大字节限制。
kernel.msgmax = 65536 从一个进程发送到另一个进程的消息的最大长度(bytes)。进程间的消息传递是在内核的内存中进行的,不会交换到磁盘上,所以如果增加该值,则将增加操作系统所使用的内存数量。
kernel.shmmax = 68719476736 表示内核所允许的最大共享内存段的大小(bytes)
kernel.shmall = 4294967296 系统上可以使用的共享内存的总量(bytes)
kernel.randomize_va_space = 1 将该值设置为 0 可禁用地址空间布局随机化。DB2 数据服务器依赖特定共享内存对象的固定地址,地址空间布局随机化会导致有些活动发生错误
net.ipv4.ip_forward = 0 0表示禁用 IPv4 包转送
net.ipv4.neigh.default.gc_stale_time=120 ARP参数,检查一次相邻层记录的有效性的周期。当相邻层记录失效时,将在给它发送数据前,再解析一次。缺省值是60秒。
net.ipv4.conf.all.rp_filter=0
net.ipv4.conf.all.arp_announce=2
net.ipv4.conf.lo.arp_announce=2

以下命令使内核参数生效:
/sbin/sysctl -p 生效
/sbin/sysctl -a | grep net.core.netdev_max_backlog 查看

完整的参数列表:
net.core.netdev_max_backlog = 30000
net.core.somaxconn = 262144
net.core.rmem_default = 8388608
net.core.wmem_default = 8388608
net.core.rmem_max=16777216
net.core.wmem_max=16777216
net.ipv4.ip_local_port_range = 1024 65536
net.ipv4.tcp_mem = 786432 1048576 1572864
net.ipv4.tcp_rmem=4096 87380 16777216
net.ipv4.tcp_wmem=4096 65536 16777216
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_max_tw_buckets = 6000
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_no_metrics_save=1
net.ipv4.tcp_keepalive_time = 1200
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2
net.ipv4.netfilter.ip_conntrack_tcp_timeout_established=1800
net.ipv4.netfilter.ip_conntrack_max=131070

kernel.sysrq = 0
kernel.core_uses_pid = 1
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 68719476736
kernel.shmall = 4294967296
kernel.randomize_va_space = 1
kernel.exec-shield = 1
net.ipv4.ip_forward = 0
net.ipv4.neigh.default.gc_stale_time=120
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.default.rp_filter=0
net.ipv4.conf.all.rp_filter=0
net.ipv4.conf.all.arp_announce=2
net.ipv4.conf.lo.arp_announce=2

如果出现error: “net.ipv4.netfilter.ip_conntrack_max” is an unknown key

执行下面的命令加载对应模块:

modprobe ip_conntrack
lsmod |grep conn – if you see entries it means modules have been loaded correctly
sysctl -w – to write the changes you made under /etc/sysctl.conf
sysctl -p – to view the changes and see if it was actually loaded.
还不行,把net.ipv4.netfilter.ip_conntrack_max替换为:

net.nf_conntrack_max = 131070试试看

除了调整内核参数,还需 调整文件数:

linux系统优化完网络必须调高系统允许打开的文件数才能支持大的并发,默认1024是远远不够的。
查看进程占用的文件句柄数; lsof -n |awk ‘{print $2}’|sort|uniq -c |sort -nr|more 其中第一行是打开的文件句柄数量,第二行是进程号

执行Shell命令:
echo ulimit -HSn 65536 >> /etc/rc.local
echo ulimit -HSn 65536 >>/root/.bash_profile
ulimit -HSn 65536

如果要sudo执行时,使用:sudo sh -c “ulimit -HSn 65536 && exec su $LOGNAME”

-H 设置硬资源限制.
-S 设置软资源限制.
-a 显示当前所有的资源限制.
-c size:设置core文件的最大值.单位:blocks
-d size:设置数据段的最大值.单位:kbytes
-f size:设置创建文件的最大值.单位:blocks
-l size:设置在内存中锁定进程的最大值.单位:kbytes
-m size:设置可以使用的常驻内存的最大值.单位:kbytes
-n size:设置内核可以同时打开的文件描述符的最大值.单位:n
-p size:设置管道缓冲区的最大值.单位:kbytes
-s size:设置堆栈的最大值.单位:kbytes
-t size:设置CPU使用时间的最大上限.单位:seconds
-v size:设置虚拟内存的最大值.单位:kbytes
-u <程序数目>  用户最多可开启的程序数目

延伸:BIO、NIO和AIO的区别、三种IO的原理与用法 为什么AIO 是高并发编程?

https://blog.csdn.net/u010541670/article/details/91890649

延伸阅读 参数配置示例详解:

https://blog.csdn.net/weixin_34053992/article/details/116613918

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐