Nginx

技术栈
工具链
反向代理负载均衡Web服务器代理网关

概览

Nginx

Nginx("engine-x")是 Igor Sysoev 于 2004 年创建的高性能 HTTP 和反向代理服务器,也是 IMAP/POP3 代理服务器。如今由 Nginx Inc. / F5 维护。

核心价值:处理高并发连接(C10K→C10M),作为反向代理、负载均衡器、静态资源服务器、API 网关。Apache 的轻量级替代。

关键特性

  • 事件驱动异步架构(epoll/kqueue),单机数万并发
  • 反向代理 + 七层/四层负载均衡
  • 静态文件服务、FastCGI/uWSGI 代理
  • 丰富的模块生态(限流、缓存、SSL、gRPC)
  • 热重载配置(零停机更新)

安装

1. 环境准备

  • 操作系统:Linux(推荐)、macOS、Windows(WSL或原生)
  • 端口:80(HTTP)、443(HTTPS)
  • 权限:绑定 1024 以下端口需要 root/sudo
  • 依赖:PCRE(正则)、zlib(Gzip)、OpenSSL(HTTPS)

2. 安装命令

Ubuntu / Debian

# 安装官方最新版本
sudo apt update
sudo apt install -y curl gnupg2 ca-certificates lsb-release debian-archive-keyring
curl -fsSL https://nginx.org/keys/nginx_signing.key | sudo gpg --dearmor -o /usr/share/keyrings/nginx.gpg
echo "deb [signed-by=/usr/share/keyrings/nginx.gpg] http://nginx.org/packages/ubuntu $(lsb_release -cs) nginx" | sudo tee /etc/apt/sources.list.d/nginx.list
sudo apt update
sudo apt install -y nginx
sudo systemctl start nginx

Docker 快速体验

# 简单静态服务器
docker run -d --name nginx -p 8080:80 nginx:alpine

# 挂载自定义配置
docker run -d --name nginx \
  -p 80:80 -p 443:443 \
  -v $(pwd)/nginx.conf:/etc/nginx/nginx.conf:ro \
  -v $(pwd)/html:/usr/share/nginx/html:ro \
  nginx:alpine

CentOS / RHEL

sudo yum install -y yum-utils
sudo tee /etc/yum.repos.d/nginx.repo <;<EOF
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/\$releasever/\$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
EOF
sudo yum install -y nginx
sudo systemctl start nginx

macOS

brew install nginx
brew services start nginx

3. 常见安装问题

问题 解决方案
80 端口被占用 lsof -i :80 检查 Apache/Caddy 等,停掉或改 Nginx 监听端口
[emerg] bind() failed 权限不足,用 sudo 启动或使用 1024+ 端口
配置语法错误 nginx -t 校验配置,输出具体错误行
SSL 证书路径不对 确认 ssl_certificatessl_certificate_key 指向正确文件
403 Forbidden 检查文件权限和 user 指令,确保 Nginx worker 有读权限

示例

Nginx 反向代理与负载均衡

目标

配置 Nginx 作为反向代理,将请求转发到多个后端服务,实现负载均衡。

完整配置

nginx.conf

# 主配置
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
    worker_connections 1024;
    use epoll;
}

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"';

    access_log /var/log/nginx/access.log main;

    sendfile on;
    tcp_nopush on;
    keepalive_timeout 65;
    gzip on;

    # ====== 负载均衡上游组 ======
    upstream backend {
        # 负载策略(默认轮询)
        # least_conn;  # 最少连接
        # ip_hash;     # 会话保持
        
        server 192.168.1.10:8080 weight=3 max_fails=3 fail_timeout=30s;
        server 192.168.1.11:8080 weight=1 backup;  # 备用节点
        server 192.168.1.12:8080 weight=2;
    }

    # ====== 反向代理服务 ======
    server {
        listen 80;
        server_name api.example.com;

        # 限流:每秒 10 个请求,突发 20
        limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
        limit_req zone=mylimit burst=20 nodelay;

        # 客户端请求体大小限制
        client_max_body_size 10m;

        location / {
            proxy_pass http://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_connect_timeout 5s;
            proxy_read_timeout 30s;
            proxy_send_timeout 30s;
            
            # 缓冲
            proxy_buffering on;
            proxy_buffer_size 4k;
            proxy_buffers 8 4k;
        }

        # 健康检查端点
        location /health {
            return 200 "OK\n";
            add_header Content-Type text/plain;
        }
    }

    # ====== HTTPS 服务 ======
    server {
        listen 443 ssl http2;
        server_name api.example.com;

        ssl_certificate /etc/nginx/certs/server.crt;
        ssl_certificate_key /etc/nginx/certs/server.key;
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers HIGH:!aNULL:!MD5;

        location / {
            proxy_pass http://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 https;
        }
    }
}

运行步骤

# 测试配置
nginx -t

# 重载配置(零停机)
nginx -s reload

# 验证
curl http://localhost/health
# 输出:OK

预期输出

多次 curl 请求会被轮询分发到不同后端。查看 access.log 可验证负载均衡效果。

教程

Nginx 入门教程:反向代理与 API 网关实践

1. Nginx 的角色定位

在现代架构中,Nginx 常作为:

  • 反向代理:隐藏后端服务细节,统一入口
  • API 网关:认证、限流、日志、路由
  • 静态资源服务器:直连比应用服务器快 10 倍+
  • SSL 终结:统一管理证书,后端用 HTTP
客户端 → [HTTPS] → Nginx → [HTTP] → 后端服务

2. 核心指令详解

proxy_pass

location /api/ {
    proxy_pass http://backend/;  # 带尾部斜杠:/api/users → /users
    proxy_pass http://backend;   # 不带斜杠:  /api/users → /api/users
}

upstream 负载策略

upstream backend {
    # 轮询(默认)
    server srv1:8080;
    server srv2:8080;

    # 加权轮询
    server srv1:8080 weight=3;
    server srv2:8080 weight=1;

    # IP Hash(会话保持)
    ip_hash;

    # 最少连接
    least_conn;

    # 一致性 Hash(适合缓存场景)
    hash $request_uri consistent;
}

3. 限流实战

# 请求频率限制
limit_req_zone $binary_remote_addr zone=per_ip:10m rate=10r/s;
limit_req zone=per_ip burst=20 nodelay;

# 连接数限制
limit_conn_zone $binary_remote_addr zone=per_ip_conn:10m;
limit_conn per_ip_conn 10;

# 下载速度限制
limit_rate 100k;
limit_rate_after 1m;

4. 缓存配置

proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m;
proxy_cache_key "$scheme$request_method$host$request_uri";

location /api/ {
    proxy_cache my_cache;
    proxy_cache_valid 200 10m;
    proxy_cache_valid 404 1m;
    proxy_cache_bypass $http_cache_control;  # 客户端可绕过缓存
}

5. 常见架构模式

模式一:前端 + API 同域

server {
    location / {
        root /var/www/frontend;  # 静态前端
    }
    location /api/ {
        proxy_pass http://backend;
    }
}

模式二:多服务路由

location /users/  { proxy_pass http://user-service; }
location /orders/ { proxy_pass http://order-service; }
location /payment/ { proxy_pass http://payment-service; }

6. 思考题

  1. 反向代理 vs 正向代理的区别?各解决什么问题?
  2. proxy_set_header X-Forwarded-For 有什么作用?
  3. Nginx 如何实现 WebSocket 代理?

参考资料

暂无参考文献