Spring Cloud Gateway路由返回404,请求无法转发至下游微服务
问题描述
Spring Cloud Gateway配置路由规则后,日志显示路由已成功匹配,但请求转发至下游微服务时始终返回404错误。
网关配置代码
@SpringBootApplication public class TwoFactorAuthenticationServiceApplication { @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { return builder.routes() .route("path_route", r -> r.path("/two-factor-authentication-service-1.0/get") .uri("http://localhost:10270/wallet-management-service-1.0/api/system-wallet/get-wallet-address")) .route("host_route", r -> r.host("*.myhost.org") .uri("http://httpbin.org")) .build(); } public static void main(String[] args) { SpringApplication.run(TwoFactorAuthenticationServiceApplication.class, args); } }
请求关键日志片段
2022-09-21 15:13:35.349 TRACE 20640 --- [ XNIO-1 I/O-2] o.s.c.g.h.p.PathRoutePredicateFactory : Pattern "/two-factor-authentication-service-1.0/get" matches against value "/two-factor-authentication-service-1.0/get" 2022-09-21 15:13:35.350 DEBUG 20640 --- [ XNIO-1 I/O-2] o.s.c.g.h.RoutePredicateHandlerMapping : Route matched: path_route 2022-09-21 15:13:35.612 TRACE 20640 --- [ctor-http-nio-2] o.s.c.g.filter.GatewayMetricsFilter : spring.cloud.gateway.requests tags: [tag(httpMethod=GET),tag(httpStatusCode=404),tag(outcome=CLIENT_ERROR),tag(routeId=path_route),tag(routeUri=http://localhost:10270/wallet-management-service-1.0/api/system-wallet/get-wallet-address),tag(status=NOT_FOUND)]
排查解决步骤
直接验证下游服务可用性
复制日志中的目标接口地址http://localhost:10270/wallet-management-service-1.0/api/system-wallet/get-wallet-address,带上请求参数?userId=1951,用curl或Postman直接访问。如果直接访问也返回404,说明问题出在下游服务本身,需检查:- 下游服务是否正常启动
- 接口路径是否拼写错误
- 服务端口是否配置正确
修正Gateway路径转发规则
当前配置中,uri指定了完整的下游接口地址,但默认情况下Gateway会将匹配的路径追加到uri之后,导致实际请求地址变成:http://localhost:10270/wallet-management-service-1.0/api/system-wallet/get-wallet-address/two-factor-authentication-service-1.0/get
这显然不符合预期,需要添加rewritePath过滤器移除匹配的路径前缀,修改后的配置如下:@Bean public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { return builder.routes() .route("path_route", r -> r.path("/two-factor-authentication-service-1.0/get") .filters(f -> f.rewritePath("/two-factor-authentication-service-1.0/get", "")) .uri("http://localhost:10270/wallet-management-service-1.0/api/system-wallet/get-wallet-address")) .route("host_route", r -> r.host("*.myhost.org") .uri("http://httpbin.org")) .build(); }检查下游服务的访问日志
开启下游微服务的请求日志,查看Gateway转发过来的请求路径、参数是否和预期一致。如果路径不符,说明Gateway的路由规则仍有问题。验证请求参数传递
确认原请求的userId=1951参数是否被正确传递到下游服务。可以在下游接口中打印参数,或者直接带参数访问下游接口,验证参数是否有效。排查网络连通性
在Gateway所在服务器上,通过ping localhost或telnet localhost 10270测试与下游服务的网络连通性,排除防火墙拦截、端口未开放等问题。
内容的提问来源于stack exchange,提问作者Montaser Majid

