大数跨境

一个合格运维,必须掌握的 Nginx 核心知识

一个合格运维,必须掌握的 Nginx 核心知识 红帽Linux认证
2026-07-02
2

一个合格运维,必须掌握的 Nginx 核心知识

一、问题背景

Nginx 几乎是每个互联网公司的接入层标配,但很多初中级运维的状态是:

  • 配置写得过且过,路径跳转、rewrite、HTTPS 全靠搜索引擎复制粘贴
  • 出了问题靠重启,重启无效就重启机器
  • accesslog 看不下去,errorlog 满屏 502/504 不知道从哪里开始
  • worker_cpu 100% 时不知道怎么定位
  • 500 个 502 是上游崩了还是 Nginx 自己拒了,根本分不清
  • 老板问“能不能扛住双 11”,心里没底

这一篇要解决的是“合格运维对 Nginx 应有的知识地图”。覆盖:架构、配置、模块、HTTPS、反向代理、负载均衡、限流、日志、调优、监控、高可用、平滑升级、典型排障,最后落到 6 套生产级配置示例。

写作目标:

  • 学完能独立写出生产级 nginx.conf
  • 能排 80% 的常见故障(502/504、worker CPU 高、连接打满、磁盘写满、慢响应)
  • 能调优到单 worker 5 万 QPS 量级
  • 能配合 Prometheus、Grafana 形成完整监控告警

二、适用场景

  • 静态资源(HTML、CSS、JS、图片、字体、音视频)服务
  • 反向代理 + 负载均衡(HTTP/1.1、HTTP/2、gRPC)
  • API 网关层限流、熔断、灰度
  • HTTPS 终止、证书自动续签(Let’s Encrypt、ACME)
  • WAF 与防 CC 攻击
  • 防盗链、防爬虫
  • 微服务入口(Spring Cloud Gateway、Kong、APISIX 之前)
  • 文件下载(大文件断点续传、Range)
  • WebSocket 反代
  • TCP/UDP 四层负载(stream 模块)
  • 与 Consul、etcd、Nacos 注册中心联动
  • 在 Kubernetes 中作为 Ingress Controller
  • CDN 回源
  • IPv6 接入

三、核心知识点

3.1 Nginx 架构

Nginx 是事件驱动的高性能 Web 服务器。核心模型是:

  • 一个 master 进程,负责加载配置、创建 worker、升级、平滑退出
  • 多个 worker 进程,处理实际的请求(默认与 CPU 核数相同)
  • 一个可选的 cache manager / cache loader 进程,处理磁盘缓存

worker 的几个关键点:

  • 每个 worker 是单线程,事件循环 + epoll(Linux)/ kqueue(BSD)
  • 多个 worker 之间互不抢连接,靠 OS 内核的 epoll accept 互斥锁(accept_mutex
  • 静态资源、HTTP 反代、stream 反代都共用同一个 worker
  • 一个 worker 默认能并行处理上万个连接(受限于 worker_connections

事件驱动模型的优点:

  • 没有线程上下文切换开销
  • 没有每个连接的内存占用(线程栈默认 1MB~8MB)
  • 内存占用稳定,不随并发线性增长

事件驱动模型的限制:

  • 不能在请求处理里跑 CPU 密集型阻塞调用
  • 不能直接访问阻塞型第三方库(需要异步库或线程池)

3.2 进程模型与信号

Nginx 用信号控制:

  • nginx -s stop
    :发 SIGTERM,优雅停止
  • nginx -s quit
    :发 SIGQUIT,worker 处理完所有连接再退出
  • nginx -s reload
    :发 SIGHUP,master 重新加载配置,旧 worker 处理完连接后退出
  • nginx -s reopen
    :发 SIGUSR1,重新打开日志(logrotate 配合使用)
  • kill -USR2 <master_pid>
    :热升级,新 master 启动
  • kill -WINCH <old_master_pid>
    :通知旧 master 关闭 worker

热升级流程:

  
  
  
bash
# 备份旧 binary
cp /usr/sbin/nginx /usr/sbin/nginx.old

# 用新 binary 替换
cp /usr/local/nginx/sbin/nginx /usr/sbin/nginx

# 触发热升级
kill -USR2 <old_master_pid>
# 新 master 启动,旧 master 改名为 .old,worker 也变 .old
# 旧 worker 继续处理现有连接,新 worker 接受新连接

# 等所有旧连接结束
kill -WINCH <old_master_pid>

# 关闭旧 master
kill -QUIT <old_master_pid>

# 如果新版本有问题,回滚
kill -HUP <old_master_pid>
# 新版本会平滑退出,回到旧版本处理

3.3 配置结构

Nginx 配置是层级化的,每段都有自己作用域:

  • main:userworker_processeserror_logpidworker_rlimit_nofile
  • events:worker_connectionsmulti_acceptuse
  • http:includedefault_typelog_formataccess_logsendfiletcp_nopushtcp_nodelaykeepalive_timeoutgzipupstream
  • server:listenserver_namerootlocationaccess_logerror_pagereturnrewrite
  • location:proxy_passtry_filesrootaliasindexlimit_reqauth_basic
  • upstream:serverip_hashleast_connkeepalivehealth_check

变量与执行顺序:

  • 变量以 $ 开头,例如 $remote_addr$http_user_agent$arg_name
  • 变量在 httpserverlocationifmapgeoset 中被赋值
  • 配置执行顺序:http → server → location → if,子级覆盖父级

3.4 模块体系

Nginx 模块分为:

  • 核心模块(Core):maineventshttp 等基础指令
  • HTTP 模块:http_corehttp_loghttp_gziphttp_sslhttp_proxyhttp_upstreamhttp_rewritehttp_limit_reqhttp_limit_connhttp_auth_requesthttp_secure_linkhttp_stub_statushttp_v2http_slice
  • Stream 模块(TCP/UDP):stream_corestream_proxystream_upstreamstream_sslstream_limit_connstream_log
  • 邮件模块(基本不用)

查看编译参数:

  
  
  
bash
nginx -V 2>&1 | tr' ''\n' | grep -E '^--'

第三方模块:

  • nginx-module-vts:实时流量监控
  • nginx-mod-http-geoip2:GeoIP
  • nginx-module-brotli:brotli 压缩
  • lua-nginx-module + OpenResty:嵌入 Lua
  • nginx-upsync-module:从 Consul/etcd 动态 upstream
  • nginx-jwt-module:JWT 校验

3.5 常用指令

  
  
  
nginx
user www www;
worker_processes auto;
worker_rlimit_nofile65535;
pid /var/run/nginx.pid;
error_log /var/log/nginx/error.log warn;

events {
    worker_connections10240;
    multi_accepton;
    useepoll;
}

http {
    include mime.types;
    default_type application/octet-stream;
    charset utf-8;
    server_tokensoff;
    client_max_body_size50m;
    client_body_buffer_size128k;
    client_header_buffer_size1k;
    large_client_header_buffers48k;
    sendfileon;
    tcp_nopushon;
    tcp_nodelayon;
    keepalive_timeout65;
    keepalive_requests1000;
    types_hash_max_size2048;
    server_names_hash_bucket_size128;
    proxy_http_version1.1;
    proxy_set_header Connection "";
    log_format main '$remote_addr - $remote_user [$time_local] '
                    '"$request$status$body_bytes_sent '
                    '"$http_referer" "$http_user_agent" '
                    'rt=$request_time uct="$upstream_connect_time" '
                    'urt="$upstream_response_time"';
    access_log /var/log/nginx/access.log main buffer=32k flush=5s;
    open_file_cache max=10240 inactive=20s;
    open_file_cache_valid30s;
    open_file_cache_min_uses2;
    open_file_cache_errorson;
    gzipon;
    gzip_min_length1k;
    gzip_comp_level5;
    gzip_types text/plain text/css application/json application/javascript application/xml;
    include /etc/nginx/conf.d/*.conf;
}

3.6 静态资源服务

  
  
  
nginx
server {
    listen80;
    server_name static.example.com;
    root /data/www/static;
    index index.html;

    location / {
        try_files$uri$uri/ =404;
    }

    location~* \.(jpg|jpeg|png|gif|webp|avif)$ {
        expires30d;
        add_header Cache-Control "public, immutable";
        access_logoff;
    }

    location~* \.(css|js)$ {
        expires7d;
        access_logoff;
    }

    location~* \.(mp4|webm|m4a)$ {
        mp4;
        mp4_buffer_size4m;
        mp4_max_buffer_size10m;
    }
}

关键指令:

  • try_files $uri $uri/ =404
    :依次尝试文件、目录、最后返回 404
  • expires 30d
    :浏览器缓存 30 天
  • mp4
    :启用 MP4 模块支持伪流
  • access_log off
    :关掉静态资源日志

3.7 反向代理与负载均衡

  
  
  
nginx
upstream backend {
    ip_hash;
    server10.0.0.1:8080 max_fails=3 fail_timeout=30s weight=1;
    server10.0.0.2:8080 max_fails=3 fail_timeout=30s weight=1;
    server10.0.0.3:8080 max_fails=3 fail_timeout=30s weight=1;
    keepalive64;
    keepalive_timeout60s;
    keepalive_requests1000;
}

server {
    listen80;
    server_name app.example.com;
    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_http_version1.1;
        proxy_set_header Connection "";
        proxy_connect_timeout5s;
        proxy_send_timeout30s;
        proxy_read_timeout30s;
        proxy_bufferingon;
        proxy_buffer_size16k;
        proxy_buffers832k;
        proxy_busy_buffers_size64k;
    }
}

负载均衡算法:

  • round-robin
    (默认):轮询
  • weight
    :权重
  • ip_hash
    :按 IP 哈希,固定上游
  • least_conn
    :最少连接
  • least_time
    :最少响应时间(商业版)
  • random
    :随机
  • hash $key consistent
    :一致性哈希
  • url_hash
    :按 URL 哈希(第三方模块)

健康检查:

  • 被动:max_failsfail_timeout
  • 主动:health_check(商业版)或 ngx_http_upstream_check_module(开源)

3.8 HTTPS 与 TLS

  
  
  
nginx
server {
    listen443 ssl http2;
    server_name secure.example.com;
    ssl_certificate /etc/nginx/ssl/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/privkey.pem;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout1d;
    ssl_session_ticketson;
    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_cipherson;
    ssl_dhparam /etc/nginx/ssl/dhparam.pem;
    add_header Strict-Transport-Security "max-age=63072000" always;
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";
    add_header X-XSS-Protection "1; mode=block";
}

证书自动续签(Let’s Encrypt):

  
  
  
bash
# 安装 certbot
apt install -y certbot python3-certbot-nginx

# 申请证书
certbot --nginx -d example.com -d www.example.com

# 自动续签(systemd timer)
systemctl enable certbot.timer
systemctl start certbot.timer

# 手动测试
certbot renew --dry-run

3.9 限流

3.9.1 limit_req_zone

  
  
  
nginx
http {
    limit_req_zone$binary_remote_addr zone=perip:10m rate=10r/s;
    limit_req_zone$server_name zone=perserver:10m rate=1000r/s;
    limit_req_zone$http_x_api_key zone=perkey:10m rate=100r/s;

    server {
        location /api/ {
            limit_req zone=perip burst=20 nodelay;
            limit_req_status429;
        }
    }
}

参数:

  • $binary_remote_addr
    :按 IP
  • $server_name
    :按 server
  • $http_x_api_key
    :按 API Key
  • rate=10r/s
    :每秒 10 个
  • burst=20
    :突发 20
  • nodelay
    :超过立即返回 429,不排队

3.9.2 limit_conn_zone

  
  
  
nginx
http {
    limit_conn_zone$binary_remote_addr zone=perip_conn:10m;
    server {
        location /download/ {
            limit_conn perip_conn 5;
            limit_conn_status503;
        }
    }
}

3.9.3 黑白名单

  
  
  
nginx
http {
    geo$blocked {
        default0;
        10.0.0.0/8 0;
        192.168.1.0/24 1;
        1.2.3.4 1;
    }

    map$http_user_agent$is_bot {
        default0;
        ~*bot1;
        ~*spider1;
        ~*crawler1;
    }

    server {
        if ($blocked) { return403; }
        if ($is_bot) { return403; }
    }
}

3.10 访问控制

  
  
  
nginx
location /admin/ {
    allow10.0.0.0/8;
    allow192.168.0.0/16;
    deny all;
    auth_basic"Admin Area";
    auth_basic_user_file /etc/nginx/.htpasswd;
}

location /api/ {
    auth_request /auth;
}

location = /auth {
    internal;
    proxy_pass http://auth-service/verify;
    proxy_set_header X-Original-URI $request_uri;
}

3.11 rewrite 与 return

  
  
  
nginx
# 强制 HTTPS
server {
    listen80;
    server_name example.com www.example.com;
    return301 https://$host$request_uri;
}

# 隐藏 .php 扩展
location / {
    rewrite ^/(.*)\.php$ /$1last;
}

# 旧 URL 跳转
location /old/path {
    return301 /new/path;
}

# 反盗链
location~* \.(jpg|png|gif)$ {
    valid_referersnoneblocked example.com *.example.com;
    if ($invalid_referer) {
        return403;
    }
}

return 与 rewrite 的区别:

  • return
     直接返回响应,不再处理后续指令
  • rewrite
     改写 URI 后重新匹配 location

3.12 日志

  
  
  
nginx
log_format json_combined escape=json
    '{'
        '"time":"$time_iso8601",'
        '"remote_addr":"$remote_addr",'
        '"request":"$request",'
        '"status":$status,'
        '"body_bytes_sent":$body_bytes_sent,'
        '"request_time":$request_time,'
        '"upstream_response_time":"$upstream_response_time",'
        '"upstream_addr":"$upstream_addr",'
        '"http_referer":"$http_referer",'
        '"http_user_agent":"$http_user_agent"'
    '}';

access_log /var/log/nginx/access.json json_combined buffer=64k flush=5s;

日志切割(logrotate):

  
  
  
bash
cat > /etc/logrotate.d/nginx <<'EOF'
/var/log/nginx/*.log {
    daily
    missingok
    rotate 30
    compress
    delaycompress
    notifempty
    create 0640 www-data adm
    sharedscripts
    prerotate
        if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
            run-parts /etc/logrotate.d/httpd-prerotate; \
        fi
    endscript
    postrotate
        [ -f /var/run/nginx.pid ] && kill -USR1 $(cat /var/run/nginx.pid)
    endscript
}
EOF

3.13 性能调优

关键参数:

  • worker_processes auto
    :与 CPU 核数相同
  • worker_rlimit_nofile 65535
    :单 worker 最大文件描述符
  • worker_connections 10240
    :单 worker 最大连接数
  • multi_accept on
    :一次 accept 多个连接
  • use epoll
    :使用 epoll
  • sendfile on
    :零拷贝发送文件
  • tcp_nopush on
    :合并小包
  • tcp_nodelay on
    :Nagle 算法关闭
  • keepalive_timeout 65
    :长连接保持
  • keepalive_requests 1000
    :单连接最大请求数
  • gzip on
    :开启 gzip
  • gzip_comp_level 5
    :压缩级别
  • open_file_cache
    :文件描述符缓存
  • worker_cpu_affinity
    :CPU 亲和性

CPU 亲和性:

  
  
  
nginx
worker_processes8;
worker_cpu_affinity0000000100000010000001000000100000010000001000000100000010000000;

3.14 健康检查

  
  
  
nginx
upstream backend {
    server10.0.0.1:8080 max_fails=3 fail_timeout=30s;
    server10.0.0.2:8080 max_fails=3 fail_timeout=30s;
    health_check interval=5s fails=3 passes=2 uri=/health;
}

max_fails=3:连续 3 次失败标记为 downfail_timeout=30s:30s 后重新探测health_check 是商业版功能,开源版用 ngx_http_upstream_check_module

3.15 高可用

3.15.1 keepalived + VIP

两台 Nginx 主备,VIP 在主机器上。

主:

  
  
  
nginx
vrrp_script chk_nginx {
    script"/usr/local/bin/check_nginx.sh"
    interval 2
    weight -20
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass SECRET
    }
    virtual_ipaddress {
        10.0.0.100/24
    }
    track_script {
        chk_nginx
    }
}

3.15.2 双 Nginx + DNS

主备 Nginx,DNS 解析到主;主故障时通过脚本切换 DNS(一般使用 api TTL 较短的方式)。

3.15.3 LVS + Nginx

LVS 四层负载,后端是多个 Nginx。

3.16 安全加固

  • 隐藏版本号:server_tokens off
  • 限制请求方法:limit_except GET POST { deny all; }
  • 防 CC:limit_req + limit_conn
  • IP 黑名单:geo 或 map
  • 防盗链:secure_link 或 valid_referers
  • 防扫描:map $http_user_agent + if
  • 限制请求体大小:client_max_body_size
  • 限制 Header 数量:large_client_header_buffers
  • 限制连接频率:limit_req

secure_link 防盗链:

  
  
  
nginx
location /download/ {
    secure_link$arg_md5,$arg_expires;
    secure_link_md5"SECRET$uri$arg_expires";
    if ($secure_link = "") { return403; }
    if ($secure_link = "0") { return410; }
    root /data/www;
}

3.17 平滑升级

  
  
  
bash
# 备份
cp /usr/sbin/nginx /usr/sbin/nginx.bak

# 编译新版本到不同目录
./configure --prefix=/usr/local/nginx-new
make
make install

# 用 nginx -V 拿到原编译参数再编译
nginx -V 2>&1 | grep configure

# 复制新 binary 替换
cp /usr/local/nginx-new/sbin/nginx /usr/sbin/nginx

# 触发热升级
kill -USR2 <master_pid>

# 等旧 worker 处理完
sleep 10
kill -WINCH <old_master_pid>

# 关掉旧 master
kill -QUIT <old_master_pid>

# 回滚
kill -HUP <old_master_pid>

四、整体排查或实施思路

4.1 故障排查主线

  • 第一步:拿到现象(响应码、耗时、错误页、客户端报错)
  • 第二步:看 Nginx errorlog
  • 第三步:看 accesslog 找异常请求
  • 第四步:看 nginx -V 编译参数和当前配置
  • 第五步:看 ss -snetstat -s 看连接数
  • 第六步:看上游日志
  • 第七步:看 CPU、内存、磁盘

4.2 部署优化主线

  • 第一步:环境假设(CPU、内存、QPS、并发、磁盘)
  • 第二步:编译参数与模块准备
  • 第三步:写 nginx.conf
  • 第四步:分批 reload 验证
  • 第五步:上线监控
  • 第六步:压测验证

五、实战步骤

5.1 安装 Nginx

5.1.1 包管理器(Debian/Ubuntu)

  
  
  
bash
apt update
apt install -y nginx
nginx -v
systemctl enable nginx
systemctl start nginx

5.1.2 包管理器(CentOS/RHEL)

  
  
  
bash
yum install -y epel-release
yum install -y nginx
systemctl enable nginx
systemctl start nginx

5.1.3 源码编译

  
  
  
bash
# 安装依赖
yum install -y gcc make pcre-devel zlib-devel openssl-devel

# 下载
wget http://nginx.org/download/nginx-1.24.0.tar.gz
tar zxf nginx-1.24.0.tar.gz
cd nginx-1.24.0

# 配置
./configure \
    --prefix=/usr/local/nginx \
    --user=www --group=www \
    --with-http_stub_status_module \
    --with-http_ssl_module \
    --with-http_v2_module \
    --with-http_gzip_static_module \
    --with-http_realip_module \
    --with-http_secure_link_module \
    --with-http_sub_module \
    --with-stream \
    --with-stream_ssl_module \
    --with-pcre \
    --with-pcre-jit \
    --add-module=/path/to/nginx-module-vts

# 编译安装
make -j$(nproc)
make install

# 添加 systemd 单元
cat > /etc/systemd/system/nginx.service <<'EOF'
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=network.target

[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable nginx
systemctl start nginx

5.2 配置文件组织

  
  
  
bash
# 推荐结构
/etc/nginx/
├── nginx.conf              # 主配置
├── mime.types
├── conf.d/                 # 业务 server
│   ├── default.conf
│   ├── api.conf
│   └── static.conf
├── snippets/               # 复用片段
│   ├── ssl-params.conf
│   ├── proxy-params.conf
│   └── security-headers.conf
├── ssl/                    # 证书
│   ├── example.com.crt
│   └── example.com.key
└── logrotate.d/
    └── nginx

主配置:

  
  
  
nginx
user www www;
worker_processes auto;
worker_rlimit_nofile65535;
pid /var/run/nginx.pid;
error_log /var/log/nginx/error.log warn;

events {
    worker_connections10240;
    multi_accepton;
    useepoll;
}

http {
    include mime.types;
    default_type application/octet-stream;
    charset utf-8;
    server_tokensoff;
    sendfileon;
    tcp_nopushon;
    tcp_nodelayon;
    keepalive_timeout65;
    keepalive_requests1000;
    client_max_body_size50m;
    client_body_buffer_size128k;
    client_header_buffer_size1k;
    large_client_header_buffers48k;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

5.3 配置 HTTPS 站点

操作目的:让一个域名支持 HTTPS。

步骤:

  
  
  
bash
# 申请证书
certbot certonly --webroot -w /var/www/html -d example.com -d www.example.com
# 证书位置
ls -la /etc/letsencrypt/live/example.com/
# fullchain.pem privkey.pem

/etc/nginx/conf.d/example.com.conf

  
  
  
nginx
server {
    listen80;
    server_name example.com www.example.com;
    return301 https://$host$request_uri;
}

server {
    listen443 ssl http2;
    server_name example.com www.example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    include /etc/nginx/snippets/ssl-params.conf;

    root /var/www/example.com;
    index index.html;

    location / {
        try_files$uri$uri/ =404;
    }
}

/etc/nginx/snippets/ssl-params.conf

  
  
  
nginx
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_cipherson;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout1d;
ssl_session_ticketson;
ssl_staplingon;
ssl_stapling_verifyon;
resolver1.1.1.18.8.8.8 valid=300s;
resolver_timeout5s;
add_header Strict-Transport-Security "max-age=63072000" 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 "no-referrer-when-downgrade" always;

生效:

  
  
  
bash
nginx -t
systemctl reload nginx

验证:

  
  
  
bash
curl -vI https://example.com
nmap --script ssl-enum-ciphers -p 443 example.com
openssl s_client -connect example.com:443 -servername example.com </dev/null

5.4 反向代理 + 负载均衡

  
  
  
nginx
upstream backend {
    least_conn;
    server10.0.0.1:8080 max_fails=3 fail_timeout=30s;
    server10.0.0.2:8080 max_fails=3 fail_timeout=30s;
    server10.0.0.3:8080 max_fails=3 fail_timeout=30s;
    keepalive64;
    keepalive_timeout60s;
}

server {
    listen80;
    server_name api.example.com;
    access_log /var/log/nginx/api.example.com.access.log main;

    location / {
        proxy_pass http://backend;
        include /etc/nginx/snippets/proxy-params.conf;
    }

    location /api/v1/health {
        access_logoff;
        return200'{"status":"ok"}';
        add_header Content-Type application/json;
    }
}

/etc/nginx/snippets/proxy-params.conf

  
  
  
nginx
proxy_http_version1.1;
proxy_set_header Connection "";
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_timeout5s;
proxy_send_timeout30s;
proxy_read_timeout30s;
proxy_bufferingon;
proxy_buffer_size16k;
proxy_buffers832k;
proxy_busy_buffers_size64k;
proxy_next_upstreamerror timeout http_502 http_503 http_504;
proxy_next_upstream_tries3;
proxy_next_upstream_timeout10s;

5.5 限流实战

5.5.1 全局 IP 限流

  
  
  
nginx
http {
    limit_req_zone$binary_remote_addr zone=global:10m rate=100r/s;
    server {
        location / {
            limit_req zone=global burst=200 nodelay;
            limit_req_status429;
        }
    }
}

5.5.2 登录接口防撞库

  
  
  
nginx
http {
    limit_req_zone$binary_remote_addr zone=login:10m rate=5r/m;
    server {
        location /api/login {
            limit_req zone=login burst=3 nodelay;
            proxy_pass http://backend;
        }
    }
}

5.5.3 业务 API 区分用户等级

  
  
  
nginx
http {
    limit_req_zone$http_x_api_key zone=apikey:10m rate=1000r/s;
    limit_req_zone$arg_token zone=token:10m rate=10r/s;

    server {
        location /api/ {
            if ($http_x_api_key) {
                set$limit_zone apikey;
            }
            if ($arg_token) {
                set$limit_zone token;
            }
            limit_req zone=$limit_zone burst=20 nodelay;
        }
    }
}

5.6 大文件下载与限速

  
  
  
nginx
server {
    listen80;
    server_name files.example.com;
    root /data/files;
    access_log /var/log/nginx/files.access.log;

    location / {
        limit_rate10m;            # 单连接 10MB/s
        limit_rate_after10m;      # 头 10MB 不限速
        limit_conn perip 2;        # 单 IP 最多 2 个连接
        limit_conn perserver 1000# 服务器总连接 1000
    }
}

5.7 WebSocket 反代

  
  
  
nginx
upstream websocket {
    server10.0.0.1:8081;
    server10.0.0.2:8081;
}

server {
    listen80;
    server_name ws.example.com;

    location / {
        proxy_pass http://websocket;
        proxy_http_version1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_read_timeout600s;       # 长连接超时
        proxy_send_timeout600s;
    }
}

5.8 gRPC 反代

  
  
  
nginx
upstream grpc_backend {
    server10.0.0.1:50051;
    server10.0.0.2:50051;
    keepalive32;
}

server {
    listen443 ssl http2;
    server_name grpc.example.com;
    ssl_certificate /etc/nginx/ssl/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/privkey.pem;

    location / {
        grpc_pass grpc://grpc_backend;
        grpc_set_header Host $host;
        grpc_connect_timeout5s;
    }
}

5.9 TCP/UDP 四层负载

  
  
  
nginx
stream {
    upstream mysql_backend {
        server10.0.0.1:3306 max_fails=3 fail_timeout=30s;
        server10.0.0.2:3306 max_fails=3 fail_timeout=30s;
    }

    server {
        listen3306;
        proxy_pass mysql_backend;
        proxy_connect_timeout5s;
        proxy_timeout600s;
    }

    upstream dns_backend {
        server8.8.8.8:53;
        server1.1.1.1:53;
    }

    server {
        listen53 udp;
        proxy_pass dns_backend;
    }
}

5.10 启用 stub_status

  
  
  
nginx
server {
    listen127.0.0.1:80;
    server_name127.0.0.1;
    location /nginx_status {
        stub_statuson;
        access_logoff;
        allow127.0.0.1;
        deny all;
    }
}

查看:

  
  
  
bash
curl http://127.0.0.1/nginx_status
# Active connections: 291
# server accepts handled requests
#  16630948 16630948 31070465
# Reading: 6 Writing: 179 Waiting: 106

Reading + Writing + Waiting 之和应小于 worker_connections * worker_processes

5.11 启用 vts 模块

  
  
  
nginx
http {
    vhost_traffic_status_zone;
    vhost_traffic_status_filter_by_hoston;
    vhost_traffic_status_filter_by_upstreamon;
    server {
        location /status {
            vhost_traffic_status_display;
            vhost_traffic_status_display_format html;
            allow127.0.0.1;
            deny all;
        }
    }
}

5.12 Prometheus 监控

使用 nginx_exporter 或 nginx-prometheus-exporter

  
  
  
bash
# 启动 nginx-prometheus-exporter
nginx-prometheus-exporter -nginx.scrape-uri=http://127.0.0.1:80/nginx_status -web.listen-address=:9113

或使用 nginxinc/nginx-prometheus-exporter,配合 vts 模块。

Prometheus 配置:

  
  
  
yaml
scrape_configs:
  -job_name:nginx
    static_configs:
      -targets: ['nginx-host:9113']
    scrape_interval:15s

5.13 排障:worker_cpu 100%

现象:worker 进程 CPU 100%。

初步判断:某个请求在 worker 里死循环或密集计算。

命令:

  
  
  
bash
# 查进程
top -H -p <nginx_pid>
# 找到 CPU 最高的线程 ID(十进制)

# 转十六进制
printf'%x\n' <tid>

# 看 perf
perf top -p <nginx_pid>

# 看 strace
strace -p <nginx_pid>

# 看 nginx 错误日志
tail -f /var/log/nginx/error.log

可能原因:

  • 反代上游慢,但上游没死,导致大量连接堆积
  • try_files
     配合 deep nested 目录
  • gzip
     大文件
  • Lua 代码死循环(OpenResty)

修复:

  • 上游限流、加超时
  • 减少 gzip 启用范围
  • 替换为异步框架

5.14 排障:大量 502/504

现象:accesslog 502/504 突增。

初步判断:Nginx 连不上后端或后端响应超时。

命令:

  
  
  
bash
# 查后端状态
curl -v http://10.0.0.1:8080/health

# 看 nginx errorlog
tail -f /var/log/nginx/error.log
# 关键关键字:connect() failed (110: Connection timed out)
# upstream prematurely closed connection
# no live upstreams

# 看后端日志
ssh 10.0.0.1 'tail -n 200 -f /var/log/app/app.log'

# 看后端进程
ssh 10.0.0.1 'ps -ef | grep -E "java|node|python" | grep -v grep'

可能原因:

  • 后端 OOM、重启中
  • 后端慢导致超时
  • 后端连接池满
  • 网络丢包

修复:

  • 加超时、加重试
  • 后端扩容
  • 检查网络

5.15 排障:磁盘写满

现象:df -h 看到 /var/log/nginx 占满。

命令:

  
  
  
bash
du -sh /var/log/nginx
ls -la /var/log/nginx/

可能原因:

  • accesslog 太大
  • errorlog 持续报错
  • 没有 logrotate

修复:

  • 临时:truncate -s 0 /var/log/nginx/access.log; nginx -s reopen
  • 长期:logrotate + 定期归档

5.16 排障:连接打满

现象:ss -s 显示 ESTABLISHED 几十万个。

命令:

  
  
  
bash
ss -s
ss -tan 'sport = :80' | awk '{print $6}' | sort | uniq -c
# 看每个 IP 的连接数
ss -tan 'sport = :80' | awk 'NR>1 {print $6}' | sort | uniq -c | sort -nr | head

可能原因:

  • 客户端未关闭长连接
  • 爬虫 / 攻击
  • keepalive_timeout
     设得太大

修复:

  • 减 keepalive_timeout
  • 减 keepalive_requests
  • 单 IP 限流
  • IP 黑名单

5.17 平滑升级

操作目的:升级 Nginx 到新版本而不中断服务。

  
  
  
bash
# 1. 备份
cp /usr/sbin/nginx /usr/sbin/nginx.bak

# 2. 编译新版本到临时目录
./configure --prefix=/tmp/nginx-new [options]
make
# 注意:不要 make install

# 3. 复制新 binary
cp /tmp/nginx-new/objs/nginx /usr/sbin/nginx.new

# 4. 替换
cp /usr/sbin/nginx.new /usr/sbin/nginx

# 5. 触发热升级
kill -USR2 $(cat /var/run/nginx.pid)

# 6. 等待
sleep 10

# 7. 优雅关闭旧 worker
kill -WINCH $(cat /var/run/nginx.pid.oldbin)

# 8. 关掉旧 master
kill -QUIT $(cat /var/run/nginx.pid.oldbin)

# 9. 验证
nginx -v
ps -ef | grep nginx

5.18 回滚配置

  
  
  
bash
# 改之前先备份
cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak.$(date +%Y%m%d_%H%M%S)

# 验证
nginx -t

# reload
nginx -s reload

# 出问题立刻回滚
cp /etc/nginx/nginx.conf.bak.YYYYMMDD_HHMMSS /etc/nginx/nginx.conf
nginx -t
nginx -s reload

5.19 WAF 集成

5.19.1 与 ModSecurity 集成

  
  
  
bash
# 编译
./configure --add-module=/path/to/ModSecurity-nginx
make
make install
  
  
  
nginx
modsecurityon;
modsecurity_rules_file /etc/nginx/modsec/main.conf;

5.19.2 与云 WAF

通过 DNS 切换或 IP 回源切换到云 WAF。

5.19.3 自定义 WAF

  
  
  
nginx
location / {
    if ($request_method !~ ^(GET|POST|HEAD)$) { return405; }
    if ($http_user_agent~* (sqlmap|nikto|acunetix|nmap)) { return403; }
    if ($query_string~* union.*select) { return403; }
    if ($http_cookie~* "(\.\./|\.\.\\)") { return403; }
}

5.20 Kubernetes Ingress

使用 nginx-ingress-controller

  
  
  
bash
# 安装
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm install ingress-nginx ingress-nginx/ingress-nginx

Ingress 资源:

  
  
  
yaml
apiVersion:networking.k8s.io/v1
kind:Ingress
metadata:
name:api
annotations:
    nginx.ingress.kubernetes.io/proxy-body-size:"50m"
    nginx.ingress.kubernetes.io/rate-limit:"100"
    nginx.ingress.kubernetes.io/rate-limit-window:"1m"
    nginx.ingress.kubernetes.io/limit-rps:"10"
spec:
ingressClassName:nginx
tls:
    -hosts:
        -api.example.com
      secretName:example-tls
rules:
    -host:api.example.com
      http:
        paths:
          -path:/
            pathType:Prefix
            backend:
              service:
                name:api-service
                port:
                  number:80

六、常用命令

6.1 启动与停止

  
  
  
bash
nginx                    # 启动
nginx -t                 # 测试配置
nginx -T                 # 测试并打印完整配置
nginx -s reload          # 重新加载配置
nginx -s reopen          # 重新打开日志
nginx -s stop            # 停止(SIGTERM)
nginx -s quit            # 优雅停止(SIGQUIT)
nginx -V                 # 编译信息
nginx -v                 # 版本
nginx -h                 # 帮助

6.2 进程与端口

  
  
  
bash
ps -ef | grep nginx
pgrep -af nginx
ss -tlnp | grep -E ':80|:443'
lsof -i :80

6.3 配置检查

  
  
  
bash
# 测试配置
nginx -t
nginx -t -c /etc/nginx/nginx.conf

# 查看最终生效配置
nginx -T | less

# 格式化输出
nginx -T 2>&1 | grep -E '^\s*#' | grep -v '^\s*#\s*$' | head -20

6.4 性能压测

  
  
  
bash
# ab
ab -n 1000 -c 100 http://example.com/
ab -k -n 10000 -c 200 -H 'Connection: keep-alive' https://example.com/

# wrk
wrk -t4 -c200 -d30s http://example.com/
wrk -t4 -c200 -d30s -H 'Host: example.com' https://example.com/

# hey
hey -n 5000 -c 200 http://example.com/

# vegeta
echo"GET http://example.com/" | vegeta attack -duration=30s -rate=1000 | vegeta report -type=hist[0,50ms,100ms,200ms,500ms,1s,2s,5s]

# 自带 stub_status
curl http://127.0.0.1/nginx_status

6.5 日志分析

  
  
  
bash
# 状态码分布
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -nr

# 耗时 Top 20
awk '{print $NF, $0}' /var/log/nginx/access.log | sort -nr | head -20

# 5xx 错误
awk '$9 ~ /^5/' /var/log/nginx/access.log

# 客户端 IP 分布
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head

# UA 分布
awk -F'"''{print $6}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head

# URL Top 20
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -20

# 实时观察
tail -f /var/log/nginx/access.log | awk '{print $1, $9, $7, $NF}'

6.6 故障定位

  
  
  
bash
# 看错误日志
tail -f /var/log/nginx/error.log

# 看连接
ss -tan 'sport = :80' | wc -l

# 看每个 worker 状态
curl http://127.0.0.1/nginx_status

# 看 CPU
top -H -p $(pgrep -f 'nginx: worker' | head -1)

# 看网络
ss -s
netstat -s

6.7 配置热加载

  
  
  
bash
nginx -t && nginx -s reload
# 如果出错,自动回滚到上次成功的配置不会发生
# 一定要先 nginx -t 验证

6.8 升级与回滚

  
  
  
bash
# 升级
kill -USR2 <master_pid>
sleep 10
kill -WINCH <old_master_pid>
kill -QUIT <old_master_pid>

# 回滚
kill -HUP <old_master_pid>

七、配置示例

7.1 静态资源服务器

  
  
  
nginx
server {
    listen80;
    server_name static.example.com;
    root /data/www/static;
    index index.html;
    charset utf-8;
    access_log /var/log/nginx/static.access.log;

    location / {
        try_files$uri$uri/ =404;
    }

    location~* \.(gif|jpg|jpeg|png|webp|avif|svg|ico)$ {
        expires30d;
        add_header Cache-Control "public, immutable";
        access_logoff;
    }

    location~* \.(css|js|woff2?|ttf|eot)$ {
        expires7d;
        access_logoff;
    }

    location~* \.(mp4|webm|m4a|m4v|mov)$ {
        mp4;
        mp4_buffer_size4m;
        mp4_max_buffer_size10m;
    }
}

7.2 HTTPS + 反向代理

  
  
  
nginx
upstream backend {
    least_conn;
    server10.0.0.1:8080 max_fails=3 fail_timeout=30s;
    server10.0.0.2:8080 max_fails=3 fail_timeout=30s;
    server10.0.0.3:8080 max_fails=3 fail_timeout=30s;
    keepalive64;
}

server {
    listen80;
    server_name api.example.com;
    return301 https://$host$request_uri;
}

server {
    listen443 ssl http2;
    server_name api.example.com;

    ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;

    include /etc/nginx/snippets/ssl-params.conf;

    access_log /var/log/nginx/api.access.log main;
    error_log /var/log/nginx/api.error.log warn;

    client_max_body_size50m;

    location /health {
        access_logoff;
        return200'OK';
    }

    location / {
        proxy_pass http://backend;
        include /etc/nginx/snippets/proxy-params.conf;
    }
}

7.3 限流配置

  
  
  
nginx
http {
    limit_req_zone$binary_remote_addr zone=perip:10m rate=10r/s;
    limit_req_zone$server_name zone=perserver:10m rate=1000r/s;
    limit_conn_zone$binary_remote_addr zone=perip_conn:10m;

    server {
        listen80;
        server_name app.example.com;

        location / {
            limit_req zone=perserver burst=2000 nodelay;
            limit_conn perip_conn 50;
            proxy_pass http://backend;
        }

        location /api/login {
            limit_req zone=perip burst=5 nodelay;
            limit_req_status429;
            add_header Retry-After 5s;
            proxy_pass http://backend;
        }
    }
}

7.4 防盗链

  
  
  
nginx
server {
    listen80;
    server_name cdn.example.com;
    root /data/www/cdn;

    location~* \.(jpg|jpeg|png|gif|webp|avif)$ {
        valid_referersnoneblocked example.com *.example.com;
        if ($invalid_referer) {
            return403;
        }
        expires30d;
        add_header Cache-Control "public, immutable";
    }
}

7.5 灰度发布

  
  
  
nginx
upstream backend_v1 {
    server10.0.0.1:8080;
    server10.0.0.2:8080;
}

upstream backend_v2 {
    server10.0.0.3:8080;
}

server {
    listen80;
    server_name app.example.com;

    # 按 cookie 灰度
    if ($cookie_gray = "v2") {
        proxy_pass http://backend_v2;
        break;
    }

    # 按 IP 灰度
    set$gray0;
    if ($remote_addr~ "^10\.0\.0\.[0-9]+$") {
        set$gray1;
    }
    if ($arg_gray = "v2") {
        set$gray1;
    }
    if ($gray = 1) {
        proxy_pass http://backend_v2;
    }

    # 默认 v1
    location / {
        proxy_pass http://backend_v1;
        include /etc/nginx/snippets/proxy-params.conf;
    }
}

7.6 TCP/UDP 负载均衡

  
  
  
nginx
stream {
    log_format stream_log '$remote_addr [$time_local] '
                          '$protocol$status$bytes_sent$bytes_received '
                          '$session_time "$upstream_addr"';

    access_log /var/log/nginx/stream.access.log stream_log;

    upstream mysql {
        server10.0.0.1:3306 max_fails=3 fail_timeout=30s;
        server10.0.0.2:3306 max_fails=3 fail_timeout=30s;
    }

    server {
        listen3306;
        proxy_pass mysql;
        proxy_connect_timeout5s;
        proxy_timeout600s;
    }

    upstream dns_backend {
        server8.8.8.8:53;
        server1.1.1.1:53;
    }

    server {
        listen53 udp;
        proxy_pass dns_backend;
        proxy_timeout5s;
    }
}

八、日志或指标观察方法

8.1 accesslog 格式

默认 combined 格式:

  
  
  
text
192.168.1.10 - - [29/Jun/2026:10:23:45 +0800] "GET /api/user/1 HTTP/1.1" 200 1234 "-" "Mozilla/5.0 ..."

字段含义:

  • $remote_addr
    :客户端 IP
  • $remote_user
    :HTTP 认证用户
  • [$time_local]
    :本地时间
  • "$request"
    :请求行
  • $status
    :响应码
  • $body_bytes_sent
    :响应字节数
  • "$http_referer"
    :Referer
  • "$http_user_agent"
    :User-Agent

自定义字段:

  • $request_time
    :请求总耗时
  • $upstream_response_time
    :上游响应耗时
  • $upstream_addr
    :上游地址
  • $upstream_status
    :上游状态
  • $upstream_connect_time
    :上游连接耗时
  • $upstream_header_time
    :上游响应头耗时
  • $connection
    :连接序号
  • $connection_requests
    :连接上的请求数
  • $pipe
    :是否 pipeline
  • $scheme
    :HTTP/HTTPS
  • $request_id
    :请求唯一 ID

8.2 errorlog 关键错误

关键字
含义
处理建议
connect() failed (110: Connection timed out)
上游连接超时
排查网络或上游
connect() failed (111: Connection refused)
上游拒绝
上游未启动
upstream prematurely closed connection
上游断连
上游崩溃或主动断
no live upstreams
所有 upstream down
检查 upstream 状态
client sent invalid header line
客户端发非法头
客户端 bug 或攻击
client sent too large entity
请求体过大
调大 client_max_body_size
SSL_CTX_use_PrivateKey_file() failed
私钥文件有问题
检查证书
BIO_new_file() failed
证书文件读取失败
检查路径权限
worker process exited on signal 9
worker 被 SIGKILL
OOM Killer 触发
worker process is shutting down
优雅退出中
正常
an upstream response is buffered to a temporary file
响应缓冲到磁盘
加 proxy buffer

8.3 关键指标

指标
来源
健康范围
异常表现
Active connections
stub_status
< worker_connections × workers
持续 > 80%
Reading
stub_status
< 100
> 500 表示 worker 处理慢
Writing
stub_status
< 100
> 500 表示上游写慢
Waiting
stub_status
< 1000
持续 > 1 万为连接打满
nginx_http_requests_total
exporter
业务相关
突增为流量暴涨
nginx_http_connections{state="active"}
exporter
< workers × connections
持续高
nginx_upstream_response_time_seconds
vts
业务相关
突增为上游慢
nginx_upstream_response_status
vts
业务相关
5xx 突增
nginx_server_response_time_seconds
vts
业务相关
突增

8.4 连接数计算公式

  • 单 worker 最大并发连接:worker_connections
  • 单 worker 上游连接:每反代一个客户端连接,就建立一个上游连接
  • 系统总连接数:客户端 + 上游 + 文件描述符 < ulimit -n
  • Linux ulimit 默认 1024,生产必须调高到 65535

调高:

  
  
  
bash
# /etc/security/limits.conf
* soft nofile 65535
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535
  
  
  
bash
# systemd 单元
[Service]
LimitNOFILE=65535
LimitNPROC=65535

九、排查路径

9.1 502 Bad Gateway

  • 看 upstream 状态
  • 看 upstream_addrupstream_statusupstream_response_time
  • 看 connect() failed 还是 upstream prematurely closed
  • 看后端日志
  • 排查网络:mtrtcppingcurl -v

9.2 504 Gateway Timeout

  • 看 proxy_read_timeout 是否合理
  • 看后端是否慢
  • 抓后端 thread dump

9.3 413 Request Entity Too Large

  • 调大 client_max_body_size
  • 检查 CDN 是否有大小限制
  • 检查 Tomcat Spring server.tomcat.max-http-form-post-size

9.4 499 Client Closed Request

  • 客户端主动断开
  • 后端慢导致客户端放弃
  • 调后端或加缓存

9.5 403 Forbidden

  • allow
     / deny 规则误伤
  • auth_basic
     配置问题
  • secure_link
     时间戳过期

9.6 404 Not Found

  • root
     / alias 路径错
  • try_files
     不匹配
  • location
     优先级问题

9.7 400 Bad Request

  • Header 过大
  • 请求行过长
  • large_client_header_buffers
     调大

9.8 SSL 握手失败

  • 证书链不全
  • 协议版本不匹配
  • 加密套件不匹配

9.9 worker 不断重启

  • worker_rlimit_nofile
     超限
  • 内存溢出
  • accept_mutex
     死锁
  • error_log
     看具体错误

十、风险提醒

  • nginx -s reload
     前必须 nginx -t,配置错误 reload 后 master 仍能接收连接,但 worker 不会接新连接,造成表面正常实际不服务
  • client_max_body_size
     不设或过大会被攻击者发大文件耗尽磁盘
  • worker_connections
     设得过大但 ulimit -n 没调高,worker 启动就报错
  • keepalive_timeout
     设得过大会让攻击者占满长连接
  • 暴露 stub_status 到公网会泄露内部状态
  • if
     指令在 location 块内使用有“邪恶 if”陷阱,能用 map 或 set 就别用 if
  • 错误的 proxy_set_header Connection "" 会让上游不保持长连接
  • proxy_buffering off
     会让上游响应立刻发到客户端,但同时占更多内存
  • 把 try_files 配错成 $uri/ =404 之前的部分,会让所有请求落空
  • autoindex on
     会让目录可遍历,泄露信息
  • geo
     模块加载超过 7 万条记录会启动失败
  • gzip_types
     写错 MIME 会被攻击者上传非法格式文件
  • add_header
     在 if 内只对当前 if 生效,redirect 中丢失头
  • worker_rlimit_nofile
     必须小于 ulimit -n

十一、验证方式

11.1 配置正确性

  
  
  
bash
nginx -t
nginx -T | less

11.2 启动验证

  
  
  
bash
systemctl status nginx
ss -tlnp | grep -E ':80|:443'
curl -I http://localhost/

11.3 HTTPS 验证

  
  
  
bash
curl -vI https://example.com
openssl s_client -connect example.com:443 -servername example.com </dev/null
nmap --script ssl-enum-ciphers -p 443 example.com

11.4 性能验证

  
  
  
bash
wrk -t4 -c200 -d30s http://localhost/
ab -n 1000 -c 100 http://localhost/

11.5 监控验证

  
  
  
bash
curl http://127.0.0.1/nginx_status
curl http://127.0.0.1:9113/metrics

11.6 日志验证

  
  
  
bash
tail -f /var/log/nginx/access.log
tail -f /var/log/nginx/error.log

十二、回滚方案

12.1 配置回滚

  
  
  
bash
# 修改前备份
cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak.$(date +%Y%m%d_%H%M%S)
cp -r /etc/nginx/conf.d /etc/nginx/conf.d.bak.$(date +%Y%m%d_%H%M%S)

# 出问题立刻回滚
cp /etc/nginx/nginx.conf.bak.YYYYMMDD_HHMMSS /etc/nginx/nginx.conf
nginx -t
nginx -s reload

12.2 二进制回滚

  
  
  
bash
# 保留 nginx.bak
kill -QUIT $(cat /var/run/nginx.pid)
cp /usr/sbin/nginx.bak /usr/sbin/nginx
systemctl start nginx

12.3 配置版本管理

  
  
  
bash
# 用 git 管理
cd /etc/nginx
git init
git add .
git commit -m "init"
git log
git diff HEAD~1

# 出问题
git checkout HEAD~1
nginx -t
nginx -s reload

十三、生产环境注意事项

  • 关闭 server_tokens
  • 关闭 autoindex
  • 关闭 ssi
  • 必须用 HTTPS
  • 必须配置 Strict-Transport-Security
  • 必须配置 client_max_body_size 上限
  • 必须配置 worker_rlimit_nofile
  • 必须调高 systemd 单元的 LimitNOFILE
  • 必须配置 access_log 与 error_log
  • 必须 logrotate
  • 必须配置 stub_status 或 vts 给监控
  • 必须配置 Prometheus exporter
  • 必须配置告警(连接数、5xx 比例、上游响应时间、QPS 异常)
  • 必须配置灰度
  • 必须有回滚方案
  • 必须做压测与基线
  • 必须用非 root 用户启动
  • 必须设置 systemd Restart=always
  • 必须配置 LimitCORE=infinity 用于 core dump
  • 必须配置 WorkingDirectory 与 RuntimeDirectory

十四、总结

Nginx 看似简单,做深了要懂 11 件事:

  • 架构与信号
  • 配置结构与变量
  • 模块体系与编译参数
  • 反向代理与负载均衡
  • HTTPS 与 TLS
  • 限流与防 CC
  • 日志与监控
  • 性能调优
  • 高可用
  • 平滑升级
  • 典型排障

合格运维的标准,是把上面 11 件事都能在生产环境用 30 分钟内完成:

  • 写出配置 5 分钟
  • 排障 10 分钟
  • 升级 5 分钟
  • 回滚 5 分钟
  • 留文档 5 分钟

剩下的是熟练度问题。

最后留一个清单,按这个清单自己跑一遍,能跑通就基本合格:

  • 5 分钟写出一个 HTTPS + 反代 + 限流 + accesslog + 健康检查的 server 块
  • 5 分钟写出 stub_status 监控 + Prometheus 集成
  • 10 分钟完成一次 reload → 5xx 突增 → 抓 accesslog → 抓 errorlog → 回滚
  • 5 分钟完成一次热升级
  • 5 分钟压测 wrk 单 worker 5 万 QPS

如果都做不到,绕回来看文章。


【声明】内容源于网络
0
0
红帽Linux认证
社区致力于分享红帽Linux及其他产品最新资讯,RHCSA/RHCE/RHCA认证动态。
内容 166
粉丝 0
红帽Linux认证 社区致力于分享红帽Linux及其他产品最新资讯,RHCSA/RHCE/RHCA认证动态。
总阅读344
粉丝0
内容166