Spring Cloud Gateway集成Eureka无法路由请求至微服务排查
我正在开发一个包含多个微服务的项目,所有微服务均已注册至Eureka Discovery Server。将Spring Cloud Gateway配置为Eureka客户端并设置了路由规则,但通过网关发起的请求返回404错误,直接调用微服务则可正常响应。
现有配置信息
API Gateway的application.properties配置
eureka.client.service-url.defaultZone= http://localhost:8761/eureka/ spring.application.name=api-gateway server.port=8080 ##Product Service Route spring.cloud.gateway.routes[0].id=product-service spring.cloud.gateway.routes[0].uri=lb://product-service spring.cloud.gateway.routes[0].predicates[0]=Path=/api/product ##Order Service Route spring.cloud.gateway.routes[1].id=order-service spring.cloud.gateway.routes[1].uri=lb://order-service spring.cloud.gateway.routes[1].predicates[0]=Path=/api/order
ApiGateway启动类代码
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication @EnableDiscoveryClient public class ApiGatewayApplication { public static void main(String[] args) { SpringApplication.run(ApiGatewayApplication.class, args); } }
pom.xml依赖配置
<artifactId>api-gateway</artifactId> <properties> <maven.compiler.source>21</maven.compiler.source> <maven.compiler.target>21</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <spring-cloud.version>2023.0.0</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway-mvc</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build>
微服务配置与代码
两个微服务(order-service和product-service)均设置server.port=0随机分配端口,已注册至Eureka:
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/ spring.application.name=order-service # for order-service # spring.application.name=product-service # for product-service
OrderController代码:
@RestController @RequestMapping("/api/order") @RequiredArgsConstructor public class OrderController { private final OrderService orderService; @PostMapping @ResponseStatus(HttpStatus.CREATED) public String placeOrder(@RequestBody OrderRequest orderRequest) { orderService.placeOrder(orderRequest); return "Order placed successfully"; } // ... other methods ... }
ProductController代码:
@RestController @RequestMapping("/api/product") @RequiredArgsConstructor public class ProductController { private final ProductService productService; // ... methods ... }
问题现象
通过Postman向http://localhost:8080/api/order发送POST请求时,收到404错误:
{ "timestamp": "2024-03-08T20:08:59.340+00:00", "status": 404, "error": "Not Found", "path": "/api/order" }
直接调用order-service的动态分配端口(如http://localhost:54062/api/order)时,可正常响应并返回“Order placed successfully”。
排查思路与解决方案
1. 核心问题:依赖选型错误
你当前使用的是spring-cloud-starter-gateway-mvc(Spring MVC版本的网关),该版本对基于Eureka的lb://负载均衡路由支持有限,且配置逻辑与默认的WebFlux版本网关不同。替换为WebFlux版本的网关依赖是最直接的解决方式:
修改pom.xml中的网关依赖:
<!-- 移除原有MVC版本依赖 --> <!-- <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway-mvc</artifactId> </dependency> --> <!-- 添加WebFlux版本的网关依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>
该依赖包含了WebFlux框架和Spring Cloud LoadBalancer组件,能够原生支持lb://格式的负载均衡路由,无需额外配置。
2. 完善路由配置:路径匹配与转发
当前的路由Path predicate仅匹配精确路径/api/order,无法覆盖带参数或子路径的请求,且建议添加路径重写过滤器确保转发路径正确:
修改application.properties中的路由配置:
##Product Service Route spring.cloud.gateway.routes[0].id=product-service spring.cloud.gateway.routes[0].uri=lb://product-service spring.cloud.gateway.routes[0].predicates[0]=Path=/api/product/** spring.cloud.gateway.routes[0].filters[0]=RewritePath=/api/product/(?<segment>.*), /api/product/${segment} ##Order Service Route spring.cloud.gateway.routes[1].id=order-service spring.cloud.gateway.routes[1].uri=lb://order-service spring.cloud.gateway.routes[1].predicates[0]=Path=/api/order/** spring.cloud.gateway.routes[1].filters[0]=RewritePath=/api/order/(?<segment>.*), /api/order/${segment}
Path=/api/order/**:匹配所有以/api/order开头的请求(包括/api/order、/api/order/1等)RewritePath过滤器:确保请求路径完整转发到微服务(因为你的微服务Controller已经映射/api/order,所以重写后路径不变;如果微服务路径是/order,可改为/${segment}去掉前缀)
3. 启用Actuator端点排查路由状态
添加Actuator配置,方便查看路由是否正确加载、微服务实例是否可达:
management.endpoints.web.exposure.include=gateway,routes,health management.endpoint.gateway.enabled=true
启动网关后,访问http://localhost:8080/actuator/gateway/routes,可查看所有已配置的路由信息,以及对应的微服务实例状态。如果路由未出现在列表中,说明配置格式有误。
4. 额外排查点
- 检查Eureka控制台(
http://localhost:8761),确认order-service和product-service状态为UP - 移除
eureka.client.service-url.defaultZone中的多余空格(你的配置中http://localhost:8761/eureka/前有空格,可能导致注册异常) - 查看网关启动日志,确认是否有“RouteDefinition added”等路由加载成功的日志
内容的提问来源于stack exchange,提问作者Delano van der Waal

