大战C100K之-Linux内核调优篇--转载
原文地址:http://joyexpr.com/2013/11/22/c100k-4-kernel-tuning/
早期的系统,系统资源包括CPU、内存等都是非常有限的,系统为了保持公平,默认要限制进程对资源的使用情况。由于Linux的默认内核配置无法满足C100K的要求,因此需要对其进行适当的调优。
我们可以通过 ulimit
查看一下典型的机器默认的限制情况:
$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 204800
max locked memory (kbytes, -l) 32
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 204800
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
比如其中的 open files
,默认一个进程能打开的文件句柄数量为1024,对于一些需要大量文件句柄的程序,如web服务器、数据库程序等,1024往往是不够用的,在句柄使用完毕的时候,系统就会频繁出现emfile错误。
俗话说:一个巴掌拍不响,要完成 C100K
的目标,需要服务器端与客户端的紧密配合,下面将分别对这二者的调优进行介绍。
客户端
1:文件句柄数量受限
在Linux平台上,无论是编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,由于每个TCP连接都要创建一个socket句柄,而每个socket句柄同时也是一个文件句柄,所以其最高并发数量要受到系统对用户单一进程同时可打开文件数量的限制以及整个系统可同时打开的文件数量限制。
1.1:单一进程的文件句柄数量受限
我们可以ulimit命令查看当前用户进程可打开的文件句柄数限制:
[root@localhost ~]# ulimit -n
1024
这表示当前用户的每个进程最多允许同时打开1024个文件,除去每个进程必然打开的标准输入、标准输出、标准错误、服务器监听socket、进程间通讯的unix域socket等文件,剩下的可用于客户端socket连接的文件数就只有大概1024-10=1014个左右。也就是说,在默认情况下,基于Linux的通讯程序最多允许同时1014个TCP并发连接。
对于想支持更高数量的TCP并发连接的通讯处理程序,就必须修改Linux对当前用户的进程可同时打开的文件数量的软限制(soft limit)和硬限制(hardlimit)。其中:
- 软限制是指Linux在当前系统能够承受的范围内进一步限制用户能同时打开的文件数。
- 硬限制是指根据系统硬件资源状况(主要是系统内存)计算出来的系统最多可同时打开的文件数量。
通常软限制小于或等于硬限制,可通过ulimit命令查看软限制和硬限制:
[root@localhost ~]# ulimit -Sn
1024
[root@localhost ~]# ulimit -Hn
4096
修改单一进程能同时打开的文件句柄数有2种方法:
1、直接使用ulimit命令,如:
[root@localhost ~]# ulimit -n 1048576
执行成功之后,ulimit n、Sn、Hn的值均会变为1048576。但该方法设置的值只会在当前终端有效,且设置的值不能高于方法2中设置的值。
2、对 /etc/security/limits.conf
文件,添加或修改:
* soft nofile 1048576
* hard nofile 1048576
其中,
*
代表对所有用户有效,若仅想针对某个用户,可替换星号。- soft即软限制,它只是一个警告值。
- hard代表硬限制,是一个真正意义的阈值,超过就会报错。
- nofile表示打开文件的最大数量。
- 1048576 = 1024 * 1024,为什么要取这个值呢?因为
在linux kernel 2.6.25之前通过ulimit -n(setrlimit(RLIMIT_NOFILE))设置每个进程的最大打开文件句柄数不能超过NR_OPEN(1024*1024),也就是100多w(除非重新编译内核),而在25之后,内核导出了一个sys接口可以修改这个最大值(/proc/sys/fs /nr_open).具体的changelog在https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=9cfe015aa424b3c003baba3841a60dd9b5ad319b
注意文件保存之后,需要注销或重启系统方能生效。
1.2:整个系统的文件句柄数量受限
解决完单一进程的文件句柄数量受限问题后,还要解决整个系统的文件句柄数量受限问题。我们可通过以下命令查看Linux系统级的最大打开文件数限制:
[root@localhost ~]# cat /proc/sys/fs/file-max
98957
file-max表示系统所有进程最多允许同时打开的文件句柄数,是Linux系统级硬限制。通常,这个系统硬限制是Linux系统在启动时根据系统硬件资源状况计算出来的最佳的最大同时打开文件数限制,如果没有特殊需要,不应该修改此限制。
要修改它,需要对 /etc/sysctl.conf
文件,增加一行内容:
fs.file-max = 1048576
保存成功后,需执行下面命令使之生效:
[root@localhost ~]# sysctl -p
2:端口数量受限
解决完文件句柄数量受限的问题后,就要解决IP端口数量受限的问题了。一般来说,对外提供请求的服务端不用考虑端口数量问题,只要监听某一个端口即可。可客户端要模拟大量的用户对服务端发起TCP请求,而每一个请求都需要一个端口,为了使一个客户端尽可能地模拟更多的用户,也就要使客户端拥有更多可使用的端口。
由于端口为16进制,即最大端口数为2的16次方65536(0-65535)。在Linux系统里,1024以下端口只有超级管理员用户(如root)才可以使用,普通用户只能使用大于等于1024的端口值。
我们可以通过以下命令查看系统提供的默认的端口范围:
[root@localhost ~]# cat /proc/sys/net/ipv4/ip_local_port_range
32768 61000
即只有61000-32768=28232个端口可以使用,即单个IP对外只能同时发送28232个TCP请求。
修改方法有以下2种:
1、执行以下命令:
echo "1024 65535"> /proc/sys/net/ipv4/ip_local_port_range
该方法立即生效,但重启后会失效。
2、修改 /etc/sysctl.conf
文件,增加一行内容:
net.ipv4.ip_local_port_range = 1024 65535
保存成功后,需执行下面命令使之生效:
[root@localhost ~]# sysctl -p
修改成功后,可用端口即增加到65535-1024=64511个,即单个客户端机器只能同时模拟64511个用户。要想突破这个限制,只能给该客户端增加IP地址,这样即可相应成倍地增加可用IP:PORT数。具体可参考yongboy的这篇文章。
服务端
1:文件描述符数量受限
同客户端的问题1。
2:TCP参数调优
要想提高服务端的性能,以达到我们高并发的目的,需要对系统的TCP参数进行适当的修改优化。
方法同样是修改 /etc/sysctl.conf
文件,增加以下内容:
net.ipv4.tcp_tw_reuse = 1
当服务器需要在大量TCP连接之间切换时,会产生大量处于TIME_WAIT状态的连接。TIME_WAIT意味着连接本身是关闭的,但资源还没有释放。将net_ipv4_tcp_tw_reuse设置为1是让内核在安全时尽量回收连接,这比重新建立新连接要便宜得多。
net.ipv4.tcp_fin_timeout = 15
这是处于TIME_WAIT状态的连接在回收前必须等待的最小时间。改小它可以加快回收。
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
提高TCP的最大缓冲区大小,其中:
net.core.rmem_max
:表示接收套接字缓冲区大小的最大值(以字节为单位)。
net.core.wmem_max
:表示发送套接字缓冲区大小的最大值(以字节为单位)。
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
提高Linux内核自动对socket缓冲区进行优化的能力,其中:
net.ipv4.tcp_rmem
:用来配置读缓冲的大小,第1个值为最小值,第2个值为默认值,第3个值为最大值。
net.ipv4.tcp_wmem
:用来配置写缓冲的大小,第1个值为最小值,第2个值为默认值,第3个值为最大值。
net.core.netdev_max_backlog = 4096
每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目。默认为1000。
net.core.somaxconn = 4096
表示socket监听(listen)的backlog上限。什么是backlog呢?backlog就是socket的监听队列,当一个请求(request)尚未被处理或建立时,他会进入backlog。而socket server可以一次性处理backlog中的所有请求,处理后的请求不再位于监听队列中。当server处理请求较慢,以至于监听队列被填满后,新来的请求会被拒绝。默认为128。
net.ipv4.tcp_max_syn_backlog = 20480
表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。
net.ipv4.tcp_syncookies = 1
表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭。
net.ipv4.tcp_max_tw_buckets = 360000
表示系统同时保持TIME_WAIT套接字的最大数量,如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息。默认为180000。
net.ipv4.tcp_no_metrics_save = 1
一个tcp连接关闭后,把这个连接曾经有的参数比如慢启动门限snd_sthresh、拥塞窗口snd_cwnd,还有srtt等信息保存到dst_entry中,只要dst_entry没有失效,下次新建立相同连接的时候就可以使用保存的参数来初始化这个连接。
net.ipv4.tcp_syn_retries = 2
表示在内核放弃建立连接之前发送SYN包的数量,默认为4。
net.ipv4.tcp_synack_retries = 2
表示在内核放弃连接之前发送SYN+ACK包的数量,默认为5。
完整的TCP参数调优配置如下所示:
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
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.core.netdev_max_backlog = 4096
net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 20480
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_tw_buckets = 360000
net.ipv4.tcp_no_metrics_save = 1
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_synack_retries = 2
其它一些参数
vm.min_free_kbytes = 65536
用来确定系统开始回收内存的阀值,控制系统的空闲内存。值越高,内核越早开始回收内存,空闲内存越高。
vm.swappiness = 0
控制内核从物理内存移出进程,移到交换空间。该参数从0到100,当该参数=0,表示只要有可能就尽力避免交换进程移出物理内存;该参数=100,这告诉内核疯狂的将数据移出物理内存移到swap缓存中。
大战C100K之-Linux内核调优篇--转载的更多相关文章
- Linux网卡调优篇-禁用ipv6与优化socket缓冲区大小
Linux网卡调优篇-禁用ipv6与优化socket缓冲区大小 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一般在内网环境中,我们几乎是用不到IPV6,因此我们没有必要把多不 ...
- Linux内核调优参数说明
该脚本是我常用的系统安装后执行脚本,包括开机启动服务.内核.SSH优化. !/bin/sh 服务优化,(sshd.network.crond.syslog.rsyslog)服务保持默认开机启动 Ser ...
- linux内核调优参考
对于新部署的机器,需要做一些基本的调优操作,以更改一些默认配置带来的性能问题 1 修改打开文件数 root@mysql:/data/tools/db# vim /etc/security/limits ...
- (转)linux内核调优参数对比和解释
[net] ######################## cat /proc/sys/net/ipv4/tcp_syncookies # 默认值:1 # 作用:是否打开SYN Cookie功能,该 ...
- linux内核调优详解
cat > /etc/sysctl.conf << EOF net.ipv4.ip_forward = net.ipv4.conf.all.rp_filter = net.ipv4. ...
- Linux内核调优部分参数说明
#接收套接字缓冲区大小的默认值(以字节为单位). net.core.rmem_default = 262144 #接收套接字缓冲区大小的最大值(以字节为单位). net.core.rmem_max = ...
- Linux虚拟内存(swap)调优篇-“swappiness”,“vm.dirty_background_ratio”和“vm.dirty_ratio”
Linux虚拟内存(swap)调优篇-“swappiness”,“vm.dirty_background_ratio”和“vm.dirty_ratio” 作者:尹正杰 版权声明:原创作品,谢绝转载 ...
- Perf -- Linux下的系统性能调优工具,第 2 部分 特殊用法以及内核调优示例
https://www.ibm.com/developerworks/cn/linux/l-cn-perf2/ 本文内容简介 之前介绍了 perf 最常见的一些用法,关注于 Linux 系统上应用程序 ...
- 大数据集群Linux CentOS 7.6 系统调优篇
大数据集群Linux CentOS 7.6 系统调优篇 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.设置主机hosts文件 1>.修改主机名 [root@node100 ...
随机推荐
- VC、IE、ASP环境下打印、预备的完美解决方式
一种基于XML的报表开发工具,它支持从设计报表.调用API打印.预览,能支持分布式报表.方便报表的存储.转发. 在报表中能嵌入VBScript,能方便地訪问VB,VC的变量,能訪问COM组件.ADO等 ...
- Ubuntu 12.04使用演示
今年年初,发布了Ubuntu 12.04(代号Precise Pangolin),但正式版预计将于2012年的4月底发布,作者对最新版本的ubuntu做了试用,先将操作视频与大家分享.更多内容请关注本 ...
- 【深入篇】Android常用布局方式简介
LinearLayout 线性布局是程序中最常见的布局方式.一般分为水平线性布局和竖直线性布局,通过android.orientation属性可以设置线性布局的方向. 在布局中操作颜色时,要用的是十六 ...
- 什么是事件委托?jquery和js怎么去实现?
事件委托又叫事件代理,事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件. js: window.onload = function(){ var oul = docume ...
- react-native React Native version mismatch
android/app/build.gradle file: dependencies { compile fileTree(dir: "libs", include: [ ...
- logwatch日志监控
1. 介绍 在维护Linux服务器时,经常需要查看系统中各种服务的日志,以检查服务器的运行状态. 如登陆历史.邮件.软件安装等日志.系统管理员一个个去检查会十分不方便:且大多时候,这会是一种被动的检查 ...
- HDU 4107 Gangster
Gangster Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ID: 4 ...
- Cocos2d-x 之大牛看法
(未完毕) cocos2d-x并非一个适合网游client(mmo)的游戏引擎.越是大型游戏,这个小引擎就越无法驾驭(尽管它很受欢迎). 之前我在原来的公司使用的是自主研发的C3引擎,已经对外开放(尚 ...
- PYTHON学习第四天课后总结:
第三天学习课后总结: 今日重点: 流程控制 1,if 条件判断语句 2,while 循环 3,for 循环 一,if +条件判断语句: 1> if+条件判断表达式: 子代码1 子代码2 子代 ...
- php的数据类型和变量的作用域
1)php支持例如以下所看到的的基本数据类型: Integer(整数).Float(浮点数).String(字符串).Boolean(布尔值).Array(数组).Object(对象),此外还有两个特 ...