Nginx:403、404、502 与 504 定位
本节沿同一请求的状态、上游目标与访问日志定位失败层;先确认主配置、conf_prefix、Host/SNI 和上游地址,与配套示例逐项对照,再选择最小修复。
前置为日志字段。以下故障与结果是理论诊断,没有向本机或外部发送探测请求;静态审阅不能证明线上根因。
先固定请求与配置身份
Nginx 排错顺序是记录目标地址端口、Host/SNI、方法和路径,确认实际master使用的主配置与prefix,再看同一时间的access_log/error_log。请求号能关联上游,但不能由日志缺失直接断定请求未到达:日志可能关闭、路径错误、写失败或查询时间不一致。先界定哪一跳返回状态,再改配置。
Nginx 200也可能是错误的默认页或应用壳,所以核对Content-Type、正文来源与upstream字段。403、404、502、504并不自动对应一种根因,不凭状态码批量调整权限、放大超时或关闭证书验证。线上使用脱敏请求样本,避免把密码、Cookie或令牌贴到工单。
403、404与文件权限
Nginx 403常见于目录无首页且autoindex关闭,或worker无法遍历父目录、读取文件。Linux目录需要遍历权限,文件需要读取权限;还可能受SELinux/AppArmor或挂载限制。检查运行用户、每级目录、最终文件和安全审计,别用chmod -R 777或关闭安全机制消除症状。历史安装文的“父目录可遍历”经验仍适用。
Nginx 404要先区分静态缺失与上游返回。无upstream_addr时检查root/alias算出的实际路径、大小写和try_files;有upstream_status=404时检查proxy_pass URI替换后上游收到的目标。示例/api/status缺失尾斜线配置后会变为上游未知目标,修本地文件权限无效。未知Host默认站点也返回404,需先确认server选择。
502、504与上游时间
Nginx 502常见于连接被拒绝、提前断开、非法响应头或上游TLS握手失败;error.log的connect() failed、prematurely closed等细节比状态码更具体。示例未启动Node时预期连接127.0.0.1:9088失败,不是把proxy_read_timeout调成60秒就能修复。多机时还需核对网络命名空间与真实目标:容器中的127.0.0.1不是宿主机。
Nginx 504表示网关等待上游超时的常见结果;先区分连接、读头还是读体阶段,再结合connect_time/header_time/response_time与应用日志。示例/slow固定7秒不出响应头,读头5秒超时预期504;实际操作系统或客户端提前退出可能改变现象。应用已处理但响应中断时不能据504判定写入没发生,重试必须依赖幂等契约。
客户端主动中断常在Nginx日志记为499,这是Nginx使用的状态,不是正常发给客户端的标准HTTP响应。它可能来自客户端超时,也可能由慢上游间接导致,不能全部归咎用户网络。输出一部分响应后失败,Nginx也无法把已发送的200改成另一完整错误响应。
重定向循环、MIME与上传限制
Nginx 重定向循环先分内部与外部:error.log出现rewrite or internal redirection cycle通常检查try_files应用壳是否存在、rewrite last是否跳回自己;浏览器多次301/308则检查HTTP到HTTPS跳转、代理协议头及后端绝对URL。absolute_redirect默认on,本例显式设为off后,对/api与/app才返回固定相对Location,避免用不可信Host构造跳转目标。若复制配置时删掉该设置,不能继续用“固定相对响应头”解释默认行为。
Nginx MIME错误常是缺失脚本被应用壳回退成text/html,或types未包含扩展。先检查响应正文与选中location,再调整MIME,不能把所有响应default_type设为JavaScript。413则先核对命中server的client_max_body_size与上游自身限制;入口和应用可能各有限制,不能只改其中一层。
TLS失败与配置未生效
Nginx TLS排错按握手目标SNI、证书名称、有效期、完整中间链、客户端信任库和私钥匹配核对。HTTP Host正确不保证握手选中同一证书;示例未知SNI会主动拒绝。读者若仅使用IP请求而未设置SNI,得到握手失败并不证明证书内容损坏。不要用curl -k、proxy_ssl_verify off把验证错误当作已解决。
Nginx 配置未生效先找prefix、include路径、PID、error.log的reload失败记录,再确认请求是否到正确实例。nginx -t通过仅代表当时检查的那套文件,不证明随后reload操作了相同实例。worker还在读旧连接属于优雅退出的一部分;静态文件是否已替换、浏览器缓存和其他代理也要单独核查。
排错练习与参考解答
练习:/healthz为200而/api/status为502;/app/lesson为200但显示应用壳而非文章。分别最先检查哪里?
参考解答:前者证明入口存活,先核对upstream地址、error.log连接失败与上游是否存在;后者可能完全符合try_files设计,应先确认该请求是否本来就是虚拟路由,而不是将“200”当作文章已发布。两者都不应先重装Nginx。
继续阅读
- 知识专题
- 应用实践
- 应用实践