Nginx:静态站点与反向代理配置 · 请求行为矩阵与失败预期至实践练习与参考解答
本篇以Nginx 静态站与代理为例;前置是主配置、conf_prefix、Host/SNI 和上游地址。源码与输入与下文配置共用同一份文件,示例未执行。
前置为路径与代理语义。示例未执行;Nginx配置未由nginx -t检验。
请求行为矩阵与失败预期
Nginx 请求行为需要同时核对客户端状态、上游目标与日志来源,不能只看到200就判断路由正确。以下是设计预期,尚未发送这些请求:
| 请求(Host为lab.local) | 预期 | 解释 |
|---|---|---|
| GET / | 200根页面 | index处理公开首页 |
| GET /missing | 404 | 普通静态位置try_files结束 |
| GET /app/lesson | 200应用壳 | 内部重定向到/app/index.html |
| GET /download/guide.txt | 200文本 | 精确alias映射固定文件 |
| GET /.git/config | 404 | 隐藏路径正则拒绝 |
| GET /api | 308 | 固定跳转到/api/,不拼Host |
| GET /api/status?mode=brief | 200 JSON | 上游收到/status?mode=brief |
| GET /api/fail | 503 JSON | 上游有意拒绝,代理不重试 |
| GET /api/slow | 504 | 预期等待响应头超过5秒 |
| GET /api/status,上游未启动 | 502 | 连接被拒绝,须看error.log |
| GET /healthz,上游未启动 | 200 | 只证明入口存活 |
| 任一路径,Host为unknown | 404 | 默认server拒绝 |
上游关闭、操作系统调度和客户端取消可能改变故障细节,具体状态以未来实测日志为准。HEAD不应有响应体;读取请求头、发送头、客户端断开也可能发生在设计超时之前。
读者自跑、TLS与清理
Nginx 自跑步骤只为读者提供,当前未执行。README完整列出复制前提、普通用户启动、nginx -t、请求对照和按相同prefix优雅退出的命令。不要在已有系统实例里试错,不使用全局进程终止。TLS可选主配置与HTTP配置共用PID,因此先停止一套再启动另一套。
md
# Nginx 理论示例(未执行)
只提供文件与预期行为,不是运行验收。Nginx 配置未由 nginx -t 检验;AST/JSON/模板检查不能证明指令、权限、模块、TLS 或网络正确。
依赖:Linux 用户空间、已由读者安装的受维护 Nginx Open Source(本文按1.28/1.29族共同指令解释)、下文 /api 反向代理步骤还需要已安装的 Node.js >=22 来运行 upstream.mjs;仅查看静态文件配置时不需要 Node.js。没有 npm 依赖,无需 npm install。TLS另要求http_ssl模块、支持TLS1.3的OpenSSL以及读者合法取得的证书链和匹配私钥。此目录不含证书或私钥。Windows原生Nginx是官方beta实现,配置需要自行替换绝对路径并检查模块;不将Linux运行方式称为Windows已验证。
以下是读者以后自跑的Linux shell说明,本轮没有执行:
```sh
# 从仓库根目录开始;目标必须不存在,避免覆盖任何已有环境。
test ! -e /tmp/m5-nginx || exit 1
cp -R examples/m5-nginx /tmp/m5-nginx
mkdir -p /tmp/m5-nginx/logs /tmp/m5-nginx/temp/client /tmp/m5-nginx/temp/proxy
# 以普通用户运行;8088、9088必须空闲,目录归该用户,不使用sudo。
node /tmp/m5-nginx/upstream.mjs
```
保留上游前台窗口,在另一个终端进行下一组操作:
```sh
nginx -p /tmp/m5-nginx/ -c nginx.conf -t
nginx -p /tmp/m5-nginx/ -c nginx.conf
curl --fail-with-body -H 'Host: lab.local' http://127.0.0.1:8088/
curl --fail-with-body -H 'Host: lab.local' 'http://127.0.0.1:8088/api/status?mode=brief'
```
读者应检查根页200、/app/lesson应用壳200、/missing为404、/download/guide.txt固定文件200、/.git/config为404、Host: unknown为404。只读API收到/status?mode=brief,返回ok=true;/api/fail预期503,/api/slow预期504(Nginx先等待5秒超时),上游未启动时/api/status预期502。/healthz仅证明Nginx响应,不证明上游健康。每次保留access.jsonl与error.log,对照课程诊断。
可选TLS:读者创建certs目录,将签发给lab.local且在有效期内的完整链命名lab-fullchain.pem、对应私钥命名lab-key.pem,并按运行用户最小可读设置私钥权限;本仓库不提供证书生成命令。先退出HTTP实例,再对nginx-tls.conf执行同样的-t及启动步骤,不能两套主配置同时运行,因为共享PID与日志。客户端用可信CA文件与curl --resolve lab.local:8443:127.0.0.1 --cacert /绝对路径/lab-ca.pem https://lab.local:8443/;不要用-k替代信任链验证。未知SNI预期握手被拒绝。
清理:读者对自己启动的前缀执行nginx -p /tmp/m5-nginx/ -c nginx.conf -s quit(TLS时换对应主配置),在上游窗口按Ctrl+C,确认专用进程结束,归档日志后只删除自己创建的/tmp/m5-nginx目录。不要使用全局pkill或删除其他Nginx配置。reload、reopen和quit必须指向相同前缀/PID,不能混用系统服务与这个教学实例。nginx
worker_processes 1;
pid logs/nginx.pid;
error_log logs/error.log warn;
events { worker_connections 256; }
http {
include conf/http-common.conf;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_session_cache shared:LABTLS:1m;
ssl_session_tickets off;
server {
listen 127.0.0.1:8443 ssl default_server;
ssl_reject_handshake on;
return 404;
}
server {
listen 127.0.0.1:8443 ssl;
server_name lab.local;
ssl_certificate certs/lab-fullchain.pem;
ssl_certificate_key certs/lab-key.pem;
include conf/site.conf;
}
}实践练习与参考解答
练习:不启动服务,画出/api/status、/app/lesson与/download/guide.txt各自经过的文件和处理器,说明为什么只有第一个请求需要Node进程。
参考解答:三个请求先经nginx.conf选择lab.local,再进入site.conf;API去lab_backend并替换前缀,app经try_files内部重定向至root内的应用壳,download直接命中精确alias。后两者由Nginx读文件,无Node依赖。以后读者验收要同时确认静态缺失404和上游缺失404来源不同,而非只验成功首页。
继续阅读
- 排错
- 知识专题
- 知识专题