Nginx Web 服务器完全教程
本教程面向零基础用户,从入门到实战,全面掌握 Nginx 的核心知识与技能。
目录
- Nginx 简介
- 安装 Nginx
- 基础配置与目录结构
- 虚拟主机配置
- 反向代理
- 负载均衡
- HTTPS 配置
- 缓存配置
- 日志管理
- Rewrite 规则
- 安全配置
- 性能优化
- 实战项目:高可用网站架构
- 常见问题与排错
- 附录:常用命令速查
1. Nginx 简介
1.1 什么是 Nginx?
Nginx(发音为 "engine-x")是一款高性能的 HTTP 和反向代理服务器,由俄罗斯工程师 Igor Sysoev 于 2004 年首次发布。它以高并发、低内存消耗、高稳定性著称,是全球使用最广泛的 Web 服务器之一。
1.2 Nginx 的核心特性
| 特性 | 说明 |
|---|---|
| 事件驱动架构 | 采用异步非阻塞的事件驱动模型,单机可支持数万并发连接 |
| 反向代理 | 充当后端服务器的前端代理,隐藏后端架构 |
| 负载均衡 | 将请求分发到多台后端服务器,提升系统可用性 |
| 静态文件服务 | 高效处理静态资源(HTML、CSS、JS、图片等) |
| SSL/TLS 终端 | 处理 HTTPS 加密通信,减轻后端压力 |
| 缓存 | 缓存后端响应,加速页面加载 |
| 模块化设计 | 通过模块扩展功能,灵活可定制 |
1.3 Nginx vs Apache
| 对比项 | Nginx | Apache |
|---|---|---|
| 架构模型 | 事件驱动,异步非阻塞 | 进程/线程驱动 |
| 并发能力 | 极高(C10K+) | 中等 |
| 内存占用 | 低 | 较高 |
| 静态文件 | 极快 | 一般 |
| 动态内容 | 需配合后端 | 内置模块支持 |
| 配置风格 | 集中式配置 | 分布式 .htaccess |
| 学习曲线 | 中等 | 较低 |
1.4 Nginx 的应用场景
- Web 服务器:直接提供静态网站服务
- 反向代理:为 Node.js、Python、Java 等后端应用提供前端代理
- API 网关:统一管理微服务 API 入口
- 负载均衡器:分发流量到多台应用服务器
- 邮件代理:IMAP/POP3/SMTP 代理
- 流媒体服务器:提供视频/音频流服务
2. 安装 Nginx
2.1 Ubuntu / Debian 安装
# 更新软件源
sudo apt update
# 安装 Nginx
sudo apt install nginx -y
# 启动 Nginx
sudo systemctl start nginx
# 设置开机自启
sudo systemctl enable nginx
# 验证安装
nginx -v
2.2 CentOS / RHEL 安装
# 安装 EPEL 源(CentOS 7)
sudo yum install epel-release -y
# 安装 Nginx
sudo yum install nginx -y
# 启动 Nginx
sudo systemctl start nginx
# 设置开机自启
sudo systemctl enable nginx
# 验证安装
nginx -v
2.3 从源码编译安装
# 安装依赖
sudo apt install -y build-essential libpcre3 libpcre3-dev zlib1g zlib1g-dev \
libssl-dev libgd-dev
# 下载源码(以 1.26.x 为例,请到官网查看最新版本)
wget http://nginx.org/download/nginx-1.26.2.tar.gz
tar -zxvf nginx-1.26.2.tar.gz
cd nginx-1.26.2
# 配置编译选项
./configure \
--prefix=/etc/nginx \
--sbin-path=/usr/sbin/nginx \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--pid-path=/var/run/nginx.pid \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_gzip_static_module \
--with-http_stub_status_module
# 编译并安装
make -j$(nproc)
sudo make install
2.4 验证安装
安装完成后,在浏览器中访问服务器的 IP 地址,应看到 Nginx 的欢迎页面:
curl http://localhost
# 输出应包含: Welcome to nginx!
3. 基础配置与目录结构
3.1 目录结构
/etc/nginx/
├── nginx.conf # 主配置文件
├── conf.d/ # 自定义配置目录(推荐在此添加站点配置)
│ └── default.conf
├── sites-available/ # 可用站点配置(Ubuntu/Debian 风格)
├── sites-enabled/ # 已启用站点(通常为 sites-available 的软链接)
├── mime.types # MIME 类型映射
├── fastcgi_params # FastCGI 参数
└── modules-enabled/ # 动态模块配置
3.2 主配置文件结构
Nginx 的主配置文件 /etc/nginx/nginx.conf 采用层级结构:
# 全局块:影响 Nginx 整体运行
user www-data; # 运行用户
worker_processes auto; # 工作进程数,auto 表示自动检测 CPU 核心数
error_log /var/log/nginx/error.log warn; # 错误日志路径和级别
pid /var/run/nginx.pid; # PID 文件路径
# events 块:连接处理配置
events {
worker_connections 1024; # 单个 worker 最大连接数
use epoll; # Linux 下推荐使用 epoll
multi_accept on; # 允许同时接受多个连接
}
# http 块:HTTP 服务核心配置
http {
include /etc/nginx/mime.types; # 引入 MIME 类型
default_type application/octet-stream; # 默认 MIME 类型
# 日志格式定义
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
access_log /var/log/nginx/access.log main; # 访问日志
sendfile on; # 开启高效文件传输
tcp_nopush on; # 优化数据包发送
tcp_nodelay on; # 禁用 Nagle 算法
keepalive_timeout 65; # 长连接超时时间
types_hash_max_size 2048; # MIME 类型哈希表大小
gzip on; # 开启 Gzip 压缩
gzip_types text/plain text/css application/json application/javascript;
# 引入其他配置文件
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
3.3 配置指令详解
核心全局指令
# 工作进程数(建议设为 CPU 核心数)
worker_processes auto;
# 每个进程可打开的最大文件数(需配合系统 ulimit)
worker_rlimit_nofile 65535;
# 错误日志级别:debug | info | notice | warn | error | crit | alert | emerg
error_log /var/log/nginx/error.log warn;
events 块指令
events {
# 每个 worker 进程的最大并发连接数
# 总并发 = worker_processes × worker_connections
worker_connections 4096;
# 事件驱动模型(Linux 推荐 epoll,macOS 推荐 kqueue)
use epoll;
# 一次 accept 接受所有新连接
multi_accept on;
}
4. 虚拟主机配置
虚拟主机(Virtual Host)允许在一台服务器上托管多个网站,通过不同的域名或端口区分。
4.1 基于域名的虚拟主机
这是最常用的方式。为每个网站创建独立的配置文件:
站点 1:example.com
# /etc/nginx/conf.d/example.com.conf
server {
listen 80;
server_name example.com www.example.com; # 绑定域名
root /var/www/example.com; # 网站根目录
index index.html index.htm; # 默认首页文件
location / {
try_files $uri $uri/ =404; # 尝试查找文件,找不到返回 404
}
}
站点 2:blog.example.com
# /etc/nginx/conf.d/blog.example.com.conf
server {
listen 80;
server_name blog.example.com;
root /var/www/blog.example.com;
index index.php index.html;
# PHP 处理(配合 PHP-FPM)
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
}
}
创建网站目录并设置权限:
sudo mkdir -p /var/www/example.com /var/www/blog.example.com
sudo chown -R www-data:www-data /var/www/example.com /var/www/blog.example.com
4.2 基于端口的虚拟主机
# 站点 A:监听 8080 端口
server {
listen 8080;
server_name localhost;
root /var/www/site-a;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
# 站点 B:监听 8081 端口
server {
listen 8081;
server_name localhost;
root /var/www/site-b;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
4.3 默认服务器配置
当请求的域名没有匹配到任何虚拟主机时,会使用默认服务器:
server {
listen 80 default_server; # 设为默认服务器
server_name _; # 匹配所有未匹配的域名
return 444; # 直接关闭连接(不返回任何内容)
}
5. 反向代理
反向代理是 Nginx 最核心的应用之一,它接收客户端请求并转发给后端服务器,然后将响应返回给客户端。
5.1 基础反向代理
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://127.0.0.1:3000; # 转发到后端 Node.js 应用
# 传递客户端真实信息到后端
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
5.2 反向代理常用参数
server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://127.0.0.1:8080;
# 请求头设置
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
# 超时设置
proxy_connect_timeout 60s; # 连接后端超时
proxy_send_timeout 60s; # 发送请求超时
proxy_read_timeout 60s; # 读取响应超时
# 缓冲设置
proxy_buffering on; # 开启响应缓冲
proxy_buffer_size 4k; # 响应头缓冲区大小
proxy_buffers 8 4k; # 响应体缓冲区数量和大小
proxy_busy_buffers_size 8k; # 忙碌缓冲区大小
}
}
5.3 WebSocket 代理
# WebSocket 专用配置
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name ws.example.com;
location /ws/ {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_read_timeout 86400s; # WebSocket 长连接超时
proxy_send_timeout 86400s;
}
}
5.4 路径级反向代理
server {
listen 80;
server_name example.com;
# 前端静态页面
location / {
root /var/www/example.com;
try_files $uri $uri/ /index.html;
}
# API 请求代理到后端
location /api/ {
proxy_pass http://127.0.0.1:3000/; # 注意末尾的 /,会去掉 /api 前缀
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# 管理后台代理
location /admin/ {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
6. 负载均衡
负载均衡将客户端请求分发到多台后端服务器,提高系统可用性和处理能力。
6.1 定义后端服务器组
# 在 http 块中定义上游服务器组
upstream backend_servers {
server 192.168.1.10:8080; # 后端服务器 1
server 192.168.1.11:8080; # 后端服务器 2
server 192.168.1.12:8080; # 后端服务器 3
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend_servers; # 使用上游服务器组
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
6.2 负载均衡策略
轮询(Round Robin)— 默认策略
upstream backend {
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;
# 请求按顺序轮流分配
}
加权轮询(Weighted Round Robin)
upstream backend {
server 192.168.1.10:8080 weight=5; # 权重 5,接收更多请求
server 192.168.1.11:8080 weight=3; # 权重 3
server 192.168.1.12:8080 weight=2; # 权重 2
}
IP Hash — 同一客户端始终访问同一后端
upstream backend {
ip_hash;
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;
# 适用于需要会话保持的场景
}
最少连接(Least Connections)
upstream backend {
least_conn;
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;
# 优先将请求分配给当前连接数最少的服务器
}
6.3 服务器状态标记
upstream backend {
server 192.168.1.10:8080 weight=5;
server 192.168.1.11:8080 backup; # 备用服务器,主服务器全部不可用时启用
server 192.168.1.12:8080 down; # 标记为不可用,不参与负载均衡
server 192.168.1.13:8080 max_fails=3 fail_timeout=30s; # 失败 3 次后暂停 30 秒
}
6.4 健康检查
upstream backend {
server 192.168.1.10:8080 max_fails=3 fail_timeout=30s;
server 192.168.1.11:8080 max_fails=3 fail_timeout=30s;
# 保持长连接到后端
keepalive 32;
}
7. HTTPS 配置
7.1 SSL/TLS 基础
HTTPS = HTTP + TLS 加密。它通过数字证书验证服务器身份,并加密客户端与服务器之间的通信,防止数据被窃听或篡改。
7.2 使用 Let's Encrypt 免费证书(推荐)
# 安装 Certbot
sudo apt install certbot python3-certbot-nginx -y
# 自动获取并配置证书
sudo certbot --nginx -d example.com -d www.example.com
# 证书自动续期(Certbot 会自动设置定时任务)
sudo certbot renew --dry-run
7.3 手动配置 SSL 证书
server {
# 监听 443 端口,启用 SSL
listen 443 ssl http2;
server_name example.com www.example.com;
# 证书文件路径
ssl_certificate /etc/nginx/ssl/example.com.crt; # 证书(含中间证书链)
ssl_certificate_key /etc/nginx/ssl/example.com.key; # 私钥
# SSL 协议版本(禁用不安全的旧版本)
ssl_protocols TLSv1.2 TLSv1.3;
# 加密套件
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
# 优先使用服务器的加密套件
ssl_prefer_server_ciphers on;
# SSL 会话缓存
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
# OCSP Stapling(加速证书验证)
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/ssl/ca-bundle.crt;
resolver 8.8.8.8 8.8.4.4 valid=300s;
# HSTS(强制浏览器使用 HTTPS)
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
root /var/www/example.com;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
# HTTP 自动跳转 HTTPS
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
7.4 生成自签名证书(开发/测试用)
# 生成自签名证书(有效期 365 天)
sudo openssl req -x509 -nodes -days 365 \
-newkey rsa:2048 \
-keyout /etc/nginx/ssl/self-signed.key \
-out /etc/nginx/ssl/self-signed.crt \
-subj "/C=CN/ST=Beijing/L=Beijing/O=Dev/CN=localhost"
8. 缓存配置
8.1 代理缓存
缓存后端服务器的响应,减少后端压力,加速页面加载:
# 在 http 块中定义缓存区域
proxy_cache_path /var/cache/nginx levels=1:2
keys_zone=my_cache:10m # 缓存区名称和大小
max_size=10g # 缓存最大磁盘占用
inactive=60m # 60 分钟无访问则清除
use_temp_path=off; # 直接写入缓存目录,不使用临时目录
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
# 启用缓存
proxy_cache my_cache;
proxy_cache_valid 200 302 10m; # 200/302 响应缓存 10 分钟
proxy_cache_valid 404 1m; # 404 响应缓存 1 分钟
proxy_cache_valid any 5m; # 其他响应缓存 5 分钟
# 缓存锁(防止缓存击穿)
proxy_cache_lock on;
proxy_cache_lock_timeout 5s;
# 添加缓存状态头(调试用)
add_header X-Cache-Status $upstream_cache_status;
# 可能的值:MISS / HIT / EXPIRED / STALE / UPDATING / BYPASS
}
}
8.2 静态文件缓存
server {
listen 80;
server_name static.example.com;
root /var/www/static;
# 图片、字体等静态资源缓存 30 天
location ~* \.(jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public, immutable";
access_log off; # 静态资源可关闭访问日志减少 I/O
}
# CSS、JS 缓存 7 天
location ~* \.(css|js)$ {
expires 7d;
add_header Cache-Control "public";
access_log off;
}
# HTML 不缓存(保证实时性)
location ~* \.html$ {
expires -1;
add_header Cache-Control "no-store, no-cache, must-revalidate";
}
}
8.3 Gzip 压缩
http {
# 开启 Gzip 压缩
gzip on;
gzip_vary on; # 添加 Vary: Accept-Encoding 头
gzip_proxied any; # 对所有代理请求启用压缩
gzip_comp_level 4; # 压缩级别 1-9,推荐 4-6
gzip_min_length 256; # 小于 256 字节不压缩
gzip_types
text/plain
text/css
text/javascript
application/javascript
application/json
application/xml
application/xml+rss
image/svg+xml
font/woff2;
}
9. 日志管理
9.1 访问日志
# 自定义日志格式
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'rt=$request_time'; # 请求处理时间
# 应用日志格式
access_log /var/log/nginx/access.log main;
# 关闭特定 location 的日志(减少磁盘 I/O)
location /health {
access_log off;
return 200 "OK";
}
9.2 错误日志
# 错误日志路径和级别
error_log /var/log/nginx/error.log warn;
# 级别:debug < info < notice < warn < error < crit < alert < emerg
# 生产环境推荐 warn 或 error
9.3 按域名分离日志
server {
listen 80;
server_name example.com;
access_log /var/log/nginx/example.com/access.log main;
error_log /var/log/nginx/example.com/error.log warn;
}
9.4 日志切割
使用 logrotate 管理日志轮转:
# /etc/logrotate.d/nginx
/var/log/nginx/*.log {
daily # 每天轮转
missingok # 日志不存在时不报错
rotate 30 # 保留 30 天
compress # 压缩旧日志
delaycompress # 延迟一天压缩
notifempty # 空日志不轮转
create 0640 www-data adm # 新日志文件权限
sharedscripts
postrotate
[ -f /var/run/nginx.pid ] && kill -USR1 $(cat /var/run/nginx.pid)
endscript
}
9.5 JSON 格式日志(便于日志分析)
log_format json_log escape=json
'{'
'"time":"$time_iso8601",'
'"remote_addr":"$remote_addr",'
'"request":"$request",'
'"status":$status,'
'"body_bytes_sent":$body_bytes_sent,'
'"request_time":$request_time,'
'"http_referer":"$http_referer",'
'"http_user_agent":"$http_user_agent"'
'}';
access_log /var/log/nginx/access.json json_log;
10. Rewrite 规则
10.1 rewrite 指令
# 基本语法:rewrite 正则表达式 替换内容 [标记];
# 永久重定向(301)
rewrite ^/old-page$ /new-page permanent;
# 临时重定向(302)
rewrite ^/temp$ /other redirect;
# 内部重写(浏览器地址不变)
rewrite ^/download/(.*)$ /files/$1 last;
10.2 常用重写规则示例
server {
listen 80;
server_name example.com www.example.com;
# 强制带 www(裸域名重定向到 www)
if ($host = example.com) {
return 301 https://www.example.com$request_uri;
}
# 强制不带 www(www 重定向到裸域名)
# if ($host = www.example.com) {
# return 301 https://example.com$request_uri;
# }
# 去掉末尾斜杠(除了根路径)
rewrite ^/(.*)/$ /$1 permanent;
# 隐藏文件扩展名
location / {
try_files $uri $uri.html $uri/ =404;
}
}
10.3 if 条件判断
# 按浏览器类型处理
if ($http_user_agent ~* (bot|spider|crawler)) {
return 403;
}
# 按文件类型设置缓存
location ~* \.(jpg|png|css|js)$ {
if ($request_uri ~* "\.(jpg|png)$") {
expires 30d;
}
if ($request_uri ~* "\.(css|js)$") {
expires 7d;
}
}
注意:
if在 Nginx 中的行为比较特殊,容易产生意外结果。能用location匹配解决的问题,尽量不要用if。
10.4 location 匹配规则
Nginx 的 location 匹配有优先级,从高到低:
# 精确匹配(最高优先级)
location = /login {
# 只匹配 /login,不匹配 /login/ 或 /login/other
}
# 前缀匹配(停止搜索正则)
location ^~ /static/ {
# 匹配以 /static/ 开头的路径,不再检查正则
}
# 正则匹配(按配置文件中的顺序,第一个匹配的生效)
location ~* \.(jpg|png|gif)$ {
# 不区分大小写的正则匹配
}
# 普通前缀匹配
location /api/ {
# 匹配以 /api/ 开头的路径
}
# 通用匹配(最低优先级)
location / {
# 兜底匹配
}
匹配优先级:= > ^~ > ~* / ~ > 普通前缀 > /
11. 安全配置
11.1 隐藏版本号
http {
server_tokens off; # 隐藏响应头中的 Nginx 版本号
}
11.2 安全响应头
server {
listen 443 ssl http2;
server_name example.com;
# 防止点击劫持
add_header X-Frame-Options "SAMEORIGIN" always;
# 防止 MIME 类型嗅探
add_header X-Content-Type-Options "nosniff" always;
# XSS 保护
add_header X-XSS-Protection "1; mode=block" always;
# 引用策略
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# 内容安全策略(根据实际需求调整)
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:;" always;
# 权限策略
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
}
11.3 限制请求速率(防 DDoS / 暴力破解)
http {
# 定义请求速率限制区域
# 每个 IP 每秒最多 10 个请求,共享内存区域 10MB
limit_req_zone $binary_remote_addr zone=login_limit:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=30r/s;
# 连接数限制
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
}
server {
listen 443 ssl;
server_name example.com;
# 登录接口限流
location /api/login {
limit_req zone=login_limit burst=20 nodelay; # 允许突发 20 个请求
limit_req_status 429;
proxy_pass http://127.0.0.1:3000;
}
# API 全局限流
location /api/ {
limit_req zone=api_limit burst=50 nodelay;
limit_conn conn_limit 20; # 每个 IP 最多 20 个并发连接
proxy_pass http://127.0.0.1:3000;
}
}
11.4 IP 白名单与黑名单
# 在 http 块中定义
geo $blocked {
default 0;
192.168.1.100 1; # 封禁单个 IP
10.0.0.0/8 1; # 封禁整个网段
}
server {
listen 80;
server_name example.com;
if ($blocked) {
return 403;
}
# 或者使用 allow/deny 指令
location /admin/ {
allow 192.168.1.0/24; # 只允许内网访问
allow 10.0.0.0/8;
deny all;
proxy_pass http://127.0.0.1:8080;
}
}
11.5 目录浏览与敏感文件保护
server {
listen 80;
server_name example.com;
# 禁止目录浏览
autoindex off;
# 禁止访问隐藏文件(. 开头的文件)
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# 禁止访问备份文件
location ~* \.(bak|sql|log|conf|env)$ {
deny all;
access_log off;
log_not_found off;
}
}
11.6 基础认证(HTTP Basic Auth)
# 生成密码文件
sudo apt install apache2-utils -y
sudo htpasswd -c /etc/nginx/.htpasswd admin
# 输入密码两次
location /admin/ {
auth_basic "Restricted Area"; # 提示文字
auth_basic_user_file /etc/nginx/.htpasswd; # 密码文件
proxy_pass http://127.0.0.1:8080;
}
12. 性能优化
12.1 系统级优化
# 增加系统最大文件描述符数
# /etc/security/limits.conf
* soft nofile 65535
* hard nofile 65535
# 增加内核参数优化
# /etc/sysctl.conf
net.core.somaxconn = 65535
net.ipv4.tcp_max_tw_buckets = 65535
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
net.core.netdev_max_backlog = 65535
# 使配置生效
sudo sysctl -p
12.2 Nginx 工作进程优化
# 自动检测 CPU 核心数
worker_processes auto;
# 绑定 worker 到 CPU 核心(减少上下文切换)
worker_cpu_affinity auto;
# 每个 worker 的最大连接数
worker_rlimit_nofile 65535;
events {
worker_connections 16384;
use epoll;
multi_accept on;
}
12.3 缓冲区优化
http {
# 客户端请求体缓冲区
client_body_buffer_size 16k;
client_max_body_size 100m; # 最大上传文件大小
# 客户端请求头缓冲区
client_header_buffer_size 1k;
large_client_header_buffers 4 8k;
# 代理缓冲区
proxy_buffer_size 4k;
proxy_buffers 8 16k;
proxy_busy_buffers_size 32k;
}
12.4 静态文件优化
server {
listen 80;
server_name static.example.com;
root /var/www/static;
# 开启 sendfile(零拷贝传输)
sendfile on;
tcp_nopush on;
tcp_nodelay on;
# 静态文件缓存
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2|svg)$ {
expires 30d;
add_header Cache-Control "public, immutable";
access_log off;
}
# 文件 ETag(浏览器缓存验证)
etag on;
}
12.5 长连接优化
http {
# 客户端长连接
keepalive_timeout 65;
keepalive_requests 1000; # 单个连接最大请求数
# 代理长连接(需配合 upstream 的 keepalive)
proxy_http_version 1.1;
proxy_set_header Connection "";
}
upstream backend {
server 127.0.0.1:3000;
keepalive 64; # 保持 64 个长连接到后端
keepalive_requests 1000;
keepalive_timeout 60s;
}
13. 实战项目:高可用网站架构
下面我们将综合运用前面学到的知识,搭建一个生产级的高可用网站架构。
13.1 架构设计
┌─────────────────┐
│ CDN / DNS │
└────────┬────────┘
│
┌────────▼────────┐
│ Nginx (主节点) │ ← SSL 终端 + 反向代理 + 负载均衡
└────────┬────────┘
│
┌───────────────┼───────────────┐
│ │ │
┌────────▼───┐ ┌───────▼────┐ ┌───────▼────┐
│ App Server 1│ │App Server 2│ │App Server 3│
│ (Node.js) │ │ (Node.js) │ │ (Node.js) │
└────────┬────┘ └───────┬────┘ └───────┬────┘
│ │ │
└───────────────┼───────────────┘
│
┌────────▼────────┐
│ Redis / 数据库 │
└─────────────────┘
13.2 完整 Nginx 配置
# /etc/nginx/nginx.conf - 主配置
user www-data;
worker_processes auto;
worker_rlimit_nofile 65535;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 16384;
use epoll;
multi_accept on;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# 日志格式
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'rt=$request_time upstream=$upstream_addr '
'cache=$upstream_cache_status';
access_log /var/log/nginx/access.log main;
# 基础优化
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
keepalive_requests 1000;
types_hash_max_size 2048;
server_tokens off;
# 缓冲区
client_body_buffer_size 16k;
client_max_body_size 50m;
client_header_buffer_size 1k;
large_client_header_buffers 4 8k;
# Gzip
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 4;
gzip_min_length 256;
gzip_types text/plain text/css text/javascript application/javascript
application/json application/xml image/svg+xml font/woff2;
# 代理缓存
proxy_cache_path /var/cache/nginx/site_cache
levels=1:2 keys_zone=site_cache:20m
max_size=10g inactive=60m use_temp_path=off;
# 速率限制
limit_req_zone $binary_remote_addr zone=general:10m rate=30r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
# WebSocket 升级映射
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# 上游服务器组
upstream app_backend {
least_conn;
server 10.0.1.10:3000 weight=5 max_fails=3 fail_timeout=30s;
server 10.0.1.11:3000 weight=5 max_fails=3 fail_timeout=30s;
server 10.0.1.12:3000 weight=3 max_fails=3 fail_timeout=30s backup;
keepalive 64;
}
# 包含站点配置
include /etc/nginx/conf.d/*.conf;
}
13.3 站点配置
# /etc/nginx/conf.d/example.com.conf
# HTTP → HTTPS 重定向
server {
listen 80;
server_name example.com www.example.com;
return 301 https://example.com$request_uri;
}
# HTTPS 主站
server {
listen 443 ssl http2;
server_name example.com www.example.com;
# SSL 证书
ssl_certificate /etc/nginx/ssl/example.com.fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/example.com.privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
# 安全头
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# 日志
access_log /var/log/nginx/example.com/access.log main buffer=16k flush=5s;
error_log /var/log/nginx/example.com/error.log warn;
root /var/www/example.com;
index index.html;
# 全局限流
limit_req zone=general burst=60 nodelay;
limit_conn conn_limit 50;
# 静态资源
location ~* \.(jpg|jpeg|png|gif|ico|svg|css|js|woff2|woff|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public, immutable";
access_log off;
try_files $uri =404;
}
# API 代理
location /api/ {
proxy_pass http://app_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Connection "";
# 代理超时
proxy_connect_timeout 10s;
proxy_send_timeout 30s;
proxy_read_timeout 60s;
# 缓存 API 响应(仅 GET)
proxy_cache site_cache;
proxy_cache_valid 200 5m;
proxy_cache_valid 404 1m;
proxy_cache_methods GET HEAD;
proxy_cache_bypass $http_authorization;
add_header X-Cache-Status $upstream_cache_status;
}
# 登录接口限流
location /api/auth/login {
limit_req zone=login burst=10 nodelay;
proxy_pass http://app_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# WebSocket
location /ws/ {
proxy_pass http://app_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 86400s;
}
# 前端 SPA(单页应用)
location / {
try_files $uri $uri/ /index.html;
}
# 健康检查端点
location /health {
access_log off;
return 200 "OK\n";
add_header Content-Type text/plain;
}
# 禁止访问隐藏文件
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# 管理后台(IP 白名单)
location /admin/ {
allow 192.168.1.0/24;
allow 10.0.0.0/8;
deny all;
proxy_pass http://app_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# 自定义错误页
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
internal;
}
}
13.4 部署检查清单
# 1. 检查配置语法
sudo nginx -t
# 2. 重新加载配置(不中断服务)
sudo nginx -s reload
# 3. 验证 SSL 证书
openssl s_client -connect example.com:443 -servername example.com
# 4. 检查端口监听
sudo ss -tlnp | grep nginx
# 5. 查看错误日志
tail -f /var/log/nginx/error.log
# 6. 测试 HTTPS 安全评分(在线工具)
# 访问 https://www.ssllabs.com/ssltest/
14. 常见问题与排错
14.1 配置测试失败
# 查看详细错误信息
sudo nginx -t
# 输出类似:nginx: [emerg] unexpected "}" in /etc/nginx/conf.d/site.conf:25
# 根据提示修改对应文件的对应行
14.2 502 Bad Gateway
原因:Nginx 无法连接后端服务器。
# 检查后端是否运行
systemctl status your-app
# 检查端口是否正确
curl http://127.0.0.1:3000
# 检查防火墙
sudo ufw status
sudo iptables -L -n
14.3 413 Request Entity Too Large
# 增大客户端请求体大小限制
client_max_body_size 100m;
14.4 403 Forbidden
# 检查文件权限
ls -la /var/www/example.com/
# 确保 Nginx 用户有权访问
sudo chown -R www-data:www-data /var/www/example.com
sudo chmod -R 755 /var/www/example.com
# 检查是否有 index 文件
ls /var/www/example.com/index.html
14.5 端口被占用
# 查看 80 端口占用情况
sudo lsof -i :80
# 或
sudo ss -tlnp | grep :80
# 停止占用端口的服务(如 Apache)
sudo systemctl stop apache2
sudo systemctl disable apache2
14.6 权限问题
# 检查 Nginx 运行用户
ps aux | grep nginx
# 确认配置中的 user 指令
grep "^user" /etc/nginx/nginx.conf
# 修复目录权限
sudo chown -R www-data:www-data /var/www/
sudo find /var/www/ -type d -exec chmod 755 {} \;
sudo find /var/www/ -type f -exec chmod 644 {} \;
15. 附录:常用命令速查
服务管理
# 启动
sudo systemctl start nginx
# 停止
sudo systemctl stop nginx
# 重启
sudo systemctl restart nginx
# 重新加载配置(不中断服务,推荐)
sudo systemctl reload nginx
# 查看状态
sudo systemctl status nginx
# 开机自启
sudo systemctl enable nginx
# 取消开机自启
sudo systemctl disable nginx
配置操作
# 测试配置语法
sudo nginx -t
# 查看 Nginx 版本和编译参数
nginx -V
# 查看 Nginx 版本
nginx -v
# 发送信号(优雅停止)
nginx -s quit
# 快速停止
nginx -s stop
# 重新打开日志文件(日志切割后使用)
nginx -s reopen
日志查看
# 实时查看访问日志
tail -f /var/log/nginx/access.log
# 实时查看错误日志
tail -f /var/log/nginx/error.log
# 统计 HTTP 状态码分布
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
# 查看访问量最高的 IP
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
# 查看访问量最高的 URL
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
性能测试
# 使用 ab(Apache Bench)进行简单压力测试
ab -n 10000 -c 100 http://example.com/
# 使用 wrk 进行压力测试
wrk -t12 -c400 -d30s http://example.com/
# 查看 Nginx 连接状态(需开启 stub_status 模块)
# 配置:
# location /nginx_status {
# stub_status on;
# allow 127.0.0.1;
# deny all;
# }
curl http://localhost/nginx_status
结语
本教程涵盖了 Nginx 从入门到生产部署的核心知识。以下是学习建议:
- 先动手:安装 Nginx,配置一个简单的静态网站
- 逐步进阶:依次尝试反向代理、HTTPS、负载均衡
- 多实践:在本地虚拟机中模拟多台服务器环境
- 读日志:遇到问题第一时间看错误日志
- 持续学习:关注 Nginx 官方文档和社区更新
Nginx 的功能远不止于此,还有流媒体服务、动态模块、Lua 脚本(OpenResty)等高级用法。掌握了本教程的基础后,可以进一步探索这些领域。
推荐阅读:
本教程最后更新:2026年5月