网关路由是怎么匹配的?多个谓词是与还是或?后端能看到客户端真实 IP 吗?后端挂了网关返回 502 还是 500?为什么按老文章写的 spring.cloud.gateway.routes 一条路由都不生效?这篇在 Spring Boot 4.0.8、Spring Cloud Gateway 5.0.3 上用一个会记录请求的后端逐项实测。
GET /api/orders/42(StripPrefix=1) → 网关返回 200,后端收到 GET /orders/42
GET /h/a/b(AddRequestHeader + RewritePath + AddResponseHeader) → 网关返回 200,后端收到 GET /echo/a/b;x-from=gw
网关返回的响应头里 x-resp = yes,x-backend = yes
GET /pre/x(StripPrefix=1 再 PrefixPath=/v2) → 网关返回 200,后端收到 GET /v2/x
POST /pre/x(Method=GET 的路由不匹配 POST) → 网关返回 404 {"timestamp":"2026-10-22T01:08:35.823Z","path":"/pre/x","status":404,"error":"Not Found",",后端没有收到请求
GET /c/q 带 X-Canary: 7 与 ?debug=1(Header 正则 + Query 同时满足) → 网关返回 200,后端收到 GET /canary-hit?debug=1
GET /c/q 带 X-Canary: abc(Header 正则不满足) → 网关返回 404 {"timestamp":"2026-10-22T01:08:36.157Z","path":"/c/q","status":404,"error":"Not Found","re,后端没有收到请求
GET /c/q 带 X-Canary: 7 但没有 ?debug(Query 不满足) → 网关返回 404 {"timestamp":"2026-10-22T01:08:36.311Z","path":"/c/q","status":404,"error":"Not Found","re,后端没有收到请求
GET /nothing(没有任何路由匹配) → 网关返回 404 {"timestamp":"2026-10-22T01:08:36.470Z","path":"/nothing","status":404,"error":"Not Found",后端没有收到请求谓词是与关系;StripPrefix、PrefixPath、SetPath、RewritePath 改路径;AddRequestHeader / AddResponseHeader 改头。
客户端发 Host: gw.example.com、X-Custom: abc、Accept: application/json;后端收到的请求头:accept: application/json; accept-encoding: identity; host: 127.0.0.1:50633; user-agent: ReactorNetty/1.3.7; x-custom: abc
客户端自己带 X-Forwarded-For: 1.2.3.4 和 Forwarded: for=9.9.9.9,没配 trusted-proxies:后端收到的 forwarded 相关头 = {}
配 trusted-proxies=.* 之后(客户端 Host: gw.example.com):后端收到 forwarded: proto=http;host=gw.example.com;for="127.0.0.1:50848"; x-forwarded-for: 127.0.0.1; x-forwarded-host: gw.example.com; x-forwarded-port: 80; x-forwarded-prefix: /api; x-forwarded-proto: http
同样配置,客户端自己带 X-Forwarded-For: 1.2.3.4:后端收到 x-forwarded-for = 1.2.3.4,127.0.0.1
加上 PreserveHostHeader 过滤器,后端收到的 host = gw.example.com默认不转发 Forwarded;trusted-proxies 打开后才加;Host 默认是后端自己的。
两条路由都匹配 /api/x,按声明顺序 first、second → 命中的是 first 给 second 设 order=-1 → 命中的是 second
order 小的在前,同 order 按声明顺序。
后端端口不可连接(127.0.0.1:1) → 网关返回 500,耗时 1.2 秒,响应体 {"timestamp":"2026-10-22T01:09:10.123Z","path":"/dead/x","status":500,"error":"Internal Server Error","requestId":"8034367e-1"}
后端 3 秒才响应,response-timeout=1s → 网关返回 504,耗时 1.0 秒,响应体 {"timestamp":"2026-10-22T01:09:11.228Z","path":"/slow/x","status":504,"error":"Gateway Timeout","requestId":"b25cfe6d-2"}连不上 500,响应超时 504。
路由写在旧前缀 spring.cloud.gateway.routes 下,GET /api/orders/1 → 网关返回 404 {"timestamp":"2026-10-22T01:09:15.603Z","path":"/api/orders/1","status":404,"error":"Not F,后端没有收到请求
只配了 management.endpoints.web.exposure.include=gateway:GET /actuator → 200 {"_links":{"self":{"href":"http://127.0.0.1:9613/actuator","templated":false}}};GET /actuator/gateway/routes → 404
再加 management.endpoint.gateway.access=unrestricted:GET /actuator/gateway/routes → 200 [{"predicate":"(RouteDefinitionRouteLocator$$Lambda/0x0000008001616b48 && Paths: [/api/**], match trailing slash: true)","route_id":"orders","filters":["[[StripPrefix parts = 1], order = 1]"],"uri":"http://127.0.0.1:50633","order":0}]新前缀 spring.cloud.gateway.server.webflux;gateway 端点要 access=unrestricted。