Nginx调优
Nginx在部署服务时经常被用到, 大多时候是作为代理使用. 如果用户量比较大就涉及到一些调优, 本文做一些分类记录.
关于Nginx的基础信息见另一篇: Nginx基础
以下部分主要基于两个主要配置文件:nginx.conf和conf.d/default.conf展开.
Worker Processes
# 默认为1, 应更新为一个CPU核心一个worker
# 查看CPU核数 grep ^processor /proc/cpuinfo | wc -l
worker_processes auto;
# 文件句柄数,默认跟随系统设置
worker_rlimit_nofile 100000;
# 事件驱动部分
events {
# 每个worker允许的连接数, 默认512
worker_connections 65536;
use epoll;
multi_accept on;
}
文件访问优化
日志
- 访问日志使用缓冲或关闭
- 如果日志文件路径包含变量,需要打开open_log_file_cache以提高性能
access_log buffer=size flush=time
sendfile
三个选项都开启,意味着先填满包,再尽快发送.
- sendfile: 提供静态资源效率,直接在内核空间完成文件发送。
- tcp_nopush: 对应Linux的TCP_CORK,数据包会在累计到一定大小后再发送,提高网络效率。与sendfile on结合使用。
- tcp_nodelay: 另一个socket选项,禁用Nagle算法,尽快发送数据,某些情况节约200ms。Nginx只针对处于keepalive的TCP才启用。
http{
sendfile on;
tcp_nopush on;
tcp_nodelay on;
}
大文件下载
nginx处理文件传输,默认会在文件发送前先复制到buffer。sendfile允许文件句柄间的直接复制。
- sendfile_max_chunk: 默认为0,可能造成一直占用worker.
- aio : 使用异步文件传输线程池
location /mp3 {
sendfile on;
tcp_nopush on;
sendfile_max_chunk 512k;
aio threads;
}
# aio threads; 是一种简写,等价于:
# in the 'main' context
thread_pool default threads=32 max_queue=65536;
# in the 'http', 'server', or 'location' context
aio threads=default;
使用cache
# 缓存
http{
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=7d use_temp_path=off;
server{
location ~* \.(apk|png|jpe?g)$ {
proxy_cache my_cache;
}
}
}
其他(待测试)
# 待验证
open_file_cache max=1024 inactive=20s;
open_file_cache_valid 60s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
sendfile off; # 1. 效果不明显
# 2: CPU占用较高
sendfile on;
directio 10m;
# 3. nginx会把大文件写到磁盘临时文件,禁用cache
location / {
proxy_max_temp_file_size 0;
}
gzip压缩
多使用缓存和压缩, 但是图片不应该开启压缩.
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
连接数优化
Keepalive Connections
- client保活
- upstream保活 (后端服务需要支持keepalive)
http {
proxy_read_timeout 120; # 可选,默认和上游间60秒超时,适用于http, server, location
# 以下为upstream保活配置
upstream minio {
server 127.0.0.1:9000;
keepalive 32; # 每个worker缓存的最大keepalive空闲连接数(到upstream)
keepalive_requests 102400; # 可选,默认1000, 一个keep-alive服务的最大请求数,超出后关闭连接
keepalive_timeout 65; # 可选,默认60s
}
location / {
# client保活:以下必须设置, 默认响应后会关闭连接
proxy_http_version 1.1; # 默认 1.0
proxy_set_header Connection "";
proxy_pass http://minio;
}
}
解决 99: Cannot assign requested address 错误
访问返回502 bad gateway,从error.log可以看到类似错误:
failed (99: Cannot assign requested address) while connecting to upstream
解决方式1: 修改Linux内核参数,开启端口复用
# 开启TCP连接中TIME-WAIT sockets的快速回收
# 及时开启,永久保存需要保存到sysctl.conf
sysctl -w net.ipv4.tcp_tw_recycle=1
解决方式2: 开启nginx和上游的keepalive,参考上一节
限制资源访问
参考官方文档: Limiting Access to Proxied HTTP Resources
限制连接数 - limit_conn_zone
两种方式:
- 基于ip
- 基于server_name
limit_conn_zone $binary_remote_addr zone=addr:10m;
location /download/ {
limit_conn addr 1;
}
http {
limit_conn_zone $server_name zone=servers:10m;
server {
limit_conn servers 1000;
}
}
限制请求率(并发请求) - limit_req_zone
- limit_req_zone: 限制单位时间内的请求数,即速率限制,采用的漏桶算法 “leaky bucket”
- limit_req_conn: 限制同一时间连接数,即并发限制
http {
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
server {
location /search/ {
limit_req zone=one;
# 下面语句仅用于本地调试,超过的会记录日志
limit_req_dry_run on;
# 用于共享内存满时,增加突发队列,而不是直接返回503
limit_req zone=one burst=5;
}
}
}
限制带宽 - limit_rate
location /download/ {
limit_conn addr 1;
limit_rate 50k;
}
扩展阅读
官方文档
- 官方优化指南
- ngx_core_module / ngx_http_proxy_module / ngx_http_core_module
- Thread Pools in NGINX Boost Performance 9x!: 主要讲了aio的使用
- A Guide to Caching with NGINX: 缓存的用法
- Optimizing Performance for Serving Content:如何优化静态文件处理