Nginx性能调优
Nginx介绍
Nginx以高性能负载均衡、缓存和web服务器出名,支撑着世界上繁忙网站中的40%。大多数使用场景下,Nginx和Linux系统的默认配置表现较好,但是仍有必要做一些调优以期达到最佳性能。这篇文章讨论当调优系统时需要考虑的一些Nginx和Linux配置。这些配置有很多,但是在本文里我们只涉及适合大多数用户的配置。那些没有涉及到的配置,只有那些对Nginx和Linux有深入理解的人,或者Nginx专家服务团队推荐,才会考虑到。Nginx专家服务,已经和世界上一些繁忙网站合作来调优Nginx以达到最大限度的性能,并且可以对任何需要充分发挥系统能力的客户提供支持。
Web服务性能调优是一项系统工程,涵盖许多方面,其中某一环节做的好并不能够保证整体性能好;但是如果某个环节做的不好,那么整体性能必然不会好。
注意 :调优时,有一条较好的准则是,一次只改一个配置项,如果改后没有性能上的提升,就退回为原先的值。
以下设定的值会影响在Nginx配置中可以用的值。
Linux系统参数优化
下文中提到的一些配置,需要较新的Linux(2.6以上)内核才能够支持,笔者使用的CentOS 7.4,内核版本3.10,如果不满足需要的话,最好进行相应的升级,毕竟打补丁是件费力不讨好的事情。对于系统层面的调优,通常我们修改文件描述符限制、缓冲区队列长度以及临时端口数量就可以了。
Backlog队列
以下设置与连接及其如何排队直接相关。如果传入的连接率很高而性能水平参差不齐,比如一些连接似乎被暂停了,那么更改这些配置可能会有用。
- net.core.somaxconn
该项设置等待被Nginx接受的连接的排队大小。由于Nginx接受连接速度非常快,这个值通常不需要非常大,但是默认值是非常低的,所以如果你有一个高流量网站,增加这个值是个好主意。如果设置过低,那么你能在内核日志中看到错误信息,这时你应该增加这个值直到没有错误信息。注意:如果你将其设置为大于512的值,你应该同时用listen指令的backlog参数匹配这个值来更改Nginx的配置。 - net.core.netdev_max_backlog
该项设置在交由CPU处理之前网卡缓冲数据包的速率。对于拥有高带宽的机器,这个值可能需要增加。查看网卡文档寻求相关建议,或者检查内核日志相关错误信息。
文件描述符限制
由于每个TCP连接都要占用一个文件描述符,一旦文件描述符耗尽,新的连接到来就会返回“Too many open files”这样的错误,为了提高性能,我们需要对其进行修改:
系统层级的限制 编辑文件 /etc/sysctl.conf,添加如下内容:
fs.file-max = 10000000
fs.nr_open = 10000000
用户层级的限制 编辑文件 /etc/security/limits.conf,添加以下内容:
* hard nofile 1000000
* soft nofile 1000000
这里我们只要保证用户层级限制不大于系统层级限制就可以了,否则可能会出现无法通过SSH登录系统的问题。修改完毕执行如下命令:
$ sysctl -p
可以通过执行命令 ulimit -a查看是否修改成功。
TCP连接队列长度
编辑文件 /etc/sysctl.conf,添加如下内容:
# The length of the syn quene
net.ipv4.tcp_max_syn_backlog = 65535
# The length of the tcp accept queue
net.core.somaxconn = 65535
其中tcp_max_syn_backlog用于指定半连接SYN队列长度,当新连接到来时,系统会检测半连接SYN队列,如果队列已满,则无法处理该SYN请求,并在 /proc/net/netstat中的 ListenOverflows和 ListenDrops中增加统计计数
somaxconn用于指定全连接ACCEPT队列长度,当该队列满了以后,客户端发送的ACK包将无法被正确处理,并返回错误"connection reset by peer"
Nginx则会记录一条error日志
“no live upstreams while connecting to upstreams”
如果出现以上错误,我们需要考虑增大这两项的配置。
Events模块
events模块中包含nginx中所有处理连接的设置。
events {
worker_connections 2048;
multi_accept on;
use epoll;
}
- worker_connections
设置可由一个worker进程同时打开的最大连接数。如果设置了上面提到的worker_rlimit_nofile,我们可以将这个值设得很高。
记住,最大客户数也由系统的可用socket连接数限制(~ 64K),所以设置不切实际的高没什么好处。 - multi_accept 告诉nginx收到一个新连接通知后接受尽可能多的连接。
- use 设置用于复用客户端线程的轮询方法。如果你使用Linux
2.6+,你应该使用epoll。如果你使用*BSD,你应该使用kqueue。
(值得注意的是如果你不知道Nginx该使用哪种轮询方法的话,它会选择一个最适合你操作系统的)
HTTP 模块
http {
server_tokens off;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
...
}
- server_tokens 并不会让nginx执行的速度更快,但它可以关闭在错误页面中的nginx版本数字,这样对于安全性是有好处的。
- sendfile 可以让sendfile()发挥作用。sendfile()可以在磁盘和TCP
socket之间互相拷贝数据(或任意两个文件描述符)。Pre-sendfile是传送数据之前在用户空间申请数据缓冲区。之后用read()将数据从文件拷贝到这个缓冲区,write()将缓冲区数据写入网络。sendfile()是立即将数据从磁盘读到OS缓存。因为这种拷贝是在内核完成的,sendfile()要比组合read()和write()以及打开关闭丢弃缓冲更加有效(更多有关于sendfile)。 - tcp_nopush 告诉nginx在一个数据包里发送所有头文件,而不一个接一个的发送。
- tcp_nodelay
告诉nginx不要缓存数据,而是一段一段的发送–当需要及时发送数据时,就应该给应用设置这个属性,这样发送一小块数据信息时就不能立即得到返回值。
临时端口
由于Nginx用作代理,每一个到upstream服务器的连接都使用一个临时端口。或者每个到上游Web服务的TCP连接都要占用一个临时端口,因此我们需要修改ip_local_port_range参数
修改 /etc/sysctl.conf文件,添加如下内容:
- net.ipv4.ip_local_port_range
这个用来指定可以使用的起止端口号。如果你看到端口耗尽,你可以增加这个范围。常见的设置为1024到65000。 - net.ipv4.tcp_fin_timeout
这个用于指定一个不再被使用的端口多久之后可以被另一连接再次使用。通常,这个值默认为60秒,但是可以安全地减少到30甚至15秒。
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.ip_local_reserved_ports = 8080,8081,9000-9010
其中,参数 ip_local_reserved_ports用于指定保留端口,这是为了防止服务端口被占用而无法启动。
Nginx配置
access_log off;
error_log /var/log/nginx/error.log crit;
- access_log 设置nginx是否将存储访问日志。关闭这个选项可以让读取磁盘IO操作更快(aka,YOLO)
- error_log 告诉nginx只能记录严重的错误:
keepalive_timeout 10;
client_header_timeout 10;
client_body_timeout 10;
reset_timedout_connection on;
send_timeout 10;
- keepalive_timeout
给客户端分配keep-alive链接超时时间。服务器将在这个超时时间过后关闭链接。我们将它设置低些可以让ngnix持续工作的时间更长。 - client_header_timeout 和client_body_timeout
设置请求头和请求体(各自)的超时时间。我们也可以把这个设置低些。 - reset_timeout_connection 告诉nginx关闭不响应的客户端连接。这将会释放那个客户端所占有的内存空间。
- send_timeout
指定客户端的响应超时时间。这个设置不会用于整个转发器,而是在两次客户端读取操作之间。如果在这段时间内,客户端没有读取任何数据,nginx就会关闭连接。
limit_conn_zone $binary_remote_addr zone=addr:5m;
limit_conn addr 100;
- limit_conn_zone
设置用于保存各种key(比如当前连接数)的共享内存的参数。5m就是5兆字节,这个值应该被设置的足够大以存储(32K5)32byte状态或者(16K5)64byte状态。 - limit_conn
为给定的key设置最大连接数。这里key是addr,我们设置的值是100,也就是说我们允许每一个IP地址最多同时打开有100个连接。
gzip on;
gzip_disable "msie6";
# gzip_static on;
gzip_proxied any;
gzip_min_length 1000;
gzip_comp_level 4;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
- gzip 是告诉nginx采用gzip压缩的形式发送数据。这将会减少我们发送的数据量。
- gzip_disable 为指定的客户端禁用gzip功能。我们设置成IE6或者更低版本以使我们的方案能够广泛兼容。
- gzip_static
告诉nginx在压缩资源之前,先查找是否有预先gzip处理过的资源。这要求你预先压缩你的文件(在这个例子中被注释掉了),从而允许你使用最高压缩比,这样nginx就不用再压缩这些文件了(想要更详尽的gzip_static的信息,请点击这里)。 - gzip_proxied 允许或者禁止压缩基于请求和响应的响应流。我们设置为any,意味着将会压缩所有的请求。
- gzip_min_length
设置对数据启用压缩的最少字节数。如果一个请求小于1000字节,我们最好不要压缩它,因为压缩这些小的数据会降低处理此请求的所有进程的速度。 - gzip_comp_level
设置数据的压缩等级。这个等级可以是1-9之间的任意数值,9是最慢但是压缩比最大的。我们设置为4,这是一个比较折中的设置。 - gzip_type 设置需要压缩的数据格式。上面例子中已经有一些了,你也可以再添加更多的格式。
open_file_cachemax=100000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
- open_file_cache
打开缓存的同时也指定了缓存最大数目,以及缓存的时间。我们可以设置一个相对高的最大时间,这样我们可以在它们不活动超过20秒后清除掉。 - open_file_cache_valid 在open_file_cache中指定检测正确信息的间隔时间。
- open_file_cache_min_uses 定义了open_file_cache中指令参数不活动时间期间里最小的文件数。
- open_file_cache_errors
指定了当搜索一个文件时是否缓存错误信息,也包括再次给配置中添加文件。我们也包括了服务器模块,这些是在不同文件中定义的。如果你的服务器模块不在这些位置,你就得修改这一行来指定正确的位置
更多介绍 :https://www.jianshu.com/p/9769950c06ad
下面这描述也是非常好的:http://blog.csdn.net/xyang81/article/details/51814787
服务器级别核心配置
- worker_processesmainworker_processes number;1配置工作进程数。传统的web服务器(如apache)都是同步阻塞模型,一请求一进(线)程模式,当进(线)程数增达到一定程度后,更多CPU时间浪费在线程和进程切换当中,性能急剧下降,所以负载率不高。Nginx是基于事件的非阻塞多路复用(epoll或kquene)模型,一个进程在短时间内就可以响应大量的请求。建议将该值设置<=cpu核心数量,一般高于cpu核心数量不会带来好处,反而可能会有进程切换开销的负面影响。
- worker_connectionseventsworker_connections number;1024并发响应能力的关键配置值,表示每个进程允许的最大同时连接数。maxConnection = work_connections * worker_processes;一般一个浏览器会同时开两条连接,如果是反向代理,nginx到后服务器的连接数量也要占用2条连接数,所以,做静态服务器,一般maxConnection= work_connections * worker_processes / 2; 做反代理服务器时maxConnection = work_connections * worker_processes / 4;
- useeventsuse epoll;根据不同的平台,选择最高效的连接处理方法指定处理连接请求的方法。linux内核2.6以上默认使用epoll方法,其它平台请参考:http://nginx.org/en/docs/events.html
备注:要达到超高负载下最好的网络响应能力,还有必要优化与网络相关的linux内核参数 - worker_cpu_affinitymainworker_cpu_affinity cpumask
…;无将工作进程绑定到特定的CPU上,减少CPU在进程之间切换的开销。用二进制bit位表示进程绑定在哪个CPU内核。如8内核4进程时的设置方法:worker_cpu_affinity
00000001 00000010 00000100 10000000 - worker_rlimit_nofilemainworker_rlimit_core
size;受linux内核文件描述符数量限制设置nginx最大能打开的文件描述符数量。因为Linux对每个进程所能打开的文件描述数量是有限制的,默认一般是1024个,可通过ulimit
-n FILECNT或/etc/securit/limits.conf配置修改linux默认能打开的文件句柄数限制。建议值为:系统最大数量/进程数。但进程间工作量并不是平均分配的,所以可以设置在大一些。推荐值为:655350 - error_logmain, http, mail, stream, server, locationerror_log 日志文件路径
日志级别;error_log logs/error.log error;配置错误日志文件的路径和日志级别。日志级别有debug,info, notice, warn, error, crit,alert和emerg几种。nginx的日志使用syslog输出,所以输出的日志格式是有规律的,系统运维人员可以根据日志规则进行查错或统计分析。更多说明请参考官方文档:http://nginx.org/en/docs/ngx_core_module.html#error_log
Nginx参数优化
Nginx参数优化主要围绕 nginx.conf这个配置文件展开,下文不再赘述。
工作进程
Nginx性能强大的一个重要原因在于它采用多进程非阻塞I/O模型,因此我们要妥善利用这一点:
- worker_processes
默认的Nginx只有一个master进程一个worker进程,我们需要对其进行修改,可以设置为指定的个数,也可以设置为 auto,即系统的CPU核数。更多的worker数量将导致进程间竞争cpu资源,从而带来不必要的上下文切换。因此这里我们将它设置为cpu的核数即可:
worker_processes auto
- worker_connections每个worker可以处理的并发连接数,默认值512不是很够用,我们适当将它增大:
worker_connections 4096
Nginx支持以下I/O复用方法处理连接:select、 poll、 kqueue、 epoll、 rtsig、 /dev/poll、 eventport。它们分别适用于不同的操作系统,其中 epoll是Linux系统上面效率最高的: use epoll
KeepAlive
持久连接可以减少打开和关闭连接所需要的CPU和网络开销,因而对性能有重大影响。Nginx终止所有客户端连接,并具有到upstream服务器的单独连接。Nginx支持客户端和upstream服务器的持久连接。如下指令涉及客户端持久连接:
- keepalive_requests
这表示客户端能在单个持久连接上发送多少请求。默认值是100,可以设置成更高的值,这在负载生成器从单个客户端发送大量请求的测试场景中非常有用。 - keepalive_timeout 表示一个空闲持久连接保持打开状态多长时间。
如下指令涉及upstream持久连接:
- keepalive 这个指定每个工作进程连接到upstream服务器的空闲持久连接数量。这个指令没有默认值。
为了启用到upstream的持久连接,需要增加如下指令: - proxy_http_version 1.1;
- proxy_set_header Connection “”;
为了避免从Nginx到Web服务频繁的建立、断开连接,我们可以启用从HTTP 1.1开始支持的KeepAlive长连接特性,它可以大幅减少CPU和网络开销,在我们的实战中也是对性能提高最大的一环。keepalive必须和 proxy_http_version与 proxy_set_header结合使用, 参考配置如下:
upstream BACKEND {
keepalive 300;
server 127.0.0.1:8081;
}
server {
listen 8080;
location / {
proxy_pass http://BACKEND;
proxy_http_version 1.1;
proxy_set_header Connection"";
}
}
其中 keepalive既非timeout,也不是连接池数量,官方解释如下:
The connections parameter sets the maximum number of idle keepalive connections to upstream servers that are preserved in the cache of each worker process. When this number is exceeded, the least recently used connections are closed.
可以看出它的意思是“最大空闲长连接数量”,超出这个数量的空闲长连接将被回收,当请求数量稳定而平滑时,空闲长连接数量将会非常小(接近于0),而现实中请求数量是不可能一直平滑而稳定的,当请求数量有波动时,空闲长连接数量也随之波动:
当空闲长连接数量大于配置值时,将会导致大于配置值的那部分长连接被回收;
当长连接不够用时,将会重新建立新的长连接。
因此,如果这个值过小的话,就会导致连接池频繁的回收、分配、再回收。
为了避免这种情况出现,可以根据实际情况适当调整这个值,在我们实际情况中,目标QPS为6000,Web服务响应时间约为200ms,因此需要约1200个长连接,而 keepalive值取长连接数量的10%~30%就可以了,这里我们取300,如果不想计算,直接设为1000也是可行的。
Access-Log缓存
记录每个请求需要花费CPU和IO周期,减少这种影响的一种方法是启用access日志缓冲。这将导致Nginx缓冲一系列日志条目,然后一次性写入文件而不是单个单个写入。通过指定access_log指令的"buffer=size"选项可以打开access日志缓冲,该设置指定要使用的缓冲区的大小。你还可以使用"flush=time"选项告诉Nginx多长时间后把缓冲区中的条目写入文件。定义了这两个选项后,当缓冲区放不下下一条日志,或者缓冲区中的条目超过了flush参数指定的时间,Nginx会将缓冲区中的条目写入日志文件。当工作进程重新打开日志文件或者关闭时,缓冲区中的条目也会被写入文件。也可以完全禁用access日志记录。
记录日志的I/O开销比较高,好在Nginx支持日志缓存,我们可以利用这个功能,降低写日志文件的频率,从而提高性能。可以将 buffer和 flush两个参数结合使用来控制缓存行为:
access_log /var/logs/nginx-access.log buffer=64k gzip flush=1m
其中 buffer制定了缓存大小,当缓冲区达到 buffer所指定的大小时,Nginx就会将缓存起来的日志写到文件中;flush指定了缓存超时时间,当 flush指定的时间到达时,也会触发缓存日志写入文件操作
限制
Nginx和Nginx Plus允许设置各种限制,用来控制客户端资源消耗,以防影响系统性能以及用户体验和安全。以下是一些相关指令:
- limit_conn / limit_conn_zone
这些指令可以用来限制Nginx允许的连接数,比如来自单个客户端IP地址的连接数。这可以防止单个客户端打开太多连接而消耗太多资源。 - limit_rate
这个用来限制客户端在单个连接上允许使用的带宽。这可以防止某些客户端导致系统超载,因而有利于为所有客户端提供QoS保证。 - limit_req / limit_req_zone
这些指令可以用来限制Nginx的请求处理速率。与limit_rate一起,可以防止某些客户端导致系统超载,因而有利于为所有客户端提供QoS保证。这些指令也可以用来增强安全性,尤其是对登录页面,通过限制请求速率,使得其对人类用户是合适的,而会减慢试图访问你的应用的程序。 - max_conns
这个用来限制同时连接到upstream组中单个服务器的最大连接数。这可以防止upstream服务器超载。默认值是0,表示没有限制。 - queue
如果设置了max_conns,那么queue指令用来决定当一个请求由于upstream组中没有可用服务器或者这些服务器达到max_conns限制而不能得到处理时会发生什么。这个指令用来设定有多少请求将会排队以及排多久。如果没有设置这个指令,就不会有排队行为。
文件描述符限制
上一节中已经对Linux系统的文件描述符限制进行了修改,Nginx配置中同样有相应的配置项:worker_rlimit_nofile, 理论上这个值应该设置为 /etc/security/limits.conf中的值除以worker_processes,但实际中不可能每个进程均匀分配,所以这里只要设置成和/etc/security/limits.conf一样就可以了
worker_rlimit_nofile 1000000
总结
以上就是笔者进行Nginx调优的一些经验,可以看出基本是围绕Nginx的Error日志展开的,之后又对一些比较大的性能瓶颈进行了一些改进。Nginx能够优化的地方非常多,本文只涉及到了其中很小的一些方面,但也足够满足我们的使用场景了。
参考链接 :
**更多nginx调优。**链接如下:http://blog.csdn.net/xifeijian/article/details/20956605
Nginx性能调优 https://www.jianshu.com/p/024b33d1a1a1
奇技指南!浅谈Nginx性能调优 : https://www.jianshu.com/p/845dc0e04d2a
上一篇: 郑子亹是怎么死的?他的盲目自大,更因为齐襄王的心胸狭隘
下一篇: 配置linux mint 19