一、 Nginx 生产级知识架构树(按流量路径 + 运维维度组织)
Nginx 生产知识体系
├── 0. 基础运行模型(必须先理解)
│ ├── 进程模型:master + worker(非阻塞事件驱动)
│ ├── 配置加载机制:nginx -t → nginx -s reload(原子性保障)
│ ├── 模块化架构:core / http / stream / 3rd-party(如 ngx_http_lua_module)
│ └── 内存池与连接池机制(避免频繁malloc/free)
│
├── 1. 接入层流量治理(L7)
│ ├── 1.1 反向代理
│ │ ├── proxy_pass(支持变量、upstream)
│ │ ├── proxy_set_header(透传trace_id、real_ip)
│ │ └── proxy_next_upstream(错误重试策略)
│ │
│ ├── 1.2 负载均衡策略
│ │ ├── round-robin(默认)
│ │ ├── least_conn(长连接场景)
│ │ ├── ip_hash(会话保持,慎用)
│ │ └── hash $request_uri consistent(一致性哈希,缓存友好)
│ │
│ ├── 1.3 健康检查(生产必须)
│ │ ├── 被动检查:max_fails + fail_timeout
│ │ └── 主动检查:Tengine check / nginx-plus / OpenResty + Lua + /healthz
│ │
│ ├── 1.4 限流与熔断
│ │ ├── limit_req(漏桶算法,防突发)
│ │ ├── limit_conn(单IP连接数限制)
│ │ └── 自定义Lua熔断(基于5xx比例动态摘除)
│ │
│ ├── 1.5 TLS/SSL 终止
│ │ ├── 证书管理(自动续期 + OCSP Stapling)
│ │ ├── TLS 1.2/1.3 启用(禁用SSLv3)
│ │ └── 会话复用(ssl_session_cache shared:SSL:10m)
│ │
│ └── 1.6 动态配置
│ ├── 变量系统($http_x_forwarded_for, $request_time)
│ ├── map 指令(路由染色、灰度)
│ └── OpenResty + Lua(实现动态upstream,替代Diamond配置中心)
│
├── 2. 静态资源与缓存加速
│ ├── 2.1 静态文件服务
│ │ ├── sendfile on(零拷贝)
│ │ ├── tcp_nopush on(减少小包)
│ │ └── expires / Cache-Control(CDN友好)
│ │
│ ├── 2.2 proxy_cache(反向代理缓存)
│ │ ├── keys_zone(共享内存索引)
│ │ ├── inactive(过期清理)
│ │ ├── proxy_cache_use_stale(后端故障时返回旧缓存)
│ │ └── proxy_cache_lock(防缓存击穿)
│ │
│ └── 2.3 与CDN协同
│ ├── 回源Host头设置
│ └── Range请求透传(视频/大文件)
│
├── 3. 性能与内核协同调优
│ ├── 3.1 Nginx自身调优
│ │ ├── worker_processes auto
│ │ ├── worker_connections 65536+
│ │ ├── multi_accept on
│ │ └── accept_mutex off(Linux 3.9+已无惊群)
│ │
│ ├── 3.2 Linux内核参数(必须同步调)
│ │ ├── net.core.somaxconn = 65535(listen backlog)
│ │ ├── net.ipv4.tcp_tw_reuse = 1(TIME-WAIT复用)
│ │ ├── net.ipv4.ip_local_port_range = 1024 65535
│ │ └── fs.file-max = 2000000(全局fd上限)
│ │
│ └── 3.3 监控与瓶颈定位
│ ├── stub_status /metrics(Prometheus exporter)
│ ├── perf + eBPF(2021年双11用bpftrace抓TCP重传)
│ └── /proc/PID/limits 检查ulimit
│
├── 4. 安全加固
│ ├── 4.1 隐藏指纹
│ │ ├── server_tokens off
│ │ └── 自定义404/50x页面(不暴露Nginx版本)
│ │
│ ├── 4.2 请求过滤
│ │ ├── if ($request_method !~ ^(GET|POST|HEAD)$) { return 405; }
│ │ ├── WAF规则(通过Lua或ModSecurity)
│ │ └── 防扫描(封禁sqlmap/nmap UA)
│ │
│ └── 4.3 文件上传防护
│ ├── client_max_body_size 10m
│ └── 限制上传路径(location ~ ^/upload/ { deny all; })
│
├── 5. 可观测性与日志
│ ├── 5.1 结构化日志
│ │ ├── JSON格式(含$request_time, $upstream_response_time)
│ │ └── trace_id透传(X-B3-TraceId)
│ │
│ ├── 5.2 错误日志分级
│ │ ├── error_log /var/log/nginx/error.log warn;
│ │ └── 关键错误告警(如"upstream timed out")
│ │
│ └── 5.3 链路追踪集成
│ └── 鹰眼(EagleEye)等效:OpenTelemetry + Jaeger
│
└── 6. 自动化与SRE工程化
├── 6.1 配置即代码(Config as Code)
│ ├── Git管理nginx.conf.j2(Jinja2模板)
│ └── Ansible/SREWorks批量下发
│
├── 6.2 灰度发布
│ ├── 流量染色(set $group = "gray" if $http_x_gray = "1")
│ └── upstream分组(backend_gray / backend_prod)
│
└── 6.3 故障自愈
├── 健康检查自动摘除
└── 日志异常触发自动reload或回滚(通过SLS+函数计算)
1 进程模型:master + worker(非阻塞事件驱动)
Nginx默认启动一个 master
进程和多个 worker
进程(数量由 worker_processes
控制):
worker_processes auto; # 推荐设为 auto(等于CPU核心数)
master
:仅负责读取配置、启动/管理worker
、接收信号(如 reload)。worker
:真正处理网络IO,每个 worker 是单线程、基于 epoll/kqueue 的事件循环,非阻塞。
监控指标
-
进程数验证 :
ps -ef | grep nginx # 应看到 1 个 master + N 个 worker(N = CPU核数)
-
CPU亲和性(可选但推荐) :
worker_cpu_affinity auto; # 绑定CPU核心,减少上下文切换
监控命令:
taskset -p $(pgrep -f "nginx: worker")
故障案例(生产真实事件)
故障 :某团队将
worker_processes
设为1
(误以为节省资源),结果单 worker CPU 100%,无法处理突发流量,大量 502。
根因 :Nginx 是单线程事件模型,一个 worker 只能跑满一个 CPU 核。
对策 :强制规范worker_processes auto
,并通过 SREWorks 自动校验配置。
2 配置加载机制:nginx -t → nginx -s reload(原子性保障)
配置片段(操作流程)
# 1. 语法检查(必须!)
nginx -t
# 2. 热加载(不中断连接)
nginx -s reload
# 3. 验证新配置生效
curl -s http://localhost/nginx_status # 若开启 stub_status
reload
本质:master 启动新 worker,旧 worker 处理完现有连接后优雅退出(零 downtime)。
监控指标
-
reload 成功率 (通过日志):
grep "signal 1 (SIGHUP)" /var/log/nginx/error.log
-
旧 worker 存活时间 (不应超过
keepalive_timeout + 10s
):ps -o pid,ppid,etime,cmd -C nginx | grep worker
故障案例
事故 :运维未执行
nginx -t
,直接reload
,配置语法错误导致 master 启动失败,新 worker 未拉起,旧 worker 被 kill,全站502持续8分钟 。
对策:
- 所有变更必须走 CI 流程,自动执行
nginx -t
;- 在 Ansible/SREWorks 中封装
nginx_reload
模块,强制前置检查。
3 模块化架构:core / http / stream / 3rd-party
配置片段(模块启用示例)
-
HTTP 模块(默认启用) :
http { ... }
-
Stream 模块(L4代理,需显式编译或安装) :
stream { upstream mysql_backend { server 10.0.1.10:3306; } server { listen 3306; proxy_pass mysql_backend; } }
-
第三方模块(如 Lua) :
# 编译时加入 ./configure --add-module=../ngx_devel_kit --add-module=../lua-nginx-module
监控指标
-
模块版本与兼容性 :
nginx -V 2>&1 | grep -o 'with-[a-zA-Z0-9_\-]*'
-
Lua 脚本性能 (若使用 OpenResty):
log_by_lua_block { local latency = ngx.now() - ngx.req.start_time() ngx.log(ngx.WARN, "request latency: ", latency) }
故障案例
2020年灰度发布失败 :团队在生产 Nginx 中动态加载未测试的 Lua 脚本,触发内存泄漏,worker 频繁 OOM。
对策:
- 第三方模块必须通过"灰度集群"压测7天;
- 禁止在非 OpenResty 环境随意加载 Lua。
4 内存池与连接池机制(避免频繁malloc/free)
配置片段(间接影响)
Nginx 内部使用内存池(pool)管理请求生命周期内存,用户无法直接配置,但可通过以下参数间接控制:
client_body_buffer_size 128k; # 请求体缓冲区
client_header_buffer_size 4k; # 请求头缓冲区
large_client_header_buffers 4 16k;
监控指标
-
内存增长趋势 (应平稳):
watch -n 1 'ps -o pid,vsz,rss,cmd -C nginx'
-
连接池复用率 (通过
$connection_requests
变量):log_format debug '$remote_addr $connection $connection_requests';
故障案例
2019年内存泄漏事件 :某业务上传超大文件(>1GB),
client_body_buffer_size
默认值过小,触发磁盘写入+频繁内存分配,worker RSS 内存飙升至 4GB,被 OOM Killer 杀死。
对策:
- 限制
client_max_body_size 10m
;- 对大文件上传走专用域名+独立 Nginx 实例。