使用Zuul网关访问SpringBoot接口时出现404错误求助
我使用SpringBoot、Zuul和Eureka构建微服务,所有服务通过Docker容器部署。当尝试通过Zuul网关访问ContentService的接口时,收到404 NOT FOUND错误。
接口信息
ContentService的接口代码:
@RestController @RequestMapping("/content") @RequiredArgsConstructor @EnableGlobalMethodSecurity(prePostEnabled = true) public class CommunityController { private CommuntiyService communtiyService; @Autowired private ACLverifier acLverifier; @Autowired private RabbitTemplate rabbitTemplate; @PostMapping("/send_message/{message}") public void sendMessage( @PathVariable("message") String message ) { System.out.println("sent message: " + message); rabbitTemplate.convertAndSend("commentExchange", "commentRoutingKey", message); } }
请求与响应
发送的Post请求:
http://localhost:8080/cont/content/send_message/hallo
返回的404响应:
{ "timestamp": "2024-06-26T08:20:29.052+00:00", "path": "/cont/content/send_message/hallo", "status": 404, "error": "Not Found", "requestId": "2355b902" }
各服务配置
ContentService
application.properties:
spring.application.name=ContentService server.port=8082 spring.data.mongodb.uri=mongodb://mongodb:27017/test # Use the database with: # docker exec -it mongodb bash # mongosh # show dbs # use <collection> # db.<entity>.find() # JWT security.jwt.secret-key=3cfa76ef14937c1c0ea519f8fc057a80fcd04a7420f8e8bcd0a7567c272e007b # 1h in millisecond security.jwt.expiration-time=3600000 # rabbitmq spring.rabbitmq.host=rabbitmq spring.rabbitmq.port=5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest # Eureka # eureka.instance.preferIpAddress=true eureka.client.registerWithEureka=true eureka.client.fetchRegistry=true eureka.client.serviceUrl.defaultZone=${EUREKA_URI:http://eureka:8761/eureka} # Actuator management.endpoints.web.exposure.include=*
启动类:
@EnableDiscoveryClient @EnableFeignClients @SpringBootApplication public class ContentServiceApplication { public static void main(String[] args) { SpringApplication.run(ContentServiceApplication.class, args); } }
Eureka
application.properties:
spring.application.name=Eruka server.port=8761 eureka.client.registerWithEureka=false eureka.client.fetchRegistry=false eureka.client.serviceUrl.defaultZone=http://eureka:8761/eureka eureka.renewalPercentThreshold=0.85
启动类:
@EnableEurekaServer @SpringBootApplication public class ErukaApplication { public static void main(String[] args) { SpringApplication.run(ErukaApplication.class, args); } }
Gateway/Zuul
application.properties:
spring.application.name=Gateway server.port=8080 spring.docker.compose.enabled=false spring.main.web-application-type=reactive spring.jpa.hibernate.ddl-auto=none # Eureka # eureka.instance.preferIpAddress=true eureka.client.registerWithEureka=true eureka.client.fetchRegistry=true eureka.client.serviceUrl.defaultZone=${EUREKA_URI:http://eureka:8761/eureka} # Actuator management.endpoints.web.exposure.include=* management.port=8080 # =================================== # Zuul # Content service zuul.routes.content-service.serviceId=content-service zuul.routes.content-service.path=/cont/** zuul.routes.content-service.stripPrefix=true
启动类:
@EnableDiscoveryClient @EnableZuulProxy @SpringBootApplication public class GatewayApplication { public static void main(String[] args) { SpringApplication.run(GatewayApplication.class, args); } }
Docker Compose配置
version: '3.8' services: # ============= GATEWAY =============== gateway: build: context: . dockerfile: API_GATEWAY/DockerfileGateway container_name: Gateway ports: - "8080:8080" networks: - ms_architecture # =================================== # ============= EUREKA =============== eureka: build: context: . dockerfile: API_GATEWAY/DockerfileEruka container_name: Eureka ports: - "8761:8761" networks: - ms_architecture # =================================== # ============= CONTENT SERVICE =============== mongodb: image: mongo:latest container_name: mongodb ports: - 27017:27017 networks: - ms_architecture content_service: build: context: . dockerfile: MicroServices/Content/ContentServiceDockerfile depends_on: - mongodb ports: - "8082:8082" environment: SPRING_DATA_MONGODB_URI: mongodb://mongodb:27017/test RABBITMQ_HOST: rabbitmq RABBITMQ_PORT: 5672 networks: - ms_architecture # =================================== # ============= RABBITMQ =============== rabbitmq: image: rabbitmq:management container_name: rabbitmq ports: - "5672:5672" - "15672:15672" networks: - ms_architecture healthcheck: test: ["CMD", "rabbitmqctl", "status"] interval: 30s timeout: 10s retries: 3 # =================================== networks: ms_architecture: driver: bridge
1. Zuul路由的serviceId与Eureka注册服务名不匹配
ContentService配置的spring.application.name=ContentService,但Zuul里配置的zuul.routes.content-service.serviceId=content-service(全小写)。Eureka默认对服务名大小写敏感,导致Zuul无法找到对应服务实例。
解决方法:
修改Zuul的application.properties,将serviceId改为与ContentService一致的名称:
zuul.routes.content-service.serviceId=ContentService
2. Zuul与Reactive Web类型冲突
Gateway配置中spring.main.web-application-type=reactive,但Zuul是基于Servlet的网关,使用Reactive类型会导致Zuul路由功能异常,无法正确处理请求转发。
解决方法:
删除Gateway的application.properties中该配置,或修改为Servlet类型:
spring.main.web-application-type=servlet
3. Eureka服务名拼写错误
Eureka的application.properties中spring.application.name=Eruka(正确应为Eureka),虽然不影响容器间DNS解析,但建议修正拼写以避免潜在问题。
4. 服务启动顺序导致注册失败
Docker Compose的depends_on仅保证容器启动顺序,不保证服务就绪。ContentService可能在Eureka未完全启动时尝试注册,导致注册失败,Zuul无法发现服务。
解决方法:
- 给ContentService添加启动等待逻辑,或在Docker Compose中配置健康检查依赖;
- 手动重启ContentService容器,确保其成功注册到Eureka。
5. 验证Eureka注册状态
访问Eureka控制台http://localhost:8761,检查ContentService和Gateway是否都出现在实例列表中。若ContentService未注册,需排查其Eureka配置和网络连接。
内容的提问来源于stack exchange,提问作者Veruca Stucker

