Spring Cloud API Gateway 无法调用后端实际微服务问题咨询
结合当前使用的Spring Boot 2.4.2 + Spring Cloud 2020.0.2版本的组件特性,按优先级从高到低排查修复即可:
1. 缺失负载均衡依赖导致路由无法解析
Spring Cloud 2020.x版本开始,原Netflix Ribbon负载均衡组件进入维护状态,官方替换为Spring Cloud LoadBalancer机制。当前网关模块的依赖列表中未引入LoadBalancer相关依赖,导致网关无法识别lb://服务名格式的URI,即使服务全部注册到Eureka,也无法解析对应服务的实例列表完成转发。
- 修复方式:在网关模块的
pom.xml中新增spring-cloud-starter-loadbalancer依赖
2. 非必要依赖引发的Web运行栈冲突
当前网关模块引入了spring-cloud-starter-config-server依赖,该依赖属于配置中心服务端组件,会引入Spring MVC的Servlet运行栈。而Spring Cloud Gateway是基于WebFlux的响应式Netty栈实现的,一旦classpath下存在MVC相关依赖,Spring Boot会自动切换为Servlet运行模式,直接导致网关的路由过滤器自动装配失效,所有转发功能完全不可用。
- 修复方式:
- 从网关模块
pom.xml中移除spring-cloud-starter-config-server依赖,仅保留Config Client相关配置即可 - 启动时核对日志,确认Netty作为Web容器启动成功,如果日志显示Tomcat启动则说明运行栈切换失败,需移除所有MVC相关依赖
- 从网关模块
3. 自定义Bean覆盖网关自动装配配置
网关主启动类中自定义的ServerCodecConfigurer Bean属于历史老版本网关的特殊配置,当前版本下该自定义Bean会覆盖网关自动装配的HTTP请求编解码逻辑,导致请求转发时参数解析异常。
- 修复方式:删除主启动类中自定义的
ServerCodecConfigurerBean,保留默认的自动装配配置即可
4. Eureka注册配置参数误用
后端部门服务中配置的eureka.instance.ip-address=true属于参数误用:eureka.instance.ip-address是静态指定注册IP的字符串参数,并非功能开关。该配置会导致服务注册到Eureka时,主机名被设置为字符串"true",网关拉取到的服务实例地址无效,无法连接后端服务。
- 修复方式:
- 从部门服务配置中移除错误的
eureka.instance.ip-address=true配置项 - 如果需要服务注册时使用IP地址而非主机名,正确的配置为
eureka.instance.prefer-ip-address=true - 打开Eureka控制台核对服务注册的实例地址,确认格式为
IP:端口的有效地址即可
- 从部门服务配置中移除错误的
5. 路由加载验证
如果上述依赖和栈冲突的问题修复后仍无法转发,可按以下逻辑核对路由匹配是否正常:
- 当前网关开启的服务发现自动路由规则,仅会匹配
/注册服务ID/**格式的路径(比如访问http://localhost:9191/department-service/departments/123才会被自动路由处理),和手动配置的/departments/**路径无匹配冲突 - 确认手动配置的路由是否被正确加载:通过
http://localhost:9191/actuator/gateway/routes接口查看已加载的路由列表,确认是否存在id为department-service的路由项 - 注意Spring Cloud 2020.x版本默认使用
PathPatternParser做路径匹配,对尾斜杠的处理更严格:比如后端服务的PostMapping路径为/departments/,需要确保请求路径和后端映射完全一致,避免因斜杠不匹配导致的请求失败。
快速排查技巧:启动网关时将
org.springframework.cloud.gateway包的日志级别设为debug,可以直观看到每个请求的匹配路径、选中的路由规则、转发目标地址,快速定位匹配失败的原因。
内容的提问来源于stack exchange,提问作者PAA

