Spring Cloud Gateway集成Eureka服务发现出现404问题求助
问题
我正在搭建基于Spring Cloud Gateway与Eureka发现客户端的微服务应用,已完成Eureka服务端、Gateway网关以及event业务服务的配置。网关的application.yml中已开启spring.cloud.gateway.discovery.locator.enabled并设置spring.cloud.gateway.discovery.locator.lower-case-service-id为true。三个应用均可正常启动,但向localhost:8080/event发送GET请求通过网关访问微服务时,出现404错误。已配置Actuator查看网关暴露的端点,确认存在该服务的路由条目。请问我遗漏了什么配置?
相关配置
Eureka Server application.yml
spring: application: name: registry server: port: 8081 eureka: client: register-with-eureka: false fetch-registry: false service-url: defaultZone: http://localhost:${server.port}/eureka/ instance: hostname: localhost prefer-ip-address: true
Spring Cloud Gateway application.yml
spring: application: name: api-gateway cloud: gateway: discovery: locator: enabled: true lower-case-service-id: true main: web-application-type: reactive server: port: 8080 eureka: client: service-url: defaultZone: http://localhost:8081/eureka/ fetch-registry: true register-with-eureka: true instance: hostname: localhost prefer-ip-address: true management: endpoint: gateway: enabled: true endpoints: web: exposure: include: - "*"
Event Service application.yml
server: port: 8082 spring: application: name: event eureka: client: service-url: defaultZone: http://localhost:8081/eureka/ fetch-registry: true register-with-eureka: true instance: hostname: localhost prefer-ip-address: true
网关路由端点响应(Actuator)
[{"predicate":"Paths: [/api-gateway/**], match trailing slash: true","metadata":{"jmx.port":"55939","management.port":"8080"},"route_id":"ReactiveCompositeDiscoveryClient_API-GATEWAY","filters":["[[RewritePath /api-gateway/?(?<remaining>.*) = '/${remaining}'], order = 1]"],"uri":"lb://API-GATEWAY","order":0},{"predicate":"Paths: [/event/**], match trailing slash: true","metadata":{"jmx.port":"55880","management.port":"8082"},"route_id":"ReactiveCompositeDiscoveryClient_EVENT","filters":["[[RewritePath /event/?(?<remaining>.*) = '/${remaining}'], order = 1]"],"uri":"lb://EVENT","order":0}]
EventController代码
package example.event.endpoint.controller; import static org.springframework.http.HttpStatus.OK; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import example.event.endpoint.service.EventService; import example.core.model.Event; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @RestController @RequestMapping("/v1/event") @Slf4j @RequiredArgsConstructor(onConstructor = @__(@Autowired)) public class EventController { private final EventService eventService; @GetMapping public ResponseEntity<Iterable<Event>> listAll(Pageable pageable) { log.info("Retrieving all events"); return new ResponseEntity<>(eventService.list(pageable), OK); } }
问题分析与解决方案
核心原因
网关自动生成的路由规则和业务服务的接口路径不匹配:
- 网关通过服务发现生成的
event服务路由是/event/**,并附带默认路径重写规则:将/event/?(?<remaining>.*)重写为/${remaining}。当你请求localhost:8080/event时,网关会将路径转发为/到event服务。 - 但你的
EventController的请求映射是@RequestMapping("/v1/event"),@GetMapping对应的接口路径是/v1/event,服务端不存在/路径的接口,因此返回404。
解决方案(任选其一即可)
方案1:使用正确的请求路径
直接访问匹配接口的路径:localhost:8080/event/v1/event。此时网关会将路径重写为/v1/event,正好匹配Controller的接口。
方案2:修改业务服务的Controller路径
将EventController的@RequestMapping改为根路径,让网关转发的/路径能匹配到接口:
@RestController @RequestMapping("/") // 修改为根路径 @Slf4j @RequiredArgsConstructor(onConstructor = @__(@Autowired)) public class EventController { private final EventService eventService; @GetMapping public ResponseEntity<Iterable<Event>> listAll(Pageable pageable) { log.info("Retrieving all events"); return new ResponseEntity<>(eventService.list(pageable), OK); } }
方案3:自定义网关路由重写规则
如果希望保持Controller的/v1/event路径,同时用localhost:8080/event就能访问,可以在网关配置中添加自定义路由,覆盖自动生成的规则:
spring: cloud: gateway: discovery: locator: enabled: true lower-case-service-id: true routes: - id: event-service-route uri: lb://event predicates: - Path=/event/** filters: - RewritePath=/event/?(?<remaining>.*), /v1/event/${remaining}
配置后,请求localhost:8080/event会被网关重写为/v1/event,转发到event服务即可匹配接口。
内容的提问来源于stack exchange,提问作者rcirne
相关产品推荐
相关产品推荐

