LabHub
学习 学习路径 课程

Tomcat 与 nginx 运维

配置 nginx 反向代理

在 LabHub 中继续学习

目标

能够将 nginx 配置为反向代理,并按照生产实践配置转发请求头、超时、正文大小、压缩、静态资源分离、 访问阻止和日志格式。

为什么重要

六行代理配置不应靠背诵,而应通过缺少它们时会发生什么来记忆。 如果不转发 Host,应用程序生成的绝对 URL 会变成 127.0.0.1:8080, 导致支付回调无法返回。如果没有 X-Forwarded-For,所有访问记录都会显示为代理 IP, 审计时将无从回答。如果没有 X-Forwarded-Proto,则会发生无限重定向循环。 此外,如果不知道 client_max_body_size 的默认值是 1MB,就可能在后端日志毫无记录的情况下, 花费数天排查文件上传故障。

步骤

  1. 准备:启动 Tomcat,并将 /opt/lab/samples/labhub-1.0.0.war 部署为 /opt/tomcat/webapps/labhub.war。 nginx 工作目录使用 /root/ng
  2. 编写 /root/ng/nginx.conf 并启动 nginx。 监听端口 8088,并将 / 代理到 http://127.0.0.1:8080http://127.0.0.1:8088/labhub/version 必须返回 200。
  3. 配置四个代理请求头并 reload。 HostX-Real-IPX-Forwarded-ForX-Forwarded-Proto。 检查:curl -s http://127.0.0.1:8088/labhub/echo 返回的 JSON 中 必须包含 x-forwarded-forx-forwarded-proto, 且 host 的值不能是 127.0.0.1:8080
  4. 配置 proxy_connect_timeout 3sproxy_send_timeout 30sproxy_read_timeout 60s
  5. client_max_body_size 设置为 20m 并 reload。 5MB 正文的 POST 不应返回 413,25MB 正文的 POST 必须返回 413
  6. 配置 gzip ongzip_min_length 1000gzip_vary on, 并在 gzip_types 中加入 application/jsoncurl -H 'Accept-Encoding: gzip' -I http://127.0.0.1:8088/labhub/big.html 的 响应中必须包含 Content-Encoding: gzip
  7. 创建 /root/ng/static/app.js 文件(内容不限), 并将其配置为通过 /assets/ 路径提供服务。也就是说, http://127.0.0.1:8088/assets/app.js 必须返回 200, 且响应头中必须包含 ExpiresCache-Control
  8. 配置所有以 /manager/ 开头的请求返回 403http://127.0.0.1:8088/manager/html 必须返回 403。
  9. 定义 log_format,使其包含 $upstream_addr$upstream_status$upstream_response_time$request_time 四个变量, 并将访问日志写入 /root/ng/logs/access.log。 reload 后发送一次请求,日志必须确实得到写入。

参考

最小代理配置与启动

编写 /root/ng/nginx.conf 并启动 nginx。 监听端口 8088,并将 / 代理到 http://127.0.0.1:8080http://127.0.0.1:8088/labhub/version 必须返回 200。

nginx 可以用 -c 指定配置文件,用 -p 指定 prefix(相对路径的基准)。请记住,此环境无法绑定低于 1024 的端口。养成启动前先用 -t 检查语法的习惯。

配置转发请求头

配置四个代理请求头并 reload。 HostX-Real-IPX-Forwarded-ForX-Forwarded-Proto。 检查:curl -s http://127.0.0.1:8088/labhub/echo 返回的 JSON 中 必须包含 x-forwarded-forx-forwarded-proto, 且 host 的值不能是 127.0.0.1:8080

有一个端点可以确认后端实际收到了什么。请亲自检查不转发 Host 时,后端看到的 Host 会是什么。

三类代理超时

配置 proxy_connect_timeout 3sproxy_send_timeout 30sproxy_read_timeout 60s

连接、发送、读取超时分别测量不同区段。思考 504 与其中哪一种关系最密切。

限制请求正文大小

client_max_body_size 设置为 20m 并 reload。 5MB 正文的 POST 不应返回 413,25MB 正文的 POST 必须返回 413

超过此限制时,nginx 会直接响应,因此后端日志中不会留下任何痕迹。只有知道默认值是多少,才能迅速定位文件上传故障。

压缩响应

配置 gzip ongzip_min_length 1000gzip_vary on, 并在 gzip_types 中加入 application/jsoncurl -H 'Accept-Encoding: gzip' -I http://127.0.0.1:8088/labhub/big.html 的 响应中必须包含 Content-Encoding: gzip

小于最小长度标准的响应不会被压缩。还需要同时启用一个用于防止缓存异常的指令。

分离静态文件

创建 /root/ng/static/app.js 文件(内容不限), 并将其配置为通过 /assets/ 路径提供服务。也就是说, http://127.0.0.1:8088/assets/app.js 必须返回 200, 且响应头中必须包含 ExpiresCache-Control

当 location 路径与实际目录名不同时,可以使用一个相应的指令。还要一并设置缓存过期响应头。

阻止管理路径

配置所有以 /manager/ 开头的请求返回 403http://127.0.0.1:8088/manager/html 必须返回 403。

在代理处阻止访问,无需部署应用程序即可更改策略。请思考正则表达式 location 与前缀 location 的优先级。

用于故障分析的日志格式

定义 log_format,使其包含 $upstream_addr$upstream_status$upstream_response_time$request_time 四个变量, 并将访问日志写入 /root/ng/logs/access.log。 reload 后发送一次请求,日志必须确实得到写入。

只有同时记录后端耗时和总耗时,才能区分“后端缓慢”和“传输缓慢”。要产生日志,必须实际发送请求。