Nginx是现在最流行的Web服务器和反向代理服务器几乎每个网站每个项目都会用到它高性能高并发低资源消耗稳定可靠功能丰富能做Web服务器反向代理负载均衡邮件代理等等但是很多人对Nginx的使用只停留在默认配置或者简单的虚拟主机配置没有做性能调优结果Nginx的性能没有充分发挥出来高并发的时候可能会出现性能瓶颈。
我用Nginx很多年了做过很多性能调优踩了很多坑也总结了很多经验今天就来分享一下Nginx高性能配置的实战经验从入门到调优全面分享。
一、Nginx为什么高性能
在讲配置调优之前先说说Nginx为什么这么高性能这么高并发了解了原理才能更好地调优。
Nginx高性能的核心是它的事件驱动架构和异步非阻塞的IO模型。
传统的Web服务器比如Apache用的是多进程或者多线程模型每个请求分配一个进程或者线程处理这样当并发高的时候进程/线程数量很多内存占用大进程/线程切换开销大性能会下降。
而Nginx用的是多进程+事件驱动模型一个主进程(master)多个工作进程(worker)每个worker进程用事件驱动异步非阻塞的方式处理请求一个worker进程能同时处理几千甚至几万个请求因为它不是一个请求占一个线程而是用epoll(Linux)或者kqueue(BSD)等事件通知机制同时监听很多连接哪个连接有事件就处理哪个没有事件就不占用CPU这样资源消耗小并发高性能好。
简单来说Nginx高性能的原因:
- 事件驱动异步非阻塞IO: 一个进程能同时处理大量连接资源消耗小。
- 多进程模型: 充分利用多核CPU一个worker挂了不影响其他worker稳定性好。
- 内存占用小: 处理大量连接内存占用也很小因为不需要为每个连接分配独立的内存。
- 模块化设计: 功能模块化需要什么加载什么灵活高效。
- C语言编写: 底层C语言性能高执行效率高。
了解了这些原理我们就知道调优的方向主要是调整worker进程数量连接数事件模型缓冲区超时压缩缓存等等让Nginx充分发挥性能。
二、基础配置优化
先说说基础配置的优化主要是nginx.conf全局配置的一些参数。
1. worker_processes:
workerprocesses指定Nginx启动几个worker进程默认是1这显然不够因为现在的服务器都是多核CPU一个worker只能用一个核所以要根据CPU核心数设置workerprocesses。
一般设置为CPU核心数比如8核CPU就设置为8这样每个核一个worker充分利用多核CPU。
也可以设置为autoNginx会自动根据CPU核心数设置推荐用auto方便也准确。
worker_processes auto;2. workercpuaffinity:
workercpuaffinity用来把worker进程绑定到指定的CPU核心上避免进程在不同核心之间切换减少切换开销提升缓存命中率提升性能。
比如8核CPU8个worker可以这样绑定:
worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;这里每个worker对应一个8位的二进制哪一位是1就绑定到哪个核第一个worker绑定到第0核第二个绑定到第1核以此类推。
不过现在的Linux内核进程调度已经很智能了大部分情况不绑定也没问题但是高并发高性能的场景绑定一下还是有好处的。
3. workerrlimitnofile:
workerrlimitnofile指定每个worker进程能打开的最大文件描述符数Linux下一切皆文件连接也是文件描述符所以这个值决定了每个worker最多能处理多少连接。
默认这个值可能比较小比如1024高并发的时候不够会报错"too many open files"所以要调大。
一般设置为65535或者更大比如1048576但是也要和系统的ulimit配合系统的最大文件描述符数也要调大不然Nginx设置了也没用。
worker_rlimit_nofile 65535;系统层面要修改/etc/security/limits.conf设置:
* soft nofile 65535
* hard nofile 65535这样所有用户的最大文件描述符数都是65535。
4. use epoll:
events块里use指定Nginx用什么事件模型Linux下推荐用epoll这是Linux下最高效的事件通知机制高并发性能很好。
events {
use epoll;
}Nginx会自动选择最合适的事件模型Linux下默认就是epoll所以不设置也没问题但是显式设置一下更明确。
5. worker_connections:
worker_connections指定每个worker进程最大的并发连接数默认是1024高并发的时候不够要调大。
这个值和workerrlimitnofile配合不能超过workerrlimitnofile一般设置为和workerrlimitnofile一样或者稍小。
events {
worker_connections 65535;
}这样每个worker最多能处理65535个连接如果有8个worker那么总的最大连接数就是8 * 65535 = 524280很高了。
不过要注意这里的连接数包括和客户端的连接和和后端服务器的连接如果Nginx做反向代理那么一个客户端请求会占用两个连接(一个客户端连接一个后端连接)所以实际的并发请求数是连接数的一半。
6. multi_accept:
multi_accept指定Nginxworker进程一次能接受多个新连接默认是off一次只接受一个设置为on一次能接受多个高并发的时候能提升效率。
events {
multi_accept on;
}推荐开启高并发的时候有好处。
三、HTTP配置优化
接下来是http块的配置优化这部分和Web服务性能关系很大。
1. sendfile:
sendfile指定是否使用sendfile系统调用发送文件默认是onsendfile能直接把文件从磁盘发送到网络不需要先读到用户空间再写到内核空间减少数据拷贝提升性能特别是静态文件性能提升明显。
http {
sendfile on;
}一定要开启这是最基本的性能优化。
2. tcp_nopush:
tcp_nopush和sendfile配合开启后Nginx会在一个数据包里发送尽可能多的数据减少网络包的数量提升网络传输效率默认是off推荐开启和sendfile配合。
http {
sendfile on;
tcp_nopush on;
}3. tcp_nodelay:
tcp_nodelay指定是否禁用Nagle算法Nagle算法是为了减少小数据包提高网络效率但是对于实时性要求高的场景比如反向代理API接口会导致延迟所以要禁用Nagle算法让数据立即发送降低延迟。
http {
tcp_nodelay on;
}推荐开启特别是反向代理场景。
4. keepalive_timeout:
keepalive_timeout指定HTTP长连接的超时时间也就是客户端和Nginx之间的长连接保持多久默认是75s。
长连接能避免每次请求都重新建立TCP连接减少TCP握手的开销提升性能特别是HTTPS还能减少SSL握手的开销。
但是长连接也会占用连接资源超时时间太长会导致很多空闲连接占用连接数影响并发所以要合理设置。
一般设置为65s或者更短比如30s根据实际情况。
http {
keepalive_timeout 65;
}5. keepalive_requests:
keepalive_requests指定一个长连接最多能处理多少个请求默认是100超过就关闭连接重新建立。
这个值要合理设置太小会频繁建立连接开销大太大可能会有连接一直被占用影响其他用户一般设置为100-1000根据实际情况。
http {
keepalive_requests 100;
}6. clientheadertimeoutclientbodytimeout:
clientheadertimeout指定读取客户端请求头的超时时间clientbodytimeout指定读取客户端请求体的超时时间默认都是60s。
如果客户端太慢迟迟不发送请求头或者请求体会占用连接所以要设置合理的超时时间避免慢连接占用资源一般设置为10-30s。
http {
client_header_timeout 15;
client_body_timeout 15;
}7. send_timeout:
send_timeout指定Nginx向客户端发送数据的超时时间如果客户端迟迟不接收数据Nginx会关闭连接默认是60s一般设置为10-30s。
http {
send_timeout 15;
}8. clientmaxbody_size:
clientmaxbody_size指定客户端请求体的最大大小默认是1m也就是1MB如果用户上传大文件超过这个值会报错413 Request Entity Too Large。
如果网站有文件上传功能要根据需求调大这个值比如10m50m100m等等。
http {
client_max_body_size 10m;
}四、Gzip压缩优化
Gzip压缩能把响应数据压缩再发送给客户端减少传输的数据量提升页面加载速度节省带宽特别是文本类的内容比如HTMLCSSJSJSONXML压缩率很高能压缩60%-80%。
Nginx自带gzip模块能很方便地开启gzip压缩。
http {
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.1;
gzip_comp_level 6;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon;
gzip_vary on;
gzip_proxied any;
gzip_disable "MSIE [1-6]\.";
}解释一下各个参数:
- gzip on: 开启gzip压缩。
- gzipminlength 1k: 最小压缩大小小于1k的不压缩因为太小的压缩后可能反而更大而且压缩也有CPU开销。
- gzip_buffers 4 16k: 压缩缓冲区4个每个16k一般默认就行。
- gziphttpversion 1.1: 最低HTTP版本HTTP/1.1才压缩HTTP/1.0不压缩因为HTTP/1.0对gzip支持不好。
- gzipcomplevel 6: 压缩级别1-91最快压缩率最低9最慢压缩率最高一般设置为6平衡压缩率和CPU开销太高CPU开销大太低压缩率低。
- gzip_types: 指定哪些MIME类型要压缩文本类的都要压缩图片视频等二进制文件不要压缩因为已经压缩过了再压缩没效果还浪费CPU。
- gzip_vary on: 加上Vary: Accept-Encoding响应头告诉代理服务器根据Accept-Encoding缓存不同版本避免代理把压缩的内容发给不支持压缩的客户端。
- gzip_proxied any: 对代理的请求也压缩不管什么情况。
- gzip_disable "MSIE [1-6]\.": IE6及以下不压缩因为IE6对gzip支持不好有bug。
开启gzip能大大减少传输的数据量提升页面加载速度推荐一定要开启。
除了gzipNginx还支持brotli压缩brotli是Google开发的压缩算法比gzip压缩率更高但是需要额外安装模块有条件的可以开启brotli效果更好。
五、静态文件缓存优化
对于静态文件比如图片CSSJS字体等等变化不频繁可以设置浏览器缓存让浏览器缓存这些文件下次访问直接从浏览器缓存读取不用再请求服务器大大提升加载速度也减轻服务器压力。
Nginx通过expires指令设置缓存时间和Cache-Control响应头。
location ~* \.(jpg|jpeg|png|gif|ico|css|js|swf|flv|woff|woff2|ttf|eot|svg)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
access_log off;
}这里对图片CSSJS字体等静态文件设置缓存30天并且关闭访问日志因为静态文件访问量大写日志会影响性能也没必要记录。
不过要注意如果静态文件更新了浏览器还用的旧的缓存会有问题所以更新静态文件的时候最好改文件名比如加版本号或者hash比如style.abc123.css这样文件名变了浏览器就会重新请求新的文件不会用旧缓存。
另外对于HTML文件不要设置太长的缓存因为HTML经常变一般设置短一点或者不缓存避免用户看到旧的页面。
六、反向代理优化
如果Nginx做反向代理代理后端的应用服务器比如PHPNode.jsTomcat等等还有一些反向代理的优化。
1. proxyconnecttimeoutproxyreadtimeoutproxysendtimeout:
这三个分别是连接后端的超时时间读取后端响应的超时时间发送请求到后端的超时时间默认都是60s要根据后端的响应时间合理设置一般设置为30-60s不要太长避免慢请求占用连接。
http {
proxy_connect_timeout 30;
proxy_read_timeout 60;
proxy_send_timeout 30;
}2. proxybuffersizeproxybuffersproxybusybufferssize:
这些是代理缓冲区的设置Nginx会把后端的响应先读到缓冲区再发给客户端合理的缓冲区能提升性能减少磁盘IO。
http {
proxy_buffer_size 64k;
proxy_buffers 4 64k;
proxy_busy_buffers_size 128k;
}一般默认就行高并发大响应的场景可以适当调大。
3. proxynextupstream:
proxynextupstream指定当后端服务器出现什么情况时Nginx会把请求转发给下一个后端服务器提升可用性。
http {
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
}这样当后端连接错误超时返回500/502/503/504等错误时Nginx会自动把请求转发给下一个后端提升可用性用户感知不到后端故障。
4. 长连接到后端:
默认Nginx和后端之间是短连接每次请求都重新建立连接开销大可以配置Nginx和后端之间用长连接减少连接建立的开销。
upstream backend {
server 127.0.0.1:8080;
keepalive 32;
}
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
}这里upstream里keepalive 32指定每个worker和后端保持32个长连接然后location里设置proxyhttpversion 1.1和proxysetheader Connection ""这样Nginx和后端之间就用HTTP/1.1长连接减少连接建立的开销提升性能。
七、安全配置
除了性能优化安全配置也很重要简单说说几个常用的安全配置。
1. 隐藏Nginx版本号:
默认Nginx会在响应头和错误页显示版本号比如Server: nginx/1.18.0这会让攻击者知道你的Nginx版本从而利用对应版本的漏洞所以要隐藏版本号。
http {
server_tokens off;
}这样响应头里就只显示Server: nginx不显示版本号。
2. 禁止访问敏感文件:
对于一些敏感文件比如.env.git配置文件备份文件等等要禁止外部访问避免泄露敏感信息。
location ~ /\.(env|git|svn|hg|bzr|idea|vscode) {
deny all;
access_log off;
log_not_found off;
}
location ~* \.(sql|bak|conf|ini|log|sh|inc|yaml|yml)$ {
deny all;
access_log off;
log_not_found off;
}这样这些敏感文件外部就访问不了了返回403。
3. 限制请求方法:
一般网站只需要GETPOSTHEAD等请求方法其他的比如PUTDELETETRACEOPTIONS等等可能不需要可以禁止减少攻击面。
if ($request_method !~ ^(GET|POST|HEAD)$) {
return 405;
}这样除了GETPOSTHEAD其他请求方法都返回405不允许。
4. 防止DDOSCC攻击:
Nginx有一些模块能限制连接数和请求速率防止DDOSCC攻击比如limitconnzonelimitreqzone。
http {
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
}
server {
limit_conn conn_limit 20;
limit_req zone=req_limit burst=20 nodelay;
}这里limitconn限制每个IP最多20个连接limitreq限制每个IP每秒最多10个请求突发20个这样能一定程度上防止CC攻击当然真正的大流量DDOS还是需要专业的防护。
八、监控和日志
最后说说监控和日志要知道Nginx的运行状态性能有没有问题需要监控和日志。
1. stub_status状态页:
Nginx有stub_status模块能查看Nginx的运行状态比如活跃连接数接受的连接数处理的请求数等等方便监控。
location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}这样访问/nginx_status就能看到Nginx的状态只允许本机访问外部禁止。
2. 访问日志优化:
访问日志能记录每个请求的信息方便分析排查问题但是高并发的时候写日志会影响性能所以要合理配置。
可以设置日志格式包含需要的信息比如请求时间响应时间状态码字节数等等方便分析慢请求。
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'$request_time $upstream_response_time';
access_log /var/log/nginx/access.log main buffer=32k flush=5s;
}这里logformat定义了日志格式包含请求时间和上游响应时间accesslog设置了缓冲区32k每5秒刷一次盘减少磁盘IO提升性能。
对于静态文件访问量大可以关闭访问日志前面已经讲过了。
3. 错误日志:
错误日志记录Nginx的错误信息比如配置错误连接错误等等要开启级别一般设置为error或者warn不要设置为debug不然日志太多影响性能。
error_log /var/log/nginx/error.log error;九、写在最后
Nginx高性能配置实战:从入门到调优。
Nginx是一个非常强大高性能的Web服务器和反向代理服务器但是默认配置只是能用要充分发挥它的性能还需要根据实际情况做调优。
本文分享了Nginx的基础配置优化HTTP配置优化Gzip压缩静态文件缓存反向代理优化安全配置监控日志等等这些都是常用的有效的优化手段大部分场景都适用。
当然性能调优不是一蹴而就的也没有万能的配置要根据自己的服务器配置业务场景流量情况等等不断测试调整找到最适合自己的配置。
希望这篇分享能帮大家更好地使用Nginx调优Nginx让网站更快更稳。
最后用一句话结尾:
"性能调优没有最好只有更好要不断监控测试调整才能让系统一直保持最佳状态。"
祝大家都能把Nginx用得又快又稳!
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录