nginx配置之性能篇
在高并发连接的情况下,Nginx是Apache服务器不错的替代品。Nginx同时也可以作为7层负载均衡服务器来使用。根据相关的测试结果,Nginx 0.7.14 + PHP 5.2.6 (FastCGI) 可以承受3万以上的并发连接数,相当于同等环境下Apache的10倍。
通常,4GB内存的服务器+Apache(prefork模式)一般只能处理3000个并发连接,因为它们将占用3GB以上的内存,还得为系统预留1GB的内存。
[TOC]
常规优化
events 优化
worker_connections
配置合理的最大连接数use epoll;
为 Linux 下多路复用IO接口select/poll的增强版本,它能显著减少程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。
events {
use epoll; # 事件处理模型优化,可以大大提高nginx性能
worker_connections 30000; # 指定单个后台worker process进程的最大并发连接数,默认512
multi_accept on; # 使nginx能尽快接收尽可能多的请求,减少客户端的连接初始化时间.
}
TCP 优化
- Nginx 关于 TCP 的优化基本都是修改系统内核提供的配置项,简单介绍如下:
http {
sendfile on; # 允许调用sendfile函数来高效传输静态文件,对于普通应用,必须设为on
tcp_nopush on; # 设置nginx在一个数据包里发送所有头文件,而不一个接一个的发送,可减少网络报文段的数量,只有在启用sendfile之后才生效
tcp_nodelay on; # 启用后会禁用nagle算法,设置nginx不要缓存数据,而是一段一段的尽快发送
keepalive_timeout 60; # 指定服务端为每个TCP连接最多可以保持多长时间,默认75秒
}
启用 gzip 压缩
- 通常,对于文本文件,在服务端发送响应之前进行 GZip 压缩,可减小到原来的 1/4 - 1/3
- 启用gzip压缩,使得返回客户端的内容更简短,传输更快,但启用压缩会消耗CPU资源,如果消耗CPU过高,可以考虑禁用压缩
- 通常只压缩大文件,避免压缩那些压缩效果不好的文件,例如图片、可执行文件等二进制文件
http {
gzip on; # 启用gzip压缩
gzip_static on; # 告诉nginx在压缩资源之前,先查找是否有预先gzip处理过的资源,如果有就不用再压缩了
gzip_vary on; # 开启自动输出"Vary: Accept-Encoding"响应头字段,可解决某些缓存服务问题
gzip_comp_level 6; # 数据的压缩等级,1-9,9是最慢但是压缩比最大的,默认1
gzip_buffers 16 8k; # 压缩缓冲区个数和大小,默认32 4k|16 8k;
gzip_proxied any; # 允许或者禁止压缩基于请求和响应的响应流,设置为any意味着将会压缩所有的请求.
gzip_min_length 1k; # 对数据启用压缩的最少字节数.如果一个请求小于1024字节,最好不要压缩它,因为压缩这些小的数据会降低处理此请求的所有进程的速度.
gzip_disable "msie6"; # 为指定的客户端禁用gzip功能,这里禁止IE6或者更低版本.或 gzip_disable "MSIE [1-6]\.";
gzip_http_version 1.1; # 针对 HTTP/1.1 及以上的请求开启 GZip
gzip_types
text/html text/css text/xml text/plain text/x-component text/javascript text/x-json
application/xml application/atom+xml application/rss+xml application/xhtml+xml image/svg+xml
application/javascript application/x-javascript
application/json application/x-web-app-manifest+json
application/x-font-ttf application/vnd.ms-fontobject
font/opentype image/x-icon; # 需要压缩的数据类型
}
开启客户端缓存
- 客户端缓存:最简单的办法是将所有的图片、js等静态内容设置一个固定的时间长度
http {
#.其他省略...
server {
#.其他省略...
location ~* \.(jpg|jpeg|gif|png|bmp|ico|css|js|xml)$ {
access_log off;
log_not_found off;
expires 30d; # 过期时间设置为30天,若静态文件不常更新则设大一点,若频繁更新则设小一点
}
}
}
设置超时时间
- 设置timeout可防御DOS攻击
http {
keepalive_timeout 60; # TCP长连接存活时间,默认75秒
client_header_timeout 10; # 设置请求头header的超时时间
client_body_timeout 10; # 设置请求体body的超时时间
send_timeout 600; # 指定客户端的响应超时时间
}
HTTPS 优化
- 启用 HTTPS 并正确配置了证书,意味着数据传输过程中无法被第三者解密或修改
http {
#.其他省略...
server {
listen 443 ssl;
server_name xxx.example.com;
root /data/nginx/www/xxx.example.com;
index index.html index.htm;
ssl_certificate /data/nginx/ssl/xxx.example.com.pem;
ssl_certificate_key /data/nginx/ssl/xxx.example.com.key;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 5m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
}
}
CPU 配置
- 设置CPU亲和性,将worker进程绑定在特定CPU内核上,减小进程切换内核的开销。
vi ./conf/nginx.conf
#.以8核为例
worker_processes 8; # 指定nginx提供web服务时的worder进程数,默认1
worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;
# 注:cpumask通常设置方法
# 2核是01 10
# 4核是0001 0010 0100 1000
# 8核是00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000
配置worker进程最大打开文件数
- 配置 nginx worker 进程最大打开文件数,相当于系统
ulimit -HSn
- 该参数不是越大越好,最好设为服务器承受的极限点
worker_rlimit_nofile 65535; # 指定单个工作进程可用文件描述符最大数量,建议等于ulimit -n,以避免"too many open files"问题
部署监控
- 修改 nginx.conf 添加 nginx-status 监控
http {
#.其他省略...
server {
#.其他省略...
location /nginx-status {
allow 127.0.0.1;
deny all;
stub_status on;
access_log off;
}
}
}
- 通过curl统计当前连接数
curl http://127.0.0.1:9002/nginx-status
进阶篇
优化 linux 内核
- 修改
/etc/sysctl.conf
配置如下参数,然后/sbin/sysctl -p /etc/sysctl.conf
使配置立即生效
net.ipv4.tcp_syncookies = 1 # 开启SYN Cookies,当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认0
net.ipv4.tcp_tw_reuse = 1 # 开启重用,允许将TIME-WAIT sockets重新用于新的TCP连接,默认0
net.ipv4.tcp_tw_recycle = 1 # 启用timewait快速回收,NAT环境建议设0禁用,linux4.12(centos7.9默认内核3.10.0)之后已废弃,默认0
net.ipv4.tcp_timestamps = 1 # 只有该参数启用,tcp_tw_reuse和tcp_tw_recycle开启才能生效,默认1
net.ipv4.tcp_fin_timeout = 1 # 当服务器主动关闭连接时,socket保持在FIN-WAIT-2状态的最大时间,默认60秒
net.ipv4.tcp_keepalive_time = 300 # 当keepalive启用时,TCP发送keepalive消息的频度,默认2小时
net.ipv4.tcp_max_tw_buckets = 5000 # 内核持有的状态为TIME_WAIT的最大数量,超出的TIME_WAIT连接会被立即销毁并打印警告,默认180000
net.ipv4.tcp_max_syn_backlog = 8192 # 调整SYN队列的长度,以容纳更多等待连接的网络连接数,默认1024
net.ipv4.ip_local_port_range = 1024 65535 # 允许系统打开的端口范围,默认32768到60999
net.core.somaxconn = 8192 # web应用中listen函数的backlog,默认128
net.core.netdev_max_backlog = 8192 # 网卡接收数据包的速率比内核处理的速率快时,允许送到队列的数据包的最大数目
需要注意如下几点:
- 关于 net.ipv4.tcp_tw_recycle,NAT环境建议设0禁用,且linux4.12(centos7.9默认内核3.10.0)之后已废弃
优化 fastcgi
- 优化fastcgi参数可以解决 nginx反向代理遇到的 504 Bad Gateway 错误
http {
fastcgi_connect_timeout 300; # 连接FastCGI超时秒数
fastcgi_send_timeout 300; # 向FastCGI传送请求超时秒数
fastcgi_read_timeout 300; # 接收FastCGI应答超时秒数
fastcgi_buffer_size 64k; # 读取FastCGI应答头的缓冲大小,默认4k
fastcgi_buffers 4 64k; # 读取FastCGI应答缓冲区个数和大小,默认4k
fastcgi_busy_buffers_size 128k; # 默认fastcgi_buffers的两倍
fastcgi_temp_file_write_size 128k; # 在写入fastcgi_temp_path 时将用多大的数据块,默认fastcgi_buffers的两倍
}
优化 php-fpm 参数
- 所谓动态网站,是指需要根据用户的请求数据实时计算出页面内容的网站,比如论坛、在线交易等
- PHP和Java是开发动态网站使用比较广泛的编程语言,相应的PHP-FPM和Tomcat则是这两种编程语言的运行环境。
- 修改 /etc/php-fpm.conf 中如下几个参数:
listen = 127.0.0.1:9000
pm = dynamic # php-fpm进程池开启进程的方式:static或dynamic
pm.max_children = 50 # 静态方式下开启的php-fpm进程数量,在动态方式下它限定php-fpm的最大进程数,默认32
pm.start_servers = 5 # 动态方式下的起始php-fpm进程数量
pm.min_spare_servers = 5 # 动态方式空闲状态下的最小php-fpm进程数量
pm.max_spare_servers = 100 # 动态方式空闲状态下的最大php-fpm进程数量
pm.max_requests = 10240 # 最大处理请求数,指定php-fpm的worker进程在处理多少个请求后就终止掉,避免第三方库造成的内存泄露,默认0
- php-fpm进程池开启进程有两种方式,一种是static,直接开启指定数量的php-fpm进程,不再增加或者减少;
- 另一种则是dynamic,开始时开启一定数量的php-fpm进程,当请求量变大时,动态的增加php-fpm进程数到上限,当空闲时自动释放空闲的进程数到一个下限。
- 如果dm设置为 static 则只有
pm.max_children
这个参数生效,系统会开启参数设置数量的php-fpm进程 - 如果dm设置为 dynamic 则4个参数都生效,系统会在php-fpm运行开始时启动
pm.start_servers
个php-fpm进程,然后根据系统的需求动态在pm.min_spare_servers
和pm.max_spare_servers
之间调整php-fpm进程数 - 通常,
max_children
必须大于max_spare_servers
,start_servers
必须大于min_spare_servers
优化 php 脚本超时时间
为了保证生产环境的安全,建议同时设置 max_execution_time
和 request_terminate_timeout
参数值:
- 修改 php.ini 中
max_execution_time = 60
(默认30s,若过大会导致php程序把FPM进程数耗尽) - 修改 /etc/php-fpm.conf 中
request_terminate_timeout = 60
- 执行
systemctl restart php-fpm
重启fpm进程以生效
优化 ulimit
- 设置 ulimit 系统最大打开的文件数量,注意执行
ulimit -n
则临时生效。
ulimit -SHn 65535
cat /etc/rc.local | grep ulimit || echo "ulimit -HSn 65535" >> /etc/rc.local
- 永久生效:修改
/etc/security/limits.conf
文件,在文件末尾添加如下4行(其中 * 代表针对所有用户,noproc 代表最大进程数,nofile 代表最大文件打开数)
* soft nofile 65535
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535
负载均衡
服务器负载均衡设备选型:
- 硬件设备:F5、Citrix、Redware、A10
- 软件:LVS、Nginx、Haproxy、zen loadbalance