第一次接触Nginx是在2013年,当时公司的一个老项目还在用Apache,每次遇到高并发就崩溃。技术主管扔给我一个Nginx的安装包说:"把这个搞明白,下周上线。"那七天我几乎没合眼,但从此彻底爱上了这个轻量级的高性能服务器。
Nginx之所以成为Web服务器学习的首选,核心在于它的"四高"特性:
新手常见误区:很多人以为Nginx只能做Web服务器,其实它还是反向代理、负载均衡、邮件代理的多面手。我经手过的项目中,80%的Nginx其实都在做反向代理。
Nginx的C10K问题解决方案堪称经典。传统Apache采用的prefork模式就像餐馆里每个顾客配一个服务员,而Nginx的epoll模型就像海底捞的智能呼叫系统:
nginx复制worker_processes auto; # 自动匹配CPU核心数
events {
worker_connections 1024; # 每个worker处理连接数
use epoll; # Linux内核的事件通知机制
}
实测数据:在2核4G的云服务器上,这个配置可以轻松应对5000+的并发连接。去年双十一大促时,我用这个配置支撑了某电商平台每秒2万次的商品详情页请求。
Nginx的配置文件像乐高积木,初学者往往被它的层次结构吓到。其实掌握这三个关键部分就成功了一半:
Main块:全局配置,好比公司的人力资源部
nginx复制user www-data; # 运行身份
pid /run/nginx.pid; # 进程ID文件位置
Events块:连接处理配置,相当于公司的客服中心
nginx复制events {
multi_accept on; # 同时接受多个新连接
accept_mutex off; # 高负载时关闭互斥锁
}
Http块:这才是业务主战场
nginx复制http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on; # 零拷贝技术关键配置
}
调试技巧:每次修改配置后,一定要执行
nginx -t测试语法。有次我漏了分号导致凌晨三点被报警叫醒,这个教训值千金。
新手常纠结安装方式,我的经验是:
apt/yum安装:bash复制# Ubuntu
sudo apt update && sudo apt install nginx
# CentOS
sudo yum install epel-release && sudo yum install nginx
bash复制wget http://nginx.org/download/nginx-1.25.3.tar.gz
tar zxvf nginx-1.25.3.tar.gz
cd nginx-1.25.3
./configure --prefix=/usr/local/nginx \
--with-http_ssl_module \
--with-http_realip_module
make && sudo make install
编译参数说明:
--with-http_stub_status_module 开启状态监控--with-http_gzip_static_module 支持预压缩文件--with-pcre 正则表达式支持隐藏版本信息:
nginx复制server_tokens off;
限制HTTP方法:
nginx复制if ($request_method !~ ^(GET|HEAD|POST)$ ) {
return 405;
}
防盗链配置:
nginx复制location ~* \.(jpg|png|gif)$ {
valid_referers none blocked yourdomain.com;
if ($invalid_referer) {
return 403;
}
}
SSL安全配置:
nginx复制ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers on;
这是Nginx的看家本领,配置示例:
nginx复制server {
listen 80;
server_name example.com;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
location ~* \.(js|css|png)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
}
关键点:
try_files 实现优雅降级expires 设置缓存时间add_header 添加安全相关头这是我用得最多的功能,对接Node.js的配置:
nginx复制upstream node_app {
server 127.0.0.1:3000;
server 127.0.0.1:3001 backup;
}
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://node_app;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
性能调优参数:
nginx复制proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 16k;
proxy_busy_buffers_size 32k;
Nginx支持多种负载均衡算法:
电商项目中的典型配置:
nginx复制upstream backend {
least_conn; # 最少连接算法
server 192.168.1.101:8080 weight=5;
server 192.168.1.102:8080;
server 192.168.1.103:8080 max_fails=3 fail_timeout=30s;
}
健康检查配置:
nginx复制check interval=3000 rise=2 fall=5 timeout=1000 type=http;
check_http_send "HEAD /health HTTP/1.0\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
nginx复制sendfile on; # 启用零拷贝技术
tcp_nopush on; # 仅在sendfile开启时有效
tcp_nodelay on; # 禁用Nagle算法
# 静态文件压缩
gzip on;
gzip_types text/plain text/css application/json;
gzip_min_length 1024;
nginx复制keepalive_timeout 65; # 长连接超时
keepalive_requests 100; # 单个连接最大请求数
client_header_timeout 15; # 请求头读取超时
client_body_timeout 15; # 请求体读取超时
send_timeout 25; # 响应发送超时
生产环境推荐日志分割:
bash复制# 按天切割日志
0 0 * * * /usr/sbin/logrotate -f /etc/logrotate.d/nginx
logrotate配置示例:
code复制/var/log/nginx/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 0640 www-data adm
sharedscripts
postrotate
/usr/bin/systemctl reload nginx > /dev/null
endscript
}
nginx复制location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
输出示例:
code复制Active connections: 291
server accepts handled requests
16630948 16630948 31070465
Reading: 6 Writing: 179 Waiting: 106
| 错误码 | 可能原因 | 解决方案 |
|---|---|---|
| 499 | 客户端提前关闭连接 | 检查后端响应时间 |
| 502 | 后端服务不可达 | 检查upstream配置 |
| 504 | 后端响应超时 | 调整proxy_read_timeout |
bash复制# 查看连接状态
ss -antp | grep nginx
# 性能分析
strace -p `cat /run/nginx.pid`
# 内存检查
pmap -x `pidof nginx` | tail -n 1
# 流量监控
iftop -nNP -i eth0
掌握基础后,建议按这个顺序深入:
推荐的三本进阶书籍:
最后分享一个我压箱底的技巧:在error_log中使用debug级别时,可以这样过滤日志:
bash复制tail -f /var/log/nginx/error.log | grep -E '\[debug\]|\[error\]'