docs(nginx): 更新代理与 stream 文档,新增 njs/可观测性/ACME 指南

- 04: 新增 random 负载均衡、upstream 响应时间变量详解
- 10: 新增访问控制、连接限制、地理/真实IP模块、高级日志配置
- 24: 新增 worker_aio_requests、EPOLLEXCLUSIVE 详解
- 30: njs JavaScript 模块完整指南
- 31: OpenTelemetry 可观测性集成指南
- 32: ACME 自动证书管理指南

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
xfy 2026-04-07 17:06:38 +08:00
parent 0979b60ff2
commit d8ac807cb7
7 changed files with 4591 additions and 1 deletions

View File

@ -190,6 +190,45 @@ upstream backend {
} }
``` ```
**随机负载均衡1.15.1+**
```nginx
upstream backend {
random; # 纯随机选择
server srv1.example.com;
server srv2.example.com;
server srv3.example.com;
}
# Power of Two Choices 算法(更智能)
upstream backend {
random two; # 随机选两台,按权重择优
server srv1.example.com;
server srv2.example.com;
server srv3.example.com;
}
# 结合最少连接策略
upstream backend {
random two least_conn; # 随机选两台,选连接数少的
server srv1.example.com;
server srv2.example.com;
}
```
**random 算法参数说明**
| 参数 | 说明 |
|------|------|
| `two` | 随机选择两台服务器,再根据策略择优 |
| `least_conn` | 与 `two` 配合,选择连接数较少的服务器 |
| `least_time=header` | 与 `two` 配合选择响应头时间最短的服务器NGINX Plus|
| `least_time=last_byte` | 与 `two` 配合选择完整响应时间最短的服务器NGINX Plus|
**适用场景**
- 多个负载均衡器共享后端时避免锁竞争
- 对一致性要求不高但需要低延迟的场景
- 配合 `zone` 实现无锁负载均衡
### server 指令参数 ### server 指令参数
| 参数 | 说明 | 默认值 | | 参数 | 说明 | 默认值 |
@ -757,12 +796,83 @@ http {
## 16. 内置变量 ## 16. 内置变量
### 代理相关变量
| 变量 | 说明 | | 变量 | 说明 |
|------|------| |------|------|
| `$proxy_host` | proxy_pass 中的服务器名称和端口 | | `$proxy_host` | proxy_pass 中的服务器名称和端口 |
| `$proxy_port` | proxy_pass 中的端口 | | `$proxy_port` | proxy_pass 中的端口 |
| `$proxy_add_x_forwarded_for` | X-Forwarded-For 头 + 客户端 IP | | `$proxy_add_x_forwarded_for` | X-Forwarded-For 头 + 客户端 IP |
### Upstream 响应时间变量(用于性能监控)
| 变量 | 说明 | 单位 |
|------|------|------|
| `$upstream_addr` | 上游服务器地址IP:端口)| - |
| `$upstream_connect_time` | 与上游建立连接的时间(含 SSL 握手)| 秒 |
| `$upstream_header_time` | 接收到上游响应头的时间 | 秒 |
| `$upstream_response_time` | 完整响应时间(从建立连接到接收完成)| 秒 |
| `$upstream_response_length` | 上游响应体长度 | 字节 |
| `$upstream_bytes_received` | 从上游接收的总字节数 | 字节 |
| `$upstream_bytes_sent` | 发送到上游的总字节数 | 字节 |
| `$upstream_status` | 上游返回的 HTTP 状态码 | - |
| `$upstream_cache_status` | 缓存命中状态HIT/MISS/EXPIRED 等)| - |
| `$upstream_queue_time` | 请求在队列中等待的时间NGINX Plus| 秒 |
**日志格式中使用响应时间变量**
```nginx
log_format detailed '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'rt=$request_time '
'uct="$upstream_connect_time" '
'uht="$upstream_header_time" '
'urt="$upstream_response_time" '
'upstream=$upstream_addr '
'upstream_status=$upstream_status '
'upstream_bytes=$upstream_response_length';
access_log /var/log/nginx/access.log detailed;
```
**响应时间变量解读**
```
请求时间线:
客户端 ──▶ NGINX ──▶ 连接上游 ──▶ 发送请求 ──▶ 接收响应头 ──▶ 接收响应体 ──▶ 客户端
│ │ │ │ │
│ │ │ │ │
└───────────┴──────────────┴────────────────┴────────────────┘
│ │ │
$upstream_ $upstream_ $upstream_
connect_time header_time response_time
```
- `$upstream_connect_time`TCP 连接 + SSL 握手时间
- `$upstream_header_time`:从开始到收到响应头
- `$upstream_response_time`:完整请求处理时间
- `$request_time`:从客户端发起请求到响应完成(包含所有上游)
**基于响应时间的告警配置示例**
```nginx
# 慢请求日志
map $upstream_response_time $slow_log {
default 0;
"~^[2-9]\." 1; # 2秒以上
"~^[0-9]{2,}" 1; # 10秒以上
}
server {
location /api/ {
# 记录慢请求
access_log /var/log/nginx/slow.log detailed if=$slow_log;
proxy_pass http://backend;
}
}
```
--- ---
## 17. 综合配置示例 ## 17. 综合配置示例

View File

@ -689,4 +689,374 @@ upstream backend {
health_check interval=5s passes=2 fails=3; health_check interval=5s passes=2 fails=3;
health_check_timeout 5s; health_check_timeout 5s;
} }
``` ```
---
## 15. 访问控制模块
### ngx_stream_access_module
基于 IP 地址的访问控制,允许或拒绝特定客户端连接。
**指令**
| 指令 | 语法 | 默认值 | 上下文 |
|------|------|--------|--------|
| `allow` | `allow address \| CIDR \| unix: \| all;` | — | stream, server |
| `deny` | `deny address \| CIDR \| unix: \| all;` | — | stream, server |
**配置示例**
```nginx
stream {
# 数据库访问控制
server {
listen 3306;
# 允许内网访问
allow 10.0.0.0/8;
allow 192.168.0.0/16;
allow 172.16.0.0/12;
# 拒绝其他所有
deny all;
proxy_pass mysql_backend;
}
# Redis 访问控制
server {
listen 6379;
# 仅允许特定 IP
allow 192.168.1.100;
allow 192.168.1.101;
deny all;
proxy_pass redis_backend;
}
# 管理端口(仅本地)
server {
listen 9000;
allow 127.0.0.1;
deny all;
proxy_pass admin_backend;
}
}
```
**规则匹配顺序**
- 按配置顺序依次检查
- 首个匹配的规则决定结果
- 未匹配任何规则时默认允许
---
## 16. 连接限制模块
### ngx_stream_limit_conn_module
限制并发连接数,防止资源耗尽。
**指令**
| 指令 | 语法 | 默认值 | 上下文 |
|------|------|--------|--------|
| `limit_conn_zone` | `limit_conn_zone key zone=name:size;` | — | stream |
| `limit_conn` | `limit_conn zone number;` | — | stream, server |
| `limit_conn_log_level` | `limit_conn_log_level info \| notice \| warn \| error;` | error | stream, server |
**配置示例**
```nginx
stream {
# 按客户端 IP 限制连接数
limit_conn_zone $binary_remote_addr zone=addr:10m;
# 按上游服务器限制连接数
limit_conn_zone $server_addr zone=server:10m;
# MySQL 代理 - 每 IP 最多 10 个连接
server {
listen 3306;
limit_conn addr 10;
proxy_pass mysql_backend;
}
# Redis 代理 - 每 IP 最多 5 个连接
server {
listen 6379;
limit_conn addr 5;
limit_conn_log_level warn;
proxy_pass redis_backend;
}
# 全局连接限制
server {
listen 8080;
limit_conn addr 50; # 每 IP 最多 50
limit_conn server 1000; # 服务总连接上限
proxy_pass backend;
}
}
```
**内存计算**
- 1MB 共享内存可存储约 16,000 个 32 字节 key$binary_remote_addr
- 或约 8,000 个 IPv6 地址16 字节)
---
## 17. 地理位置模块
### ngx_stream_geo_module
根据客户端 IP 地址创建变量值,用于地理路由或访问控制。
**指令**
| 指令 | 语法 | 默认值 | 上下文 |
|------|------|--------|--------|
| `geo` | `geo [$address] $variable { ... }` | — | stream |
**配置示例**
```nginx
stream {
# 基础地理映射
geo $remote_addr $region {
default other;
10.0.0.0/8 internal;
192.168.0.0/16 internal;
172.16.0.0/12 internal;
# 中国大陆 IP 段(示例)
1.0.1.0/24 china;
1.0.2.0/23 china;
# ... 更多 IP 段
}
# 使用变量进行路由
map $region $backend_pool {
internal internal_backend;
china china_backend;
other global_backend;
}
upstream internal_backend {
server 192.168.1.1:3306;
}
upstream china_backend {
server 10.0.1.1:3306;
}
upstream global_backend {
server 10.0.2.1:3306;
}
server {
listen 3306;
proxy_pass $backend_pool;
}
}
```
**高级用法**
```nginx
stream {
# 使用变量作为地址源
geo $realip_remote_addr $region {
default other;
# ... 配置
}
# 带 CIDR 包含
geo $country {
default XX;
include /etc/nginx/geo/countries.conf;
}
# countries.conf 内容示例:
# 1.0.1.0/24 CN;
# 1.0.2.0/23 CN;
# 1.1.1.0/24 AU;
}
# 使用 GeoIP 数据库(需 ngx_stream_geoip_module
geoip_country /usr/share/GeoIP/GeoIP.dat;
map $geoip_country_code $backend {
default global_backend;
CN china_backend;
US us_backend;
EU eu_backend;
}
}
```
---
## 18. 真实 IP 模块
### ngx_stream_realip_module
处理 PROXY 协议头,获取客户端真实 IP 地址。
**指令**
| 指令 | 语法 | 默认值 | 上下文 |
|------|------|--------|--------|
| `set_real_ip_from` | `set_real_ip_from address \| CIDR;` | — | stream, server |
| `real_ip_header` | `real_ip_header field;` | proxy_protocol | stream, server |
**配置示例**
```nginx
stream {
server {
listen 3306 proxy_protocol; # 接收 PROXY 协议
# 信任的代理服务器地址
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 192.168.0.0/16;
set_real_ip_from 172.16.0.0/12;
proxy_pass mysql_backend;
}
}
```
**可用变量**
| 变量 | 说明 |
|------|------|
| `$realip_remote_addr` | 原始客户端地址PROXY 协议中的地址)|
| `$realip_remote_port` | 原始客户端端口 |
| `$proxy_protocol_addr` | PROXY 协议中的客户端地址 |
| `$proxy_protocol_port` | PROXY 协议中的客户端端口 |
| `$proxy_protocol_server_addr` | PROXY 协议中的目标服务器地址 |
| `$proxy_protocol_server_port` | PROXY 协议中的目标服务器端口 |
**典型场景**
```nginx
stream {
# 场景:负载均衡器 → NGINX → 后端
server {
listen 3306 proxy_protocol;
# 负载均衡器的 IP
set_real_ip_from 10.0.0.1;
set_real_ip_from 10.0.0.2;
# 使用真实 IP 进行限流
limit_conn_zone $realip_remote_addr zone=conn_limit:10m;
limit_conn conn_limit 10;
# 日志记录真实 IP
log_format main '$realip_remote_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received';
access_log /var/log/nginx/stream.log main;
proxy_pass mysql_backend;
}
}
```
---
## 19. 高级日志配置
### 日志格式详解
```nginx
stream {
# JSON 格式日志
log_format json_combined escape=json
'{'
'"time_local":"$time_local",'
'"remote_addr":"$remote_addr",'
'"server_addr":"$server_addr",'
'"server_port":"$server_port",'
'"protocol":"$protocol",'
'"status":"$status",'
'"bytes_sent":"$bytes_sent",'
'"bytes_received":"$bytes_received",'
'"session_time":"$session_time",'
'"upstream_addr":"$upstream_addr",'
'"upstream_bytes_sent":"$upstream_bytes_sent",'
'"upstream_bytes_received":"$upstream_bytes_received",'
'"upstream_connect_time":"$upstream_connect_time"'
'}';
# 详细格式日志
log_format detailed '$remote_addr - [$time_local] '
'$protocol/$status '
'sent:$bytes_sent recv:$bytes_received '
'time:$session_time '
'upstream:$upstream_addr '
'upstream_time:$upstream_connect_time';
# 条件日志(仅记录错误)
map $status $loggable {
~^[23] 0;
default 1;
}
server {
listen 3306;
access_log /var/log/nginx/stream.json json_combined;
access_log /var/log/nginx/stream_errors.log detailed if=$loggable;
proxy_pass backend;
}
}
```
### 日志缓冲与压缩
```nginx
stream {
server {
listen 3306;
# 缓冲写入(提升性能)
access_log /var/log/nginx/stream.log main buffer=32k flush=5s;
# gzip 压缩日志
access_log /var/log/nginx/stream.log.gz main gzip buffer=32k;
proxy_pass backend;
}
}
```
### open_log_file_cache
缓存日志文件描述符,减少文件打开操作:
```nginx
stream {
open_log_file_cache max=1000 inactive=20s valid=1m min_uses=2;
server {
listen 3306;
access_log /var/log/nginx/stream.log main;
proxy_pass backend;
}
}
```
**参数说明**
| 参数 | 说明 |
|------|------|
| `max` | 缓存的最大文件描述符数 |
| `inactive` | 非活动文件保留时间 |
| `valid` | 检查文件是否有效的时间间隔 |
| `min_uses` | 最小使用次数才缓存 |

View File

@ -1069,9 +1069,134 @@ events {
# 互斥锁(现代 Linux 不需要) # 互斥锁(现代 Linux 不需要)
accept_mutex off; accept_mutex off;
# 异步 I/O 请求数epoll + aio 场景)
worker_aio_requests 64; # 默认 32
} }
``` ```
### 6.3 新增指令详解
#### worker_aio_requests
设置使用 `epoll``aio` 时,单个 worker 进程的最大未完成异步 I/O 操作数。
**语法**`worker_aio_requests number;`
**默认值**`worker_aio_requests 32;`
**上下文**events
**版本**1.1.4+
```nginx
events {
worker_connections 10240;
use epoll;
multi_accept on;
worker_aio_requests 64; # 提高异步 I/O 并发
}
http {
# 配合 aio 使用
location /videos/ {
aio threads;
sendfile on;
}
}
```
**适用场景**
- 高并发文件传输(视频、图片服务)
- 使用 `aio threads` 异步 I/O
- 大文件下载服务
#### ssl_object_cache_inheritable
控制 SSL 对象(证书、密钥等)在配置重载时是否继承。
**语法**`ssl_object_cache_inheritable on | off;`
**默认值**`ssl_object_cache_inheritable on;`
**上下文**main
**版本**1.27.4+
```nginx
# 默认情况下SSL 对象在 reload 时会继承
ssl_object_cache_inheritable on;
http {
server {
listen 443 ssl;
# 静态证书路径 - 支持继承
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
}
}
```
**说明**
- 开启时,未修改的 SSL 证书/密钥在 reload 时复用
- 变量形式加载的 SSL 对象无法继承
- 关闭时,每次 reload 都重新加载所有 SSL 对象
### 6.4 EPOLLEXCLUSIVE 标志详解
**版本支持**Linux 2.6.39+nginx 1.11.3+
`EPOLLEXCLUSIVE` 是 Linux 内核提供的标志,用于解决多 worker 进程的惊群问题。
**传统惊群问题**
```
新连接到达
┌──────────┬─────────┴─────────┬──────────┐
▼ ▼ ▼ ▼
Worker 1 Worker 2 Worker 3 Worker 4
(唤醒) (唤醒) (唤醒) (唤醒)
│ │ │ │
└──────────┴─────────┬─────────┴──────────┘
只有一个 accept 成功
其他唤醒浪费 CPU
```
**使用 EPOLLEXCLUSIVE 后**
```
新连接到达
┌──────────┬─────────┴─────────┬──────────┐
▼ ▼ ▼ ▼
Worker 1 Worker 2 Worker 3 Worker 4
(唤醒) (休眠) (休眠) (休眠)
accept 成功,处理连接
```
**nginx 配置建议**
```nginx
# Linux 2.6.39+ 不需要 accept_mutex
events {
use epoll;
accept_mutex off; # 关闭互斥锁,使用 EPOLLEXCLUSIVE
multi_accept on; # 可以开启EPOLLEXCLUSIVE 已解决惊群
}
```
**优势**
- 减少不必要的进程唤醒
- 降低 CPU 使用率
- 提高高并发场景性能
**注意事项**
- 仅对 `epoll` 有效
- 需要内核 2.6.39+
- nginx 1.11.3+ 自动启用
### 6.3 内核参数优化 ### 6.3 内核参数优化
```bash ```bash

1232
docs/30-nginx-njs-guide.md Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1236
docs/32-nginx-acme-ssl.md Normal file

File diff suppressed because it is too large Load Diff

View File

@ -35,6 +35,9 @@
| 27 | [安全深度指南](./27-nginx-security-deep-dive.md) | WAF/ModSecurity、DDoS 防护、OWASP Top 10、安全头部 | | 27 | [安全深度指南](./27-nginx-security-deep-dive.md) | WAF/ModSecurity、DDoS 防护、OWASP Top 10、安全头部 |
| 28 | [API 网关配置](./28-nginx-api-gateway.md) | API 路由设计、JWT 验证、限流配额、版本控制 | | 28 | [API 网关配置](./28-nginx-api-gateway.md) | API 路由设计、JWT 验证、限流配额、版本控制 |
| 29 | [动态配置与服务发现](./29-nginx-dynamic-config.md) | 动态 upstream、etcd/Consul、dyups、nginx-unit | | 29 | [动态配置与服务发现](./29-nginx-dynamic-config.md) | 动态 upstream、etcd/Consul、dyups、nginx-unit |
| 30 | [njs JavaScript 模块](./30-nginx-njs-guide.md) | njs 引擎、js_import/js_set/js_content、Fetch API、共享字典 |
| 31 | [OpenTelemetry 可观测性](./31-nginx-observability.md) | ngx_otel_module、分布式追踪、Jaeger/Zipkin 集成、采样策略 |
| 32 | [ACME 自动证书管理](./32-nginx-acme-ssl.md) | ngx_http_acme_module、Let's Encrypt、自动续期、HTTP-01/DNS-01 挑战 |
--- ---
@ -68,10 +71,16 @@
### 扩展与第三方 ### 扩展与第三方
- [第三方扩展模块](./22-nginx-third-party-modules.md) - NJS, Lua, Brotli, RTMP 等 - [第三方扩展模块](./22-nginx-third-party-modules.md) - NJS, Lua, Brotli, RTMP 等
- [Lua 模块深度指南](./26-nginx-lua-guide.md) - OpenResty、ngx_lua、cosocket - [Lua 模块深度指南](./26-nginx-lua-guide.md) - OpenResty、ngx_lua、cosocket
- [njs JavaScript 模块](./30-nginx-njs-guide.md) - njs 引擎、JavaScript 扩展
### 安全深度 ### 安全深度
- [安全与访问控制](./09-nginx-security.md) - 综合安全配置 - [安全与访问控制](./09-nginx-security.md) - 综合安全配置
- [安全深度指南](./27-nginx-security-deep-dive.md) - WAF、DDoS、OWASP - [安全深度指南](./27-nginx-security-deep-dive.md) - WAF、DDoS、OWASP
- [ACME 自动证书管理](./32-nginx-acme-ssl.md) - Let's Encrypt、自动 SSL 证书
### 可观测性
- [日志与监控](./08-nginx-logging-monitoring.md) - 访问日志、错误日志、stub_status
- [OpenTelemetry 可观测性](./31-nginx-observability.md) - 分布式追踪、Jaeger/Zipkin
### API 与动态配置 ### API 与动态配置
- [API 网关配置](./28-nginx-api-gateway.md) - API 路由、JWT、限流配额 - [API 网关配置](./28-nginx-api-gateway.md) - API 路由、JWT、限流配额