VortMall 微服务故障排查手册
VortMall 微服务故障排查手册
适用范围:VortMall-Api 全部 15 个业务微服务、网关、认证服务及公共组件。
技术栈:Java 21 / Spring Boot 4.0 / Spring Cloud 2025.1 / Spring Cloud Alibaba 2025.1 / MyBatis-Plus 3.5 / RocketMQ / Nacos / Seata / Redis / Elasticsearch / XXL-JOB
目录
- 一、服务启动失败
- 二、Nacos 注册与配置异常
- 三、数据库连接异常
- 四、Redis 缓存异常
- 五、消息队列(RocketMQ)异常
- 六、Outbox 可靠消息发送异常
- 七、网关路由异常
- 八、Feign 服务间调用异常
- 九、Seata 分布式事务异常
- 十、XXL-JOB 定时任务异常
- 十一、Elasticsearch 搜索异常
- 十二、Sa-Token 认证授权异常
一、服务启动失败
1.1 端口占用
现象:启动报 Address already in use: bind
排查:
# Windows
netstat -ano | findstr :<端口号>
taskkill /PID <进程ID> /F
# Linux
lsof -i :<端口号>
kill -9 <PID>
各服务默认端口对照:
| 服务 | 端口 |
|---|---|
| vortmall-gateway | 8000 |
| vortmall-auth | 8001 |
| vortmall-biz-product | 19901 |
| vortmall-biz-payment | 19902 |
| vortmall-biz-system | 19903 |
| vortmall-biz-marketing | 19904 |
| vortmall-biz-order | 19905 |
| vortmall-biz-content | 19906 |
| vortmall-biz-organize | 19907 |
| vortmall-biz-logistics | 19908 |
| vortmall-biz-aftersales | 19909 |
| vortmall-biz-distribution | 19910 |
| vortmall-biz-decoration | 19911 |
| vortmall-biz-message | 19912 |
| vortmall-biz-user | 19913 |
| vortmall-biz-file | 19914 |
| vortmall-biz-pos | 19915 |
1.2 Bean 创建失败
现象:BeanCreationException、UnsatisfiedDependencyException
常见原因与解决:
| 原因 | 解决方案 |
|---|---|
| 缺少依赖包 | 检查 pom.xml 是否引入对应 starter,执行 mvn dependency:tree 排查冲突 |
@Mapper 未扫描到 | 确认 Mapper 接口在 com.vortmall.*.infrastructure 包下,或检查 @MapperScan 配置 |
| 条件装配不满足 | 检查 @ConditionalOnProperty 对应的配置项(如 vortmall.outbox.enabled)是否设置 |
| 循环依赖 | Spring Boot 4.x 默认禁止循环依赖,使用 @Lazy 或重构解耦 |
1.3 配置文件加载失败
现象:ConfigDataLocationNotFoundException、Could not resolve placeholder
排查步骤:
- 确认
bootstrap.yml中spring.config.import路径正确:
spring:
config:
import:
- classpath:config.yml # Nacos 公共配置(必须)
- classpath:datasource.yml # 数据源
- classpath:cache.yml # Redis 缓存
- classpath:mq.yml # RocketMQ(按需)
- classpath:seata.yml # Seata(按需)
- classpath:job.yml # XXL-JOB(按需)
- 确认
env.yml中vortmall.host地址可达 - 检查 Nacos 配置中心中对应的
dataId是否存在,namespace 是否与部署环境一致
1.4 Java 版本不匹配
现象:UnsupportedClassVersionError、--enable-preview 相关报错
解决:项目要求 Java 21,确认 JAVA_HOME 指向 JDK 21,且 IDE 编译级别设置为 21。
二、Nacos 注册与配置异常
2.1 服务注册失败
现象:NacosException: failed to req API、服务列表中看不到实例
排查:
- 确认 Nacos Server 已启动:
curl http://<vortmall.host>:8848/nacos/ - 检查
config.yml中配置:server-addr地址与实际 Nacos 服务地址一致namespace与 Nacos 控制台中使用的命名空间一致
- 检查网络连通性(防火墙、VPN)
- 确认服务没有被
spring.cloud.nacos.discovery.enabled: false禁用
2.2 配置拉取失败
现象:启动时配置值为空或使用了默认值
排查:
- 登录 Nacos 控制台 → 配置管理 → 确认当前命名空间正确
- 检查
dataId和group是否匹配 - 共享配置(如
datasource-multiple.yml)是否已创建 - 检查 Nacos 客户端日志:
logs/nacos/config.log
2.3 配置热更新不生效
现象:修改了 Nacos 配置但服务未感知
排查:
- 确认使用了
@RefreshScope或@ConfigurationProperties - 检查是否是在
static或构造函数中读取的配置(不支持动态刷新) - 确认 Nacos 配置发布后 MD5 已变更
三、数据库连接异常
3.1 连接池初始化失败
现象:DruidDataSource init error、Communications link failure
排查:
- 确认 MySQL 服务已启动且端口可达(默认 3306)
- 检查数据源配置(
datasource.yml或 Nacos 中的配置):url格式:jdbc:mysql://<host>:3306/<db-name>?...- 用户名/密码正确
- 检查数据库是否存在(各服务对应的库名见下表)
各服务数据库名对照:
| 服务 | 数据库名 |
|---|---|
| vortmall-biz-product | vortmall-product |
| vortmall-biz-order | vortmall-order |
| vortmall-biz-user | vortmall-user |
| vortmall-biz-payment | vortmall-payment |
| vortmall-biz-system | vortmall-system |
| vortmall-biz-marketing | vortmall-marketing |
| vortmall-biz-content | vortmall-content |
| vortmall-biz-message | vortmall-message |
| vortmall-biz-aftersales | vortmall-aftersales |
| vortmall-biz-decoration | vortmall-decoration |
| vortmall-biz-distribution | vortmall-distribution |
| vortmall-biz-organize | vortmall-organize |
| vortmall-biz-logistics | vortmall-logistics |
| vortmall-biz-file | vortmall-file |
| vortmall-biz-pos | vortmall-pos |
3.2 连接池耗尽
现象:GetConnectionTimeoutException、Cannot get a connection, pool error Timeout waiting for idle object
排查:
- 检查 Druid 监控(如已开启):
/druid/datasource.html - 排查慢 SQL:开启 Druid 的
stat过滤器 - 排查连接泄漏:检查是否有未关闭的手动
Connection - 临时方案:增大
maxActive(默认 20),但需同步排查根因
spring:
datasource:
druid:
max-active: 50
max-wait: 60000
3.3 慢 SQL 导致超时
现象:接口响应慢、QueryTimeoutException
排查:
- 开启 MyBatis-Plus SQL 日志:
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
- 检查是否缺少索引:
EXPLAIN SELECT ... - 检查是否存在全表扫描、N+1 查询
- 使用 Druid 的
wall和stat过滤器监控
3.4 MyBatis-Plus 常见问题
| 问题 | 解决方案 |
|---|---|
Invalid bound statement | 检查 XML 文件路径与 Mapper 接口包路径一致,确认 mapper-locations 配置 |
Table 'xxx' doesn't exist | 检查实体类 @TableName 注解与实际表名是否一致 |
| 字段映射异常 | 检查 @TableField 注解、驼峰转换配置 map-underscore-to-camel-case |
四、Redis 缓存异常
4.1 连接失败
现象:RedisConnectionFailureException、Unable to connect to Redis
排查:
- 确认 Redis 已启动:
redis-cli -h <host> -p 6379 ping - 检查
cache.yml中的连接配置 - 检查密码是否正确
- 检查 Redis 最大连接数:
redis-cli info clients
4.2 缓存穿透 / 击穿 / 雪崩
| 问题 | 现象 | 解决 |
|---|---|---|
| 缓存穿透 | 大量查询不存在的数据,请求打到数据库 | 缓存空值、布隆过滤器 |
| 缓存击穿 | 热点 key 过期瞬间大量请求涌入 | 使用 vortmall-common-lock 分布式锁保护加载逻辑 |
| 缓存雪崩 | 大量 key 同时过期 | TTL 添加随机偏移量 |
4.3 Redisson 分布式锁问题
现象:vortmall-common-lock 获取锁超时或死锁
排查:
- 检查 Redis 连接是否正常
- 检查锁的
leaseTime是否过短(业务未执行完锁已释放) - 检查是否有异常导致锁未正确释放
- 通过
redis-cli查看锁 key 状态:GET <lock-key>
4.4 Sa-Token 会话 Redis 异常
现象:登录后立即失效、NotLoginException
排查:
- 确认网关和业务服务使用的 Redis 是同一实例
- 检查
sa-token.token-name配置一致性 - 检查 Redis key 前缀是否冲突
五、消息队列(RocketMQ)异常
5.1 Producer 发送失败
现象:RemotingTooMuchRequestException、MQBrokerException: No route info of this topic
排查:
- 确认 RocketMQ NameServer 已启动:
${vortmall.host}:9876 - 确认 Broker 已注册到 NameServer
- 检查 Topic 是否已创建(生产环境建议关闭自动创建):
# 查看 Topic 列表
mqadmin topicList -n <nameserver>:9876
# 创建 Topic
mqadmin updateTopic -n <nameserver>:9876 -b <broker>:10911 -t <TOPIC_NAME>
- 检查
mq.yml中name-server地址是否正确
5.2 Consumer 消费失败
现象:消息重复消费、消费延迟
排查:
- 检查消费者
Consumer<T>Function Bean 是否正确注册 - 检查
group配置(同一 group 下的实例会负载均衡) - 检查消费逻辑是否抛出异常导致重试:
- RocketMQ 默认重试 16 次
- 确保消费逻辑幂等(利用
MessageBody.identifier)
- 查看消费积压:
mqadmin consumerProgress -n <nameserver>:9876 -g <消费者组>
5.3 消息积压
现象:消费者消费速度跟不上生产者
排查与处理:
- 确认积压量:通过 RocketMQ Dashboard 或命令查看各 Queue 的消费偏移量
- 扩容消费者:增加消费者实例数(不能超过 Queue 数量)
- 排查消费瓶颈:
- 单条消息处理耗时过长 → 优化业务逻辑或异步化
- 数据库/外部 API 慢 → 排查下游瓶颈
- 消费异常重试 → 检查错误日志
- 临时方案:调整消费线程数
spring:
cloud:
stream:
rocketmq:
bindings:
<binding-name>:
consumer:
maxConcurrency: 20
六、Outbox 可靠消息发送异常
6.1 消息滞留在 Outbox 表中
现象:outbox_message 表中大量 PENDING 状态记录
排查:
- 检查 XXL-JOB 中对应的 Outbox 扫描任务是否在运行
- 检查
AbstractOutBoxJobHandler的日志输出 - 确认
StreamProducer(vortmall-common-mq)可用 - 检查
vortmall.outbox.enabled是否为true
6.2 Outbox 消息发送后状态异常
现象:消息已发到 MQ 但 Outbox 表状态仍为 PENDING
排查:
- 检查
OutBoxServiceImpl.processAndSend的事务提交是否正常 - 检查数据库连接是否在发送 MQ 后断开
- 查看
maxRetry配置(vortmall.outbox.defaultMaxRetry)
6.3 Outbox 表数据清理
正常情况下,成功发送的 Outbox 记录会被定时清理(retentionDays 控制保留天数)。如果表数据膨胀:
- 确认清理任务在 XXL-JOB 中已配置并正常运行
- 手动清理:
DELETE FROM outbox_message
WHERE status = 'SUCCESS'
AND update_time < DATE_SUB(NOW(), INTERVAL 7 DAY);
七、网关路由异常
7.1 503 Service Unavailable
现象:网关返回 503,LoadBalancerNotFoundException
排查:
- 确认目标服务已注册到 Nacos(Nacos 控制台 → 服务列表)
- 确认网关
application.yml中路由配置的uri与服务注册名一致:lb://vortmall-biz-product - 检查网关和业务服务是否注册在同一 Nacos 命名空间中
7.2 CORS 跨域问题
现象:前端报 Access-Control-Allow-Origin 错误
排查:
- 检查网关
CorsConfig配置 - 确认没有重复设置 CORS 头(网关已配
DedupeResponseHeader过滤器) - 如果业务服务也设置了 CORS,会导致响应头重复 → 业务服务不应单独配置 CORS
7.3 请求超时
现象:网关返回 504 Gateway Timeout
排查:
- 确认下游服务响应时间
- 调整网关超时配置:
spring:
cloud:
gateway:
httpclient:
connect-timeout: 10000
response-timeout: 30s
7.4 请求体过大
现象:上传文件时报 DataBufferLimitException: Exceeded limit on max bytes to buffer
解决:网关已配置 max-in-memory-size: 20MB,如需更大:
spring:
codec:
max-in-memory-size: 50MB
八、Feign 服务间调用异常
8.1 调用超时
现象:ReadTimeoutException、feign.RetryableException
排查:
- 确认被调用服务是否健康
- 调整 Feign 超时配置:
spring:
cloud:
openfeign:
client:
config:
default:
connectTimeout: 10000
readTimeout: 30000
8.2 Fallback 未触发
现象:Feign 调用失败直接抛异常,未执行 Fallback
排查:
- 确认
spring.cloud.openfeign.circuitbreaker.enabled: true - 确认 Resilience4j 相关依赖已引入(
spring-cloud-starter-circuitbreaker-resilience4j) - 确认 FeignClient 正确设置了
fallback或fallbackFactory
8.3 服务发现找不到实例
现象:Load balancer does not contain an instance for the service
排查:
- 确认被调用服务的
spring.application.name与 FeignClient 中name/value一致 - 确认调用方和被调用方注册在同一 Nacos 命名空间和 group 下
- 确认被调用服务实例健康(Nacos → 服务详情 → 查看实例状态)
8.4 序列化/反序列化异常
现象:HttpMessageConversionException、字段丢失
排查:
- 确认请求和响应 DTO 字段一致(注意 Feign 模块中定义的 DTO 与业务模块中可能不同步)
- 本项目使用 fastjson2,检查是否有 Jackson 注解混用导致的行为差异
- 日期格式、枚举序列化方式是否一致
九、Seata 分布式事务异常
9.1 Seata Server 连接失败
现象:RegistryException、can not connect to seata-server
排查:
- 确认 Seata Server 已启动
- 检查
seata.yml配置:registry.type: nacos- Nacos 地址:
${vortmall.host}:8848 - namespace:
seata_server
- 在 Nacos 控制台确认 Seata Server 已注册(切换到
seata_servernamespace)
9.2 全局事务回滚失败
现象:部分分支事务未回滚、数据不一致
排查:
- 检查 Seata Server 日志
- 确认
undo_log表存在于各业务数据库中 - 确认
enable-auto-data-source-proxy: true生效 - 排查分支事务是否有修改了全局锁范围外的数据
9.3 事务超时
现象:GlobalTransactionException: Could not found global transaction
排查:
- 排查事务执行时间是否过长
- 调整 Seata 超时配置
- 考虑将长耗时操作拆出事务(如发送 MQ、调用外部 API)
9.4 使用注意
@GlobalTransactional标注在 Application Service 层- 避免在事务中做耗时 I/O(HTTP 调用、文件上传)
tx-service-group必须各服务一致(当前统一为default_tx_group)
十、XXL-JOB 定时任务异常
10.1 执行器注册失败
现象:XXL-JOB Admin 中看不到执行器
排查:
- 确认 XXL-JOB Admin 已启动:
http://<vortmall.host>:8082/xxl-job-admin - 检查
job.yml配置:adminAddresses地址正确accessToken与 Admin 端一致appName格式:${spring.application.name}-executor
- 检查执行器端口(默认随机
9900-9999)是否被占用或被防火墙拦截
10.2 任务执行失败
现象:XXL-JOB Admin 中任务状态为失败
排查:
- 在 Admin 中查看任务执行日志(调度日志 → 执行日志)
- 检查服务端日志(
logs/xxl-job/jobhandler/目录) - 确认
@XxlJob("handlerName")中的名称与 Admin 端任务配置一致
十一、Elasticsearch 搜索异常
11.1 连接失败
现象:ElasticsearchException、Connection refused
排查:
- 确认 ES 集群已启动(默认端口 9200)
- 检查
es.yml中的连接配置 - 确认 ES 版本兼容性(项目使用 8.17.2 客户端)
11.2 索引不存在
现象:index_not_found_exception
排查:
- 确认索引是否已创建:
curl <es-host>:9200/_cat/indices?v - 检查索引名是否与业务代码中定义的一致
- 手动创建索引或等待数据同步任务创建
11.3 数据同步延迟
现象:数据库已更新但搜索结果未变
排查:
- 检查 Canal binlog 消费是否正常(
vortmall-biz-product使用 Stream 消费 Canal 事件) - ES 默认 refresh 间隔 1s,可手动刷新:
POST /<index>/_refresh - 排查同步消费者日志
11.4 通过 Elasticsearch 查看系统日志
系统运行日志通过 Logstash 采集后写入 Elasticsearch,可通过以下方式查看和检索。
查看集群健康状态:
curl <es-host>:9200/_cluster/health?pretty
查看所有日志索引:
curl <es-host>:9200/_cat/indices?v&s=index
日志索引通常按日期命名,格式如 vortmall-log-YYYY.MM.DD。
按关键字搜索日志:
# 搜索包含 "Exception" 的日志(最近 100 条)
curl -X GET "<es-host>:9200/vortmall-log-*/_search?pretty" \
-H "Content-Type: application/json" \
-d '{
"size": 100,
"sort": [{"@timestamp": "desc"}],
"query": {
"match": {
"message": "Exception"
}
}
}'
按服务名过滤日志:
# 查看指定服务的错误日志
curl -X GET "<es-host>:9200/vortmall-log-*/_search?pretty" \
-H "Content-Type: application/json" \
-d '{
"size": 50,
"sort": [{"@timestamp": "desc"}],
"query": {
"bool": {
"must": [
{"match": {"app_name": "vortmall-biz-order"}},
{"match": {"level": "ERROR"}}
]
}
}
}'
按时间范围查询日志:
# 查询最近 1 小时内的错误日志
curl -X GET "<es-host>:9200/vortmall-log-*/_search?pretty" \
-H "Content-Type: application/json" \
-d '{
"size": 50,
"sort": [{"@timestamp": "desc"}],
"query": {
"bool": {
"must": [
{"match": {"level": "ERROR"}}
],
"filter": [
{"range": {"@timestamp": {"gte": "now-1h", "lte": "now"}}}
]
}
}
}'
通过 Kibana 查看日志(如果已部署):
- 访问 Kibana:
http://<kibana-host>:5601 - 进入 Discover 页面
- 选择日志索引模式(如
vortmall-log-*) - 使用 KQL 语法搜索,示例:
- 搜索错误日志:
level: "ERROR" - 按服务过滤:
app_name: "vortmall-biz-order" AND level: "ERROR" - 搜索特定异常:
message: "NullPointerException" - 组合条件:
app_name: "vortmall-biz-payment" AND message: "timeout" AND @timestamp >= "2026-03-27"
- 搜索错误日志:
日志清理(磁盘空间不足时):
# 删除 30 天前的日志索引
curl -X DELETE "<es-host>:9200/vortmall-log-2026.02.*"
# 查看索引占用磁盘空间
curl "<es-host>:9200/_cat/indices/vortmall-log-*?v&s=store.size:desc&h=index,store.size"
十二、Sa-Token 认证授权异常
12.1 Token 无效或过期
现象:NotLoginException: Token无效
排查:
- 检查 Token 是否已过期(
sa-token.timeout配置) - 确认 Token 是否通过正确的 Header 传递(检查
sa-token.token-name) - 确认 Redis 中 Token 对应的会话数据存在
12.2 网关与服务 Token 不互通
现象:网关校验通过但服务端拿不到登录信息
排查:
- 确认网关使用
sa-token-reactor-spring-boot3-starter(响应式) - 确认业务服务使用
sa-token-spring-boot3-starter(Servlet) - 确认两端连接同一 Redis、使用相同 Token 配置
- 检查网关
AuthContextFilter是否正确传递了用户上下文
12.3 权限不足
现象:NotPermissionException、NotRoleException
排查:
- 检查用户角色权限数据是否正确
- 确认接口上的权限注解(
@SaCheckPermission)与权限数据匹配 - 检查权限缓存是否过期需要刷新
附录:故障处理流程
发现异常
│
├─ 服务不可用? ──→ 检查 Nacos 注册状态 → 检查服务进程 → 查看启动日志
│
├─ 接口报错? ──→ 查看网关日志 → 定位目标服务 → 查看服务错误日志
│
├─ 数据异常? ──→ 检查数据库直连 → 检查缓存一致性 → 检查 MQ 消费状态
│
├─ 性能问题? ──→ 慢 SQL 排查 → 连接池状态 → MQ 积压 → ES 日志检索
│
└─ 分布式事务? ──→ Seata Server 日志 → undo_log 表 → 各分支事务状态









