Yihui’s Blog

Spring Cloud Gateway 500 问题排查

日期:2026-07-11
标签:#面试 #八股 #SpringCloudGateway #后端 #线上问题排查

一句话答案

先用 requestId 和 Gateway 日志判断 500 是网关自身、过滤器还是下游返回,再排查路由、服务发现、超时、连接池、响应提交和 Reactor 阻塞。

面试口语版

我先确认状态码由谁产生:看网关 access log、异常栈、Trace 和下游日志,若下游根本没收到请求,重点查路由 Predicate、服务发现、DNS、TLS 和 Netty 连接池;若过滤器报错,检查空指针、鉴权、请求体重复读取和响应已提交后再次写入;若下游返回 500,则沿下游排查。还要看 Reactor 线程是否执行阻塞数据库或文件操作、是否连接池耗尽和超时。应急可回滚过滤器、切备用路由、降级并保留错误体和异常类型指标。

关键细节

  • Gateway 是响应式模型,阻塞 reactor-http-nio 线程会影响大量请求。
  • 请求/响应 Body 通常只能消费一次,修改时要正确装饰 exchange。
  • onErrorResume 不能吞掉真实异常并统一伪装为 500。
  • 监控按 routeId、异常类型、下游状态和阶段拆分。

面试官追问

  1. 如何判断 500 是网关还是下游产生?
  2. 为什么在 Gateway 过滤器中调用阻塞代码危险?
  3. 响应已经 committed 后还能改状态码吗?

面试官追问参考答案

1. 如何判断 500 是网关还是下游产生?

通过 requestId/Trace 查下游是否收到请求及返回码,网关 access log 记录路由 ID、代理耗时和 upstream status。无下游 Span 且网关有异常栈通常是网关问题;下游明确返回 500 则网关只是透传。

2. 为什么在 Gateway 过滤器中调用阻塞代码危险?

少量 Netty EventLoop 承载大量连接,阻塞一个线程会让其负责的其他请求都无法推进,产生级联延迟。应使用非阻塞客户端,确实阻塞的短任务切到受控 boundedElastic,并限制并发。

3. 响应已经 committed 后还能改状态码吗?

通常不能,响应头已发送后再修改会失败或无效。过滤器应在写出前完成鉴权和错误映射,使用 beforeCommit 或正确的响应装饰器,异常处理需判断 isCommitted。

学习清单

  • 能按路由、过滤器、网络和下游分层排查。
  • 理解 Reactor EventLoop 与响应提交时机。
维护与整理 · Yihui在 GitHub 上编辑

继续阅读

浏览全部文章