Nginx Web服务器完全教程

教程简介

零基础Nginx Web服务器完全教程,涵盖虚拟主机、反向代理、负载均衡、HTTPS配置、缓存配置、日志管理、rewrite规则、安全配置、性能优化等核心技能,配有高可用网站架构实战项目。

Nginx Web 服务器完全教程

本教程面向零基础用户,从入门到实战,全面掌握 Nginx 的核心知识与技能。


目录

  1. Nginx 简介
  2. 安装 Nginx
  3. 基础配置与目录结构
  4. 虚拟主机配置
  5. 反向代理
  6. 负载均衡
  7. HTTPS 配置
  8. 缓存配置
  9. 日志管理
  10. Rewrite 规则
  11. 安全配置
  12. 性能优化
  13. 实战项目:高可用网站架构
  14. 常见问题与排错
  15. 附录:常用命令速查

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 从入门到生产部署的核心知识。以下是学习建议:

  1. 先动手:安装 Nginx,配置一个简单的静态网站
  2. 逐步进阶:依次尝试反向代理、HTTPS、负载均衡
  3. 多实践:在本地虚拟机中模拟多台服务器环境
  4. 读日志:遇到问题第一时间看错误日志
  5. 持续学习:关注 Nginx 官方文档和社区更新

Nginx 的功能远不止于此,还有流媒体服务、动态模块、Lua 脚本(OpenResty)等高级用法。掌握了本教程的基础后,可以进一步探索这些领域。

推荐阅读


本教程最后更新:2026年5月

内容声明

本文内容为AI技术学习教程,仅供学习参考。如涉及技术问题,欢迎通过 xurj005@163.com 与我们交流。

目录