调优概述
Nginx介绍
Nginx 是一款轻量级的 Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,其特点是占有内存少,并发能力强,支持FastCGI、SSL、Virtual Host、URL Rewrite、Gzip等功能,并且支持很多第三方的模块扩展。
Nginx性能调优从大的方面来说,在系统设计之初,需要考虑硬件的选择,操作系统的选择,基础软件的选择;从小的方面来说,包括每个子系统的设计,算法选择,如何使用编译器的选项,如何发挥硬件最大的性能等等。
调优原则
在性能优化时,我们必须遵循一定的原则,否则,有可能得不到正确的调优结果。主要有以下几个方面:
-
对性能进行分析时,要多方面分析系统的资源瓶颈所在,因为系统某一方面性能低,也许并不是它自己造成的,而是其他方面造成的。如CPU利用率是100%时,很可能是内存容量太小,因为CPU忙于处理内存调度。
-
一次只对影响性能的某方面的一个参数进行调整,多个参数同时调整的话,很难界定性能的影响是由哪个参数造成的。
-
由于在进行系统性能分析时,性能分析工具本身会占用一定的系统资源,如CPU资源、内存资源等等。我们必须注意到这点,即分析工具本身运行可能会导致系统某方面的资源瓶颈情况更加严重。
调优思路
性能调优首要要发现问题,找到性能瓶颈点,然后根据瓶颈所处层级选择优化的方法,下图介绍了Nginx物理机的调优思路。
图1 Nginx物理机调优思路

调优分析思路如下:
-
对于服务端的问题,需要重点定位的硬件指标包括CPU、内存、硬盘、BIOS配置,其中CPU是需要重点关注的:服务端虚拟机CPU未压满或存在明显热点函数直接影响最终测试结果,需要注意的是虚拟机的CPU是否压满是在虚拟机内部查看,不是在host主机上查看;需要重点关注的软件指标包括应用软件、OS层的优化,该部分的调优对于性能的提升是很可观的。
-
对于网络问题,需要重点定位的包括网络带宽和网络中断,处理网络中断的核是否压满是需要重点关注的,http长连接场景需要重点关注网络带宽是否达到瓶颈。
-
对于客户端问题:客户端的性能是否满足测试需要,尤其对于http短连接场景。
硬件调优
配置BIOS
目的
对于不同的硬件设备,通过在BIOS中设置一些高级选项,可以有效提升服务器性能。
方法
步骤 1 关闭SMMU。
方法一:
1. 重启服务器,按Esc键进入BIOS设置界面。
2. 依次进入“Advanced > MISC Config > > Support Smmu”。
3. 将“Support Smmu”设置为“Disabled”,按“F10”保存退出(永久有效)。
方法二:
1. 执行vim /etc/grub2-efi.cfg命令。
2. 搜索字段"4.14",在内核代码中加入"iommu.passthrough=1"。

3. 保存退出后,重启服务器。
步骤 2 关闭预取。
1. 进入BIOS设置界面。
2. 依次进入“Advanced > MISC Config > CPU Prefetch”。
3. 将“CPU Prefetch”设置为“Disabled”,按“F10”保存退出(永久有效)。
操作系统调优
配置扩展文件描述符
目的
在Nginx环境中,需要配置最大打开文件数为102400,否则在测试过程中可能会导致软件最大打开文件数被限制在1024,影响服务器性能。
方法
步骤 1 在"/etc/security/limits.conf"文件中写入以下配置。
其中:*表示所有用户;hard表示严格的设定,必定不能超过这个设定的数值;soft表示警告的设定,可以超过这个设定值,但是若超过则有警告信息。
步骤 2 保存文件并重启服务器。
配置内核参数
目的
对于不同的操作系统,通过调优内核参数,可以有效的提高服务器的性能。
方法
步骤 1 执行vim /etc/sysctl.conf命令,并输入下列内核参数:
内核参数说明如下表所示:
说明
当使用容器时,由于不能关闭nf_conntrack模块,所以需要在内核参数中增加nf_conntrack相关设置,防止table记录满产生丢包问题。
在/etc/sysctl.conf文件中还需添加如下内核参数:
步骤 2 写入参数后保存配置文件
步骤 3 执行命令以生效配置:
关闭nf_conntrack模块
注意
使用容器的场景不能做本章节的操作。
目的
内核的nf_conntrack模块可以用来实现NAT,但是在没有使用NAT的场景,开启nf_conntrack模块会导致不需要的CPU消耗,甚至可能导致table记录满产生丢包问题,因此可以考虑关闭nf_conntrack模块提升性能。
方法
步骤 1 在"/etc/modprobe.d/blacklist.conf"文件中加入如下参数:
步骤 2 保存文件后,重启服务器使文件生效。
关闭selinux
目的
为了减少selinux的性能损耗,关闭selinux。
方法
步骤 1 执行vim /etc/sysconfig/selinux命令,打开selinux文件。
步骤 2 将"SELINUX=enforcing" 改为 "SELINUX=disabled"。
步骤 3 保存文件,重启服务器。
步骤 4 执行如下语句确认selinux是否关闭,如果SELinux status参数显示为disabled即为关闭状态。
配置网卡中断绑核
目的
-
每个CPU对应一个网卡,每个CPU内的中断绑核只绑在属于本CPU的网卡上,按node各自绑核。
-
中断个数在尽量少的情况下满足当前所有业务core在客户端满压下满CPU运作即可。
方法
步骤 1 关闭irqbalance。
若要对网卡进行绑核操作,需要关闭irqbalance。
1. 关闭irqbalance服务,重启失效。
2. 停止irqbalance服务,永久有效。
3. 查看irqbalance服务状态是否已关闭。
步骤 2 网卡中断绑核。
网卡中断绑核,绑定的核专门用于处理网卡中断。
1. 设置队列深度为CPU的核数
2. 查询中断号。
3. 根据中断号,将每个中断各绑定在一个核上。
绑核脚本示例
绑核脚本内容如下所示,以4core的http短连接场景的绑核脚本为例,如果要修改绑核脚本,只需修改要绑定的网口名eth1,以及要绑定的core,然后在关闭irqbalance.service的情况下使用脚本即可:
Nginx调优
目的
通过调优Nginx的配置文件,可以有效的提高服务器的性能。
方法
步骤 1 Nginx.conf根据测试的业务核数,修改worker_processes和worker_cpu_affinity配置。
调优原则:以压满业务核为前提,用尽量少的中断核,配合中断脚本使用。
步骤 2 为nginx示例配置html文件。
Html文件策略:每个nginx实例分别访问独自的html文件。
故每起一个nginx实例,就需要增加一个html文件。在2p测试时,需要在/Nginx/html下新增一个html,并在相应的nginx.conf中修改所有location中的对应页面。
步骤 3 Nginx启动添加taskset。
将Nginx的master进程绑定在N号core上。
绑定策略:跟自己的业务core绑在同一个node或者CPU上。
配置文件参数说明
以Nginx虚拟机http短连接为例,主要的配置参数如下,配合绑核中断即可使用。对于其他场景只需修改worker_processes和worker_cpu_affinity即可。
Nginx的配置是区块型的,包括全局配合(如user、worker_processes等)和模块配置(其中events为events模块,http为http模块),每个模块配置中又分为各个区块,如http模块中有server区块,server有location区块。Nginx基本配置与参数说明如下:
调优概述
Nginx介绍
Nginx 是一款轻量级的 Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,其特点是占有内存少,并发能力强,支持FastCGI、SSL、Virtual Host、URL Rewrite、Gzip等功能,并且支持很多第三方的模块扩展。
Nginx性能调优从大的方面来说,在系统设计之初,需要考虑硬件的选择,操作系统的选择,基础软件的选择;从小的方面来说,包括每个子系统的设计,算法选择,如何使用编译器的选项,如何发挥硬件最大的性能等等。
调优原则
在性能优化时,我们必须遵循一定的原则,否则,有可能得不到正确的调优结果。主要有以下几个方面:
对性能进行分析时,要多方面分析系统的资源瓶颈所在,因为系统某一方面性能低,也许并不是它自己造成的,而是其他方面造成的。如CPU利用率是100%时,很可能是内存容量太小,因为CPU忙于处理内存调度。
一次只对影响性能的某方面的一个参数进行调整,多个参数同时调整的话,很难界定性能的影响是由哪个参数造成的。
由于在进行系统性能分析时,性能分析工具本身会占用一定的系统资源,如CPU资源、内存资源等等。我们必须注意到这点,即分析工具本身运行可能会导致系统某方面的资源瓶颈情况更加严重。
调优思路
性能调优首要要发现问题,找到性能瓶颈点,然后根据瓶颈所处层级选择优化的方法,下图介绍了Nginx物理机的调优思路。
图1 Nginx物理机调优思路
调优分析思路如下:
对于服务端的问题,需要重点定位的硬件指标包括CPU、内存、硬盘、BIOS配置,其中CPU是需要重点关注的:服务端虚拟机CPU未压满或存在明显热点函数直接影响最终测试结果,需要注意的是虚拟机的CPU是否压满是在虚拟机内部查看,不是在host主机上查看;需要重点关注的软件指标包括应用软件、OS层的优化,该部分的调优对于性能的提升是很可观的。
对于网络问题,需要重点定位的包括网络带宽和网络中断,处理网络中断的核是否压满是需要重点关注的,http长连接场景需要重点关注网络带宽是否达到瓶颈。
对于客户端问题:客户端的性能是否满足测试需要,尤其对于http短连接场景。
硬件调优
配置BIOS
目的
对于不同的硬件设备,通过在BIOS中设置一些高级选项,可以有效提升服务器性能。
服务器上的SMMU一般用来完成设备的地址转换,并且可以实现设备隔离,在虚拟化中很实用,但是在物理机测试场景下,SMMU可能会导致性能下降,尤其对于小包网络场景,因此建议关闭该功能提升服务器性能。在虚拟机场景需要打开此配置来使用PCI直通功能。
在本测试场景中,预取会导致cache污染,cache miss增加,因此建议关闭预取功能。
方法
步骤 1 关闭SMMU。
方法一:
1. 重启服务器,按Esc键进入BIOS设置界面。
2. 依次进入“Advanced > MISC Config > > Support Smmu”。
3. 将“Support Smmu”设置为“Disabled”,按“F10”保存退出(永久有效)。
方法二:
1. 执行vim /etc/grub2-efi.cfg命令。
2. 搜索字段"4.14",在内核代码中加入"iommu.passthrough=1"。
3. 保存退出后,重启服务器。
步骤 2 关闭预取。
1. 进入BIOS设置界面。
2. 依次进入“Advanced > MISC Config > CPU Prefetch”。
3. 将“CPU Prefetch”设置为“Disabled”,按“F10”保存退出(永久有效)。
操作系统调优
配置扩展文件描述符
目的
在Nginx环境中,需要配置最大打开文件数为102400,否则在测试过程中可能会导致软件最大打开文件数被限制在1024,影响服务器性能。
方法
步骤 1 在"/etc/security/limits.conf"文件中写入以下配置。
其中:*表示所有用户;hard表示严格的设定,必定不能超过这个设定的数值;soft表示警告的设定,可以超过这个设定值,但是若超过则有警告信息。
步骤 2 保存文件并重启服务器。
配置内核参数
目的
对于不同的操作系统,通过调优内核参数,可以有效的提高服务器的性能。
方法
步骤 1 执行vim /etc/sysctl.conf命令,并输入下列内核参数:
内核参数说明如下表所示:
linux参数
参数定义
当前值
默认值
net.ipv4.tcp_tw_reuse
1表示允许将TIME-WAIT sockets重新用于新的TCP连接,0表示关闭。
1
0
net.ipv4.tcp_keepalive_time
TCP发送keepalive探测消息的间隔时间(秒),用于确认TCP连接是否有效
60
7200
net.ipv4.tcp_fin_timeout
socket 保持在 FIN_WAIT_2 状态的最大时间
1
60
net.ipv4.tcp_max_tw_buckets
减少TIME_WAIT连接数,避免过多TIME_WAIT连接占用网络资源导致新建连接资源紧张,时延增加
5000
262144
net.ipv4.ip_local_port_range
增加可用端口范围,避免大量连接占用端口时,新建连接不断寻找可用端口导致的性能跳水
1024 65500
32768 61000
net.core.somaxconn
定义了系统中每一个端口最大的监听队列的长度,这是个全局的参数
65535
128
net.ipv4.tcp_max_syn_backlog
表示SYN队列的长度,加大队列长度可以容纳更多等待连接的网络连接
262144
1024
net.core.netdev_max_backlog
当每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目
262144
1000
net.core.rmem_max
系统套接字读最大缓冲区
16777216
131071
net.core.wmem_max
系统套接字写最大缓冲区,增加buffer大小,避免大量新建连接导致buffer溢出,出现无法建立连接情况
16777216
131071
net.nf_conntrack_max
最大跟踪连接数
0
65536
说明
当使用容器时,由于不能关闭nf_conntrack模块,所以需要在内核参数中增加nf_conntrack相关设置,防止table记录满产生丢包问题。
在/etc/sysctl.conf文件中还需添加如下内核参数:
步骤 2 写入参数后保存配置文件
步骤 3 执行命令以生效配置:
关闭nf_conntrack模块
注意
使用容器的场景不能做本章节的操作。
目的
内核的nf_conntrack模块可以用来实现NAT,但是在没有使用NAT的场景,开启nf_conntrack模块会导致不需要的CPU消耗,甚至可能导致table记录满产生丢包问题,因此可以考虑关闭nf_conntrack模块提升性能。
方法
步骤 1 在"/etc/modprobe.d/blacklist.conf"文件中加入如下参数:
步骤 2 保存文件后,重启服务器使文件生效。
关闭selinux
目的
为了减少selinux的性能损耗,关闭selinux。
方法
步骤 1 执行vim /etc/sysconfig/selinux命令,打开selinux文件。
步骤 2 将"SELINUX=enforcing" 改为 "SELINUX=disabled"。
步骤 3 保存文件,重启服务器。
步骤 4 执行如下语句确认selinux是否关闭,如果SELinux status参数显示为disabled即为关闭状态。
配置网卡中断绑核
目的
每个CPU对应一个网卡,每个CPU内的中断绑核只绑在属于本CPU的网卡上,按node各自绑核。
中断个数在尽量少的情况下满足当前所有业务core在客户端满压下满CPU运作即可。
方法
步骤 1 关闭irqbalance。
若要对网卡进行绑核操作,需要关闭irqbalance。
1. 关闭irqbalance服务,重启失效。
2. 停止irqbalance服务,永久有效。
3. 查看irqbalance服务状态是否已关闭。
步骤 2 网卡中断绑核。
网卡中断绑核,绑定的核专门用于处理网卡中断。
1. 设置队列深度为CPU的核数
2. 查询中断号。
cat /proc/interrupts | grep $eth1 | awk -F ':' '{print $1}'3. 根据中断号,将每个中断各绑定在一个核上。
绑核脚本示例
绑核脚本内容如下所示,以4core的http短连接场景的绑核脚本为例,如果要修改绑核脚本,只需修改要绑定的网口名eth1,以及要绑定的core,然后在关闭irqbalance.service的情况下使用脚本即可:
#!/bin/bash cnt=2 eth1=enp3s0 ethtool -L $eth1 combined $cnt irq1=`cat /proc/interrupts| grep -E ${eth1} | head -1 | awk -F ':' '{print $1}'` irq1=`echo $irq1`i=0 while(( $i < 1)) do for cpunum in 2 3 do echo $cpunum "->" $irq1 echo $cpunum > /proc/irq/$irq1/smp_affinity_list let "irq1++" done let "i++" done 参数说明如下表所示:参数名称
参数解释
cnt
网口队列数
eth1
通信中使用的网口名
irq1
网口eth1对应的中断号
cpumun
分配给网口eth1用于处理网卡中断的核
Nginx调优
目的
通过调优Nginx的配置文件,可以有效的提高服务器的性能。
方法
步骤 1 Nginx.conf根据测试的业务核数,修改worker_processes和worker_cpu_affinity配置。
调优原则:以压满业务核为前提,用尽量少的中断核,配合中断脚本使用。
步骤 2 为nginx示例配置html文件。
Html文件策略:每个nginx实例分别访问独自的html文件。
故每起一个nginx实例,就需要增加一个html文件。在2p测试时,需要在/Nginx/html下新增一个html,并在相应的nginx.conf中修改所有location中的对应页面。
步骤 3 Nginx启动添加taskset。
将Nginx的master进程绑定在N号core上。
绑定策略:跟自己的业务core绑在同一个node或者CPU上。
配置文件参数说明
以Nginx虚拟机http短连接为例,主要的配置参数如下,配合绑核中断即可使用。对于其他场景只需修改worker_processes和worker_cpu_affinity即可。
Nginx的配置是区块型的,包括全局配合(如user、worker_processes等)和模块配置(其中events为events模块,http为http模块),每个模块配置中又分为各个区块,如http模块中有server区块,server有location区块。Nginx基本配置与参数说明如下:
user root;
worker_processes 3;
worker_cpu_affinity
1
10
100;
error_log /dev/null;
worker_rlimit_nofile 102400;
#全局配置:
#定义Nginx运行的用户和用户组。
#nginx进程数,建议设置为等于CPU总核心数。
#通过worker_cpu_affinity给每个worker进程绑定一个CPU, 1表示启用core0,10表示启用core1,100表示启动core2,依次类推,100000表示启用core5,1后面有n个0就表示启动core n。
#错误日志文件路径,/dev/null表示关闭nginx日志。
#指定一个nginx进程打开的最多文件描述符数目,受系统进程的最大打开文件数量(ulimit -n)限制。
events {
worker_connections 102400;
multi_accept on;
use epoll;
accept_mutex on;
}
#events模块配置:
#定义每个进程的最大连接数,受系统进程的最大打开文件数量限制,并发总数是worker_processes 和 worker_connections 的乘积。
#告诉nginx进程收到一个新连接通知后接受尽可能多的连接,如果multi_accept被禁止了,nginx一个工作进程只能同时接受一个新的连接。
#设置工作模式为epoll,除此之外还有select,poll,kqueue,rtsig和/dev/poll模式。
#打开accept_mutex,避免了worker争夺资源造成的上下文切换以及try_lock的锁开销
http {
include mime.types;
default_type application/octet-stream;
access_log /dev/null;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
sendfile_max_chunk 512k;
keepalive_timeout 65;
keepalive_requests 2000;
client_header_buffer_size 4k;
large_client_header_buffers 4 32k;
server_names_hash_bucket_size 128;
client_max_body_size 100m;
open_file_cache max=102400 inactive=40s;
open_file_cache_valid 50s;
open_file_cache_min_uses 1;
open_file_cache_errors on;
#http模块配置:
#文件扩展名与文件类型映射表。
#默认文件类型。
#Nginx访问日志路径,/dev/null表示关闭访问日志。
#开启高效文件传输模式,获取文件跨过用户态;.gzip压缩器需要在用户态进行,因此无法和sendfile共存。
#开启防止网络阻塞,返回数据的首个数据包会携带从sendfile中获取大块的数据后才会被发送。
#开启防止网络阻塞。
#限制最大sendfile的文件大小,防止过大的文件占据整个工作进程默认为“无限制”。
#设置客户端连接保存活动的超时时间。
#设置一个keep-alive连接上可以服务的请求的最大数量。当最大请求数量达到时,连接被关闭。
#客户端请求头部的缓冲区大小,这个可以根据你的系统分页大小来设置,一般一个请求的头部大小不会超过1k,不过由于一般系统分页都要大于1k,所以这里设置为分页大小。分页大小可以用命令getconf PAGESIZE取得。
#设置客户端请求的Header头缓冲区大小:4为个数,32k为大小,表示申请4个32k。当http 的URI太长或者request header过大时会报414 Request URI too large或400 bad request错误。
#保存服务器名字的hash表的大小。
#控制全局nginx所有请求报文大小,100M。
#max设置缓存中的最大元素数,在缓存溢出时,删除最近最少使用(LRU)的元素;inactive定义一个时间,如果在此期间未访问该元素,则从该缓存中删除该元素。
#多长时间检查一次缓存的有效信息。也就是说即使我一直访问这个文件,30s后会检查此文件的更改信息是否变化,发现变化就更新
# open_file_cache指令中的inactive参数时间内文件的最少使用次数,如果超过这个数字,文件更改信息一直是在缓存中打开的
#启用文件查找错误的缓存
server {
listen 10000 reuseport;
server_name localhost;
access_log off;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
#设定主机配置
#侦听10000端口,http短连接场景建议打开reuseport
#定义使用localhost访问
#关闭主机的访问日志
#默认请求
#定义服务器的默认网站根目录位置,root是web根目录
#定义首页索引文件的名称及顺序
# 定义错误提示页面
# HTTPS server
server {
listen 20000 ssl;
server_name localhost;
ssl_certificate /usr/local/nginx/server_2048.crt;
ssl_certificate_key /usr/local/nginx/server_2048.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4";
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
}
}
#配置ssl加密
#侦听20000端口
#定义使用localhost访问
# ssl_certificate证书是公钥,它会被发送到连接服务器的每个客户端
# ssl_certificate_key私钥是用来解密的,所以它的权限要得到保护但nginx的主进程能够读取。当然私钥和证书可以放在一个证书文件中,这种方式也只有公钥证书才发送到client。
#设置ssl会话缓存的类型和大小,shared:SSL:1m表示我所有的nginx工作进程共享ssl会话缓存,1M可以存放约4000个sessions。
#客户端可以重用会话缓存中ssl参数的过期时间,5分钟
#用于启动特定的加密协议
#选择加密套件
#设置协商加密算法时,优先使用我们服务端的加密套件,而不是客户端浏览器的加密套件。
#定义服务器的默认网站根目录位置,root是web根目录
#定义首页索引文件的名称及顺序