微服务启动故障排查

问题1:NoClassDefFoundError - MessageConverter

错误现象

java.lang.NoClassDefFoundError: org/springframework/amqp/support/converter/MessageConverter

根本原因

hm-common 模块中的 MqConfig 配置类使用了 Spring AMQP 的类,但 pom.xml 中 AMQP 依赖被标记为 <scope>provided</scope>,导致运行时找不到这些类。

解决方案

hm-common/pom.xml 中移除 AMQP 依赖的 provided 作用域:

<!-- 修改前 -->
<dependency>
    <groupId>org.springframework.amqp</groupId>
    <artifactId>spring-amqp</artifactId>
    <scope>provided</scope>  <!-- 删除这行 -->
</dependency>

<!-- 修改后 -->
<dependency>
    <groupId>org.springframework.amqp</groupId>
    <artifactId>spring-amqp</artifactId>
</dependency>

预防措施

  • 公共配置类如果引用了某个依赖的类,该依赖不能使用 provided 作用域
  • provided 仅适用于编译时需要但运行时有容器提供的场景(如 Servlet API)

问题2:端口冲突 - Port 8080 was already in use

错误现象

Web server failed to start. Port 8080 was already in use.

根本原因

多个微服务配置了相同的端口号(hm-service 和 hm-gateway 都使用了 8080)。

解决方案

修改其中一个服务的端口,确保每个微服务使用不同的端口:

# hm-service/src/main/resources/application.yaml
server:
  port: 8087  # 改为其他未被占用的端口

端口分配规范

  • hm-gateway: 8080(网关入口)
  • item-service: 8081
  • cart-service: 8082
  • user-service: 8084
  • trade-service: 8085
  • pay-service: 8086
  • hm-service: 8087(单体服务)

快速排查命令

# 查看占用端口的进程
netstat -ano | findstr :8080

# 强制关闭进程(替换 <PID> 为实际进程ID)
taskkill /F /PID <PID>

问题3:Nacos gRPC 连接失败

错误现象

Server check fail, please check server 127.0.0.1, port 9848 is available
Connection refused: no further information: /127.0.0.1:9848

根本原因

微服务缺少 bootstrap.yaml 配置文件,导致 Nacos 客户端使用默认配置连接到 localhost:8848,而 Nacos 2.x 的 gRPC 端口是 9848(8848 + 1000)。

解决方案

创建 bootstrap.yaml 文件,明确指定 Nacos 服务器地址:

# src/main/resources/bootstrap.yaml
spring:
  application:
    name: pay-service
  profiles:
    active: dev
  cloud:
    nacos:
      server-addr: 192.168.179.140:8848  # 必须显式配置
      config:
        file-extension: yaml
        shared-configs:
          - data-id: shared-jdbc.yaml
          - data-id: shared-log.yaml
          - data-id: shared-swagger.yaml
          - data-id: shared-seata.yaml

关键知识点

  • bootstrap.yaml 优先于 application.yaml 加载
  • Nacos 2.x 使用 gRPC 协议,端口规则:HTTP端口 + 1000
    • HTTP: 8848
    • gRPC: 9848
  • 所有微服务都必须配置 bootstrap.yaml 指向正确的 Nacos 地址

问题4:数据源初始化失败

错误现象

can not init DataSourceResource with HikariDataSource (null)

根本原因

pay-service 的 application.yaml 中硬编码了 datasource 配置并使用了占位符 ${hm.db.host}${hm.db.pw},但这些值没有正确从 Nacos 配置中心获取。

解决方案

移除 application.yaml 中的 datasource 配置,改用 Nacos 共享配置:

# 修改前 - 错误的配置
spring:
  datasource:
    url: jdbc:mysql://${hm.db.host}:3306/hm-pay?...
    username: root
    password: ${hm.db.pw}

# 修改后 - 正确的配置
hm:
  db:
    database: hm-pay  # 只指定数据库名称

配置加载流程

  1. bootstrap.yaml 先加载 → 连接 Nacos
  2. 从 Nacos 获取 shared-jdbc.yaml → 包含数据库主机、密码等敏感信息
  3. application.yaml 提供本地配置 → 只指定数据库名称
  4. 最终拼接jdbc:mysql://<host>:3306/hm-pay?...

最佳实践

  • 数据库连接信息(host、password)放在 Nacos 配置中心
  • 本地 application.yaml 只配置数据库名称(hm.db.database)
  • 所有微服务遵循统一的配置结构
  • 不要在 application.yaml 中硬编码完整的 datasource 配置

通用排查流程

1. 查看完整错误堆栈

  • 找到最底层的 Caused by 异常
  • 识别核心错误类型(ClassNotFoundException、ConnectionRefused 等)

2. 检查配置文件

  • 确认 bootstrap.yaml 是否存在且配置正确
  • 验证 application.yaml 中的占位符是否有对应值
  • 检查端口是否冲突

3. 验证外部依赖

  • Nacos 服务器是否正常运行
  • 数据库是否可访问
  • RabbitMQ 等服务是否正常

4. 对比正常服务

  • 参考其他能正常启动的微服务配置
  • 保持配置结构的一致性

常用诊断命令

# 查看端口占用
netstat -ano | findstr :<端口号>

# 关闭占用端口的进程
taskkill /F /PID <进程ID>

# 测试 Nacos 连通性
curl http://192.168.179.140:8848/nacos/

# 查看 Maven 依赖树
mvn dependency:tree

# 清理并重新编译
mvn clean compile

经验总结

  1. 依赖作用域要谨慎:公共模块的依赖不要随意使用 provided
  2. 端口规划要明确:提前规划好每个服务的端口,避免冲突
  3. 配置文件要完整:微服务必须有 bootstrap.yaml 指定注册中心地址
  4. 配置分离要做好:敏感信息放配置中心,本地只配差异化参数
  5. 保持一致性:所有微服务遵循相同的配置规范和结构
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐