日期: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、异常类型、下游状态和阶段拆分。
面试官追问
- 如何判断 500 是网关还是下游产生?
- 为什么在 Gateway 过滤器中调用阻塞代码危险?
- 响应已经 committed 后还能改状态码吗?
面试官追问参考答案
1. 如何判断 500 是网关还是下游产生?
通过 requestId/Trace 查下游是否收到请求及返回码,网关 access log 记录路由 ID、代理耗时和 upstream status。无下游 Span 且网关有异常栈通常是网关问题;下游明确返回 500 则网关只是透传。
2. 为什么在 Gateway 过滤器中调用阻塞代码危险?
少量 Netty EventLoop 承载大量连接,阻塞一个线程会让其负责的其他请求都无法推进,产生级联延迟。应使用非阻塞客户端,确实阻塞的短任务切到受控 boundedElastic,并限制并发。
3. 响应已经 committed 后还能改状态码吗?
通常不能,响应头已发送后再修改会失败或无效。过滤器应在写出前完成鉴权和错误映射,使用 beforeCommit 或正确的响应装饰器,异常处理需判断 isCommitted。
学习清单
- 能按路由、过滤器、网络和下游分层排查。
- 理解 Reactor EventLoop 与响应提交时机。