Nginx
Nginx 可以直接读取文件返回页面,也可以接收 HTTP 请求,再建立另一条连接访问应用。反向代理涉及两端连接:客户端连接 Nginx,Nginx 连接上游。两条连接各自有地址、协议、超时和关闭过程。
客户端 ── HTTP / HTTPS ── Nginx
├── 静态处理 → 文件系统
├── 直接响应 → 拒绝、跳转、入口探针
└── 代理连接 → 应用服务 → 响应应用只绑定服务器回环地址时,同机 Nginx 可以访问它;把 Nginx 放到另一个容器后,回环地址就指向容器自己。部署位置改变了连接方式,即使 proxy_pass 的文本没变,请求也可能到达不同进程。
进程、安装与配置层级
master 与 worker
master 读取配置、管理 worker,并处理重载和退出信号。worker 使用事件机制同时处理多个连接,执行请求处理模块和响应过滤器。启用缓存后还可能出现 cache manager、cache loader 等辅助进程。进程与信号说明
事件驱动减少了每个连接占用一个线程的成本,CPU、文件描述符、网络和磁盘仍会限制吞吐量。一个代理请求通常同时占用客户端和上游连接,空闲 keepalive 也占资源。因此 worker_processes × worker_connections 不能直接当作业务并发请求数。
在 Linux 安装
在专用测试服务器上,由有 sudo 权限的管理员安装发行版包。Ubuntu 24.04 可执行:
sudo apt update
sudo apt install -y nginx curl ca-certificates
sudo nginx -t
sudo systemctl enable --now nginx
nginx -v
nginx -V
systemctl status nginx --no-pagerRHEL、Rocky Linux、AlmaLinux 等系统先检查仓库提供的版本,再使用对应 RPM 包:
dnf info nginx
sudo dnf install -y nginx curl ca-certificates
sudo nginx -t
sudo systemctl enable --now nginx-v 显示版本,-V 显示编译参数、模块和默认路径。后续实验基于 Ubuntu 24.04 / Nginx 1.24.0;部署其他发行线时按实际版本选择指令。发行版包与 Nginx 官方包可能采用不同路径和安全维护方式,不要未经比较混装仓库。官方软件包说明
配置检查应显示 syntax is ok 和 test is successful。失败时按文件、行号和错误修复;服务未运行则查看 sudo journalctl -u nginx -n 60 --no-pager 和 sudo ss -lntp,区分配置、权限与端口占用。
公网接入还涉及域名解析、云安全组和主机网络。本机请求正常后再检查外部路径,不直接执行全局防火墙重置。受限网络使用批准的软件源;离线安装同时准备软件包、依赖和签名验证,见离线部署。
include 在当前位置展开
nginx.conf
├── main:worker_processes、pid、error_log、user
├── events:worker_connections
└── http
├── mime.types、log_format、map、缓存和限流共享区
├── upstream:后端池
└── server:listen、server_name、证书
└── location:文件、代理、访问规则include 引入文件,文件名本身不赋予上下文。http 内引入的文件可以定义 server 和 upstream,不能再包一层 http。Ubuntu 常见 sites-enabled,官方包常见 conf.d,实际加载关系要看主配置。
sudo nginx -T 2>&1 | less-T 解析当前磁盘文件并输出,并非运行中 worker 的配置转储。文件改了但没有成功 reload,输出可能与实际响应不同。输出还可能包含内网地址、认证字段和路径,只在受控终端查看。命令行参数
user 指定 root master 启动的 worker 身份。普通用户启动实验时不能靠该指令切换身份;静态目录、日志和临时目录都应按实际 UID 准备。
用实验理解站点、路径和代理
建立隔离环境
以下命令在安装了 Docker 的 Linux 开发机执行,操作者有调用 Engine 的权限。镜像构建安装包时使用容器内 root;运行实验为 UID/GID 10001,不发布宿主端口、不安装宿主服务。Docker 安装与权限
mkdir nginx-routing-lab
cd nginx-routing-lab
cat > Dockerfile <<'EOF'
FROM ubuntu:24.04
RUN apt-get update && apt-get install -y --no-install-recommends \
nginx curl python3 ca-certificates procps \
&& rm -rf /var/lib/apt/lists/* \
&& mkdir /lab && chown 10001:10001 /lab
USER 10001:10001
WORKDIR /lab
CMD ["bash"]
EOF
docker build -t local/nginx-routing-lab:1 .
docker run --rm -it --network none local/nginx-routing-lab:1构建时需要软件源可达。进入容器后,以下操作全部在 /lab 执行;id -u 应为 10001,nginx -v 给出实际包版本。
准备可观察的上游
Python 服务返回收到的 URI 和字段;/slow 在发送响应头前等待两秒,用来观察上游读取超时。它只是 HTTP 观察服务,真实 Java 应用的托管见 Spring Boot 部署运维。
mkdir -p html/assets files cache
printf 'entry-v1\n' > html/index.html
printf 'asset-ok\n' > html/assets/app.abc123.js
printf 'alias-ok\n' > files/manual.txt
python3 -c "print('gzip-line\\n' * 512)" > html/assets/large.txt
cat > upstream.py <<'EOF'
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
import json, time
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path.startswith('/slow'):
time.sleep(2)
body = json.dumps({'path': self.path,
'host': self.headers.get('Host'),
'xff': self.headers.get('X-Forwarded-For')}).encode()
self.send_response(200)
self.send_header('Content-Type', 'application/json')
self.send_header('Content-Length', str(len(body)))
self.end_headers()
try:
self.wfile.write(body)
except BrokenPipeError:
pass
def log_message(self, *args):
pass
ThreadingHTTPServer(('127.0.0.1', 18081), Handler).serve_forever()
EOF
python3 upstream.py &
upstream_pid=$!upstream_pid 只记录本次启动的子进程,结束时用它停止实验,不按模糊名称终止其他服务。
完整配置与首次请求
cat > nginx.conf <<'EOF'
worker_processes 1;
pid /lab/nginx.pid;
error_log /lab/error.log warn;
events { worker_connections 256; }
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
gzip on;
gzip_min_length 1024;
gzip_comp_level 4;
gzip_vary on;
gzip_types text/plain text/css application/javascript application/json;
client_body_temp_path /lab/client-temp;
proxy_temp_path /lab/proxy-temp;
fastcgi_temp_path /lab/fastcgi-temp;
uwsgi_temp_path /lab/uwsgi-temp;
scgi_temp_path /lab/scgi-temp;
log_format route '$host $request_method $uri status=$status '
'upstream=$upstream_addr us=$upstream_status '
'rt=$request_time urt=$upstream_response_time';
access_log /lab/access.log route;
proxy_cache_path /lab/cache keys_zone=public_cache:1m max_size=16m inactive=1m;
map $http_authorization $has_auth { default 1; '' 0; }
map $http_cookie $has_cookie { default 1; '' 0; }
limit_req_zone $binary_remote_addr zone=per_client:1m rate=1r/m;
upstream demo { server 127.0.0.1:18081; keepalive 4; }
server {
listen 127.0.0.1:18080 default_server;
server_name _;
return 404;
}
server {
listen 127.0.0.1:18080;
server_name app.lab.test;
root /lab/html;
index index.html;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Forwarded "";
location = /entry-health { default_type text/plain; return 200 'entry-v1\n'; }
location ^~ /assets/ { try_files $uri =404; }
location /files/ { alias /lab/files/; }
location ^~ /api/ { proxy_pass http://demo/; }
location /keep/ { proxy_pass http://demo; }
location /slow { proxy_pass http://demo; proxy_read_timeout 1s; }
location /broken { proxy_pass http://127.0.0.1:18082; }
location /public/ {
proxy_pass http://demo;
proxy_cache public_cache;
proxy_cache_valid 200 30s;
proxy_cache_bypass $has_auth $has_cookie;
proxy_no_cache $has_auth $has_cookie;
add_header X-Cache $upstream_cache_status always;
}
location /limited {
limit_req zone=per_client;
limit_req_status 429;
proxy_pass http://demo;
}
location ~* \.js$ { return 403; }
location / { try_files $uri $uri/ =404; }
}
}
EOF
nginx -t -p /lab/ -c /lab/nginx.conf
nginx -p /lab/ -c /lab/nginx.conf默认站点拒绝未知 Host。业务站点使用保留的测试名称,通过 --resolve 指定本次连接地址,不需要注册域名。-q 禁止默认 curlrc,--noproxy '*' 排除代理,--fail-with-body 让预期成功请求遇到 HTTP 错误时非零退出。
curl -q --noproxy '*' --fail-with-body --silent --show-error \
--resolve app.lab.test:18080:127.0.0.1 http://app.lab.test:18080/
curl -q --noproxy '*' --fail-with-body --silent --show-error \
--resolve app.lab.test:18080:127.0.0.1 'http://app.lab.test:18080/api/orders?limit=2'分别得到 entry-v1 和 path 为 /orders?limit=2 的 JSON。若上游刚启动尚未监听,先检查进程和 /lab/error.log,再用相同请求重试。
server、location 与文件路径
HTTP 请求先按监听地址和端口确定候选站点,再按主机名选择;未匹配时使用该监听地址的默认站点。server_name _ 只是约定名称,默认身份由 default_server 决定。HTTPS 在 HTTP 字段到达前先握手,SNI 还参与证书和相关配置选择。请求处理说明
实验采用平级 location,匹配规范化 URI 路径,不匹配查询参数:
= 精确命中 → 使用该 location
否则记录最长前缀
├── 带 ^~ → 使用前缀,不检查本层正则
└── 普通前缀 → 按配置顺序检查正则
├── 首个正则命中 → 使用正则
└── 都不命中 → 使用最长前缀嵌套 location 涉及逐层搜索,不能直接套这张平级表。index、try_files 最后一个 URI、rewrite ... last 等可能触发内部重定向,再次选择配置。$request_uri 保留原始 URI,$uri 可能在处理过程中改变。核心模块指令
| 请求 | 预期 | 配置作用 |
|---|---|---|
/entry-health | 200,entry-v1 | 精确匹配 |
/assets/app.abc123.js | 200,asset-ok | ^~ 阻止 .js 正则接管 |
/other.js | 403 | 正则命中 |
/files/manual.txt | 200,alias-ok | alias 替换前缀 |
/missing | 404 | 文件不存在 |
Host 改为 unknown.lab.test | 404 | 默认站点拒绝 |
负例不使用 fail 选项,分别检查传输退出码和 HTTP 状态:
status=$(curl -q --noproxy '*' --silent --show-error --max-time 5 \
--resolve app.lab.test:18080:127.0.0.1 \
-o /lab/negative-body -w '%{http_code}' http://app.lab.test:18080/other.js)
transport=$?
test "$transport" -eq 0 && test "$status" = 403
printf 'transport=%s status=%s\n' "$transport" "$status"root /lab/html 加上 /assets/app.abc123.js 得到 /lab/html/assets/app.abc123.js。alias /lab/files/ 则将 /files/ 替换成目录,得到 /lab/files/manual.txt。每一级目录需要 worker 的搜索权限,文件需要读权限。
SPA 可以用 try_files $uri $uri/ /index.html 处理前端路由;JS、CSS 和 API 应分别返回真实错误,不能把缺失资源兜底成 HTML。否则状态虽为 200,浏览器仍会因脚本内容错误而无法执行。前端部署进一步解释发布与资源版本的配合。
上游连接与请求处理
URI 转换和可信字段
普通前缀 location 中,proxy_pass 带 URI 时,用该 URI 替换匹配前缀;不带 URI 时通常传递原请求 URI。实验 /api/orders 变成 /orders,/keep/orders 保持不变。正则、命名 location、变量形式及 rewrite 改写不能直接套用此前缀规则。代理模块
curl -q --noproxy '*' --fail-with-body --silent --show-error \
--resolve app.lab.test:18080:127.0.0.1 \
-H 'X-Forwarded-For: 203.0.113.99' http://app.lab.test:18080/api/orders返回的 xff 应为 127.0.0.1。实验把 Nginx 当作唯一可信入口,因此覆盖客户端传入的地址,并清除 Forwarded。应用只信任来自这个代理的转发信息,后端端口也要限制直接访问。
Nginx 位于可信负载均衡之后时,$remote_addr 最初是负载均衡地址。应通过 set_real_ip_from 限定可信来源,再选择 real_ip_header 与递归规则;不能信任所有客户端的 X-Forwarded-For。处理后的地址还影响日志、限流和访问控制。Real IP 模块
Host、转发协议和外部端口决定应用生成的绝对跳转与回调地址。TLS 在更前方终止时,本段 $scheme 可能只是 HTTP,应采用上游经过清洗的可信字段,不能把它解释为用户原协议。
超时、缓冲、上传和长连接
| 指令 | 控制过程 |
|---|---|
proxy_connect_timeout | 建立上游连接 |
proxy_send_timeout | 相邻两次向上游写入之间的等待 |
proxy_read_timeout | 相邻两次从上游读取之间的等待 |
proxy_request_buffering | 是否先接收完整请求体再发送上游 |
proxy_buffering | 是否缓冲上游响应,必要时使用临时文件 |
读写超时不是整个请求的总时限。持续输出数据的响应可以远超 read timeout;应用仍需自己的总预算和取消策略。入口断开后,应用的数据库写入可能继续完成。
实验 /slow 在响应头前暂停两秒,Nginx 等待一秒后返回 504。用前面负例命令更换路径验证,error log 应出现 upstream timed out ... while reading response header。响应头已发给客户端后的超时可能表现为响应体截断,无法再承诺一个新的 504。
请求缓冲可能使用临时磁盘,响应缓冲可以减少慢客户端长时间占用上游连接。关闭缓冲适用于某些流式接口,却会改变背压和重试条件。SSE 可按独立路径关闭响应缓冲,由应用发送心跳;不要为一个接口改动全站。
上传同时受 client_max_body_size、应用 multipart 限制、临时目录容量和超时影响。入口允许 20 MiB、应用只允许 10 MiB 时,应用依然会拒绝;调整后要测试允许大小和超限请求两条路径。
WebSocket 需要真实支持该协议的上游。在 http 中定义 map,在目标 server 中加入 location:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}location /ws/ {
proxy_pass http://demo;
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 60s;
}实验 Python 服务不支持 WebSocket。实际接入后,在浏览器 F12 → Network → WS 查看 101、消息与断开原因;只构造 Upgrade 字段的 curl 不能验证完整会话。WebSocket 代理
proxy_set_header 只有在当前层完全没有同类指令时才从上层继承。因此 /ws/ 另设 Upgrade 等字段后,若应用还需要转发地址与协议,必须在该 location 补齐可信字段;不能假定 server 中的设置会逐项合并。重复配置可放入专用 include,再在每个代理 location 引用。
后端池、连接复用和重试
upstream 定义后端集合。默认加权轮询适合无状态请求;least_conn 比较活动连接数,但连接少不一定表示剩余 CPU 多。依赖本机内存的会话还需考虑节点故障,粘滞分配不能恢复丢失的状态。
双实例可采用下列结构,两个端口必须真实运行应用后才承接流量:
upstream orders {
zone orders 64k;
server 127.0.0.1:18081 max_fails=2 fail_timeout=10s;
server 127.0.0.1:18082 max_fails=2 fail_timeout=10s;
keepalive 16;
}keepalive 是每个 worker 保存的空闲上游连接数,不限制全部活动连接。HTTP/1.1 代理需允许连接复用,实验显式清除了 Connection: close。上游模块
max_fails 和 fail_timeout 根据请求失败做被动判断;达到条件后临时避开节点,窗口结束再尝试。失败是否计入取决于模块定义,不能把任意业务 4xx 都当作节点故障。只有一个节点的池会忽略这些失败控制参数,不能据此演示自动故障转移。
开源版本不能直接使用商业订阅的 health_check。发布时可标记节点 down、测试并重载,等待已有连接退出后再停应用。长连接需要额外的退出安排。
检查 proxy_next_upstream 时还要考虑请求是否已发送、响应是否已开始。允许 non_idempotent 重试可能重复 POST 写入,订单或支付须先设计业务幂等。增加重试次数也会增加尾延迟和上游压力。
两端 TLS 分别配置
客户端到 Nginx 的 TLS 不会自动保护 Nginx 到应用的连接。准备有效域名证书、完整链和私钥后,在目标 server 设置:
listen 443 ssl;
server_name api.example.com;
ssl_certificate /etc/nginx/certs/api.fullchain.pem;
ssl_certificate_key /etc/nginx/certs/api.key;
ssl_protocols TLSv1.2 TLSv1.3;私钥不放静态目录,按 master 身份限制读权限。Nginx 1.24 用 listen 443 ssl http2,1.25.1 起可用独立 http2 on,先检查版本和模块。HTTP/2 模块
代理 HTTPS 上游还需要验证身份:
proxy_ssl_server_name on;
proxy_ssl_name internal-api.example.com;
proxy_ssl_verify on;
proxy_ssl_trusted_certificate /etc/nginx/certs/upstream-ca.pem;
proxy_ssl_verify_depth 3;名称与上游证书匹配,CA 文件来自可信来源。代理模块默认不启用上游证书验证,只改 proxy_pass 为 HTTPS 不足以认证上游。签发、完整链、名称验证和续期参见 SSL / 证书。
缓存、限流与日志
响应能否共享
浏览器缓存保存客户端副本,proxy_cache 保存入口侧响应。带内容 hash 的文件可以长缓存,HTML 入口通常要求重新验证。no-cache 允许存储但复用前需验证,no-store 才禁止存储;immutable 要与内容变更时 URL 也改变的发布方式配合。HTTP 缓存规范
用 add_header 设置响应头时检查继承:Nginx 1.24 的当前层只要定义了 add_header,就不会继续继承上层同类配置。安全响应头和缓存头应一起核对,不能只确认新加的 X-Cache。响应头模块
对 /public/config 连续执行两次:
curl -q --noproxy '*' --fail-with-body --silent --show-error \
--resolve app.lab.test:18080:127.0.0.1 -D - \
http://app.lab.test:18080/public/config首次预期 X-Cache: MISS,有效期内再次为 HIT。增加 -H 'Authorization: Bearer lab-only' 后为 BYPASS。proxy_cache_bypass 控制读取旧缓存,proxy_no_cache 控制保存新响应,两个方向都需考虑;实验也绕过 Cookie 请求。
上游的 Cache-Control、Set-Cookie、Vary 会影响缓存处理,不要为提高命中率忽略它们。共享缓存键必须区分真正影响响应的条件;认证、个人资料等接口默认不启用共享缓存。允许 stale 响应前,先判断旧数据还能被业务接受多久。
共享内存区保存缓存键等元数据,响应文件放磁盘。max_size 是缓存管理目标,不是瞬时磁盘硬配额,仍需观察文件系统空间、inode 和增长速度。
限流必须真正经过处理阶段
实验 /limited 按客户端地址限制每分钟一次。在新启动且尚未请求该路径的容器中,连续请求应得到 200、429、429;重复实验需等桶恢复,刚 reload 也可能保留共享区中的限流状态。
for attempt in 1 2 3; do
curl -q --noproxy '*' --silent --show-error --max-time 5 \
--resolve app.lab.test:18080:127.0.0.1 -o /dev/null \
-w '%{http_code}\n' http://app.lab.test:18080/limited
done这里使用 proxy_pass,不要改成 return 200:提前返回可能在限流阶段之前结束请求。burst 提供突发容量,默认可能延迟处理;nodelay 让容量内突发立即通过,超出仍拒绝。请求限流模块
共享办公出口可能对应很多用户。先识别代理后的真实地址,再根据流量分布选择阈值;未经认证的用户名字段可被伪造,不宜直接作为可靠限流键。
压缩与观察
文本资源通常适合 gzip,图片和压缩包再次压缩收益有限。下面配置放在 http 中;测试资源必须足够大并符合 MIME 类型:
gzip on;
gzip_min_length 1024;
gzip_comp_level 4;
gzip_vary on;
gzip_types text/plain text/css application/javascript application/json;用带 Accept-Encoding: gzip 的真实 GET 保存响应头和响应体,观察 Content-Encoding、Vary;只发 HEAD 或请求不足阈值的小文件不能确认压缩效果。提高级别会消耗 CPU,含敏感反射内容的动态响应还需评估压缩侧信道。gzip 模块
实验已经启用这组配置,并准备了足够大的文本文件:
curl -q --noproxy '*' --fail-with-body --silent --show-error --max-time 5 \
--resolve app.lab.test:18080:127.0.0.1 -H 'Accept-Encoding: gzip' \
-D gzip.headers -o response.gz http://app.lab.test:18080/assets/large.txt
grep -iE '^(Content-Encoding|Vary):' gzip.headers
gzip -dc response.gz | cmp - html/assets/large.txt预期响应头包含 Content-Encoding: gzip、Vary: Accept-Encoding,解压比较无输出且退出码为 0。若压缩未发生,检查资源大小、MIME、客户端字段与实际加载配置,而不是只看 gzip on 是否出现在文件中。
访问日志的 status 是最终客户端状态,upstream_status 是上游结果;多次上游尝试可能产生多个地址、状态和耗时。request_time 包含 Nginx 处理全过程,不能直接当作应用执行时间。静态请求通常显示 upstream=-。
tail -n 20 /lab/access.log
tail -n 20 /lab/error.log生产日志记录请求 ID、路径、状态及上游耗时,避免记录凭据、Cookie 和敏感查询参数。轮转后用 nginx -s reopen 重新打开文件;删除仍被进程持有的日志不一定释放空间。日志模块
运行变更与故障恢复
配置文件与实际响应分别验证
在实验容器保留旧配置,把探针改成 v2:
cp nginx.conf nginx.conf.previous
sed -i "s/return 200 'entry-v1/return 200 'entry-v2/" nginx.conf
nginx -t -p /lab/ -c /lab/nginx.conf
curl -q --noproxy '*' --fail-with-body --silent --show-error \
--resolve app.lab.test:18080:127.0.0.1 http://app.lab.test:18080/entry-health
nginx -p /lab/ -c /lab/nginx.conf -s reload重载前仍为 entry-v1。重载后建立新连接再次请求,预期为 v2;信号发送与 worker 切换存在时间差,不能把命令退出当作响应已更新。
磁盘配置 → 检查 → master 尝试加载
├── 失败 → 旧配置继续服务
└── 成功 → 新 worker 接收新连接
旧 worker 完成已有连接后退出把 invalid_directive; 加到配置末尾再执行 nginx -t,预期非零;不要 reload,运行入口仍能返回 v2。恢复旧配置并重载后,探针应回到 v1:
cp nginx.conf.previous nginx.conf
nginx -t -p /lab/ -c /lab/nginx.conf && \
nginx -p /lab/ -c /lab/nginx.conf -s reload生产变更也先保留配置、证书和模块依赖,再测试、sudo systemctl reload nginx、验证本机和外部业务请求。配置测试不会逐个验证上游可用。普通静态文件内容更新通常不需要重载,但文件缓存、软链和客户端缓存会影响观察。
从响应来源定位
| 现象 | 首查内容 | 修复与复测 |
|---|---|---|
| TCP 连接失败 | 地址、监听、代理与网络路径 | 恢复正确监听或访问路径,再按原 Host 请求 |
| 403 | error log 权限、directory index 或上游状态 | namei -l 检查真实父目录,按 worker 身份修权限 |
| 404 | Host、路径映射与 upstream 状态 | 修正站点或路径,同时验证存在与缺失资源 |
| 502 | 连接拒绝、提前关闭、无可用节点、上游 TLS | 从 Nginx 网络空间访问正确上游,再修连接配置 |
| 504 | error log 的 connect/read/send 阶段 | 修对应阻塞,以相同负载与预算复测 |
| 413 | 请求大小、入口和应用限制 | 统一允许范围与临时存储,验证上下界 |
| 429 | 限流日志、客户端地址和限流键 | 确认共享代理地址,再调整范围与阈值 |
| TLS 失败 | SNI、实际服务证书与信任链 | 在 HTTP 之前修复握手问题 |
/broken 指向没有监听的 18082,预期 502 和连接拒绝日志。改成实际运行的 18081,测试并重载后应恢复 JSON。/slow 则对应响应头读取超时;504 也可能出现在建立连接阶段,必须读取错误日志中的具体过程。
SELinux 环境检查 getenforce、sudo ausearch -m avc -ts recent 和文件标签。按发行版策略设置静态目录标签、评估代理连接权限,不用关闭 SELinux 或全目录 chmod 777 修复。
容器场景从容器视角检查路径和上游。静态解析的主机名可能仍指向旧容器 IP;应用重建后,根据版本选择动态解析或重载,不能把服务名不变理解为连接地址永久不变。
容量判断联合观察连接数、延迟、上游错误、worker CPU、描述符、内存和临时磁盘。压测应经过相同的 TLS、压缩、缓存及应用路径,缓存命中的静态测试不能代表动态接口能力。
实验结束只停止本次进程,再退出容器:
nginx -p /lab/ -c /lab/nginx.conf -s quit
kill "$upstream_pid"
wait "$upstream_pid" 2>/dev/null || true
exitquit 请求优雅退出,stop 是快速退出。--rm 删除实验容器可写层,镜像与宿主 Dockerfile 保留;没有业务数据卷或宿主服务需要清理。
权威资料与规范地址
安装与进程管理
| 查阅内容 | 官方地址 |
|---|---|
| 进程、信号与重载 | https://nginx.org/en/docs/control.html |
| Linux 软件包 | https://nginx.org/en/linux_packages.html |
| 命令行参数 | https://nginx.org/en/docs/switches.html |
