乐途乐途
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
  • 学习路径
  • Spring Cloud Alibaba概述与技术选型
  • Nacos注册中心
  • Nacos配置中心
  • Sentinel流量控制
  • Sentinel降级与熔断
  • Seata分布式事务
  • RocketMQ消息驱动
  • Spring AI Alibaba与AI集成
  • Dubbo RPC服务调用
  • Gateway服务网关
  • GraalVM静态编译
  • 其他组件速览
  • Alibaba最佳实践与面试考点

Spring Cloud Alibaba 最佳实践与面试考点

本章是 Spring Cloud Alibaba 独立教程的收官之作,将前面各章的知识点整合为生产可用的最佳实践方案,并从面试视角体系化梳理核心考点。


生产部署架构

完整微服务生产部署拓扑

飞翔科技在经历数月的微服务化改造后,CTO 大翔要求架构师白歌输出一份生产部署拓扑图。白歌花了三天时间,将 Nacos、Sentinel、Seata、RocketMQ 以及可观测性组件全部整合进一套拓扑中。

白歌将这张拓扑图贴在团队 Wiki 首页,标注了一句话:"任何组件缺失,都可能导致某个维度失控——注册、配置、防护、事务、消息、可观测,六个维度缺一不可。"

Nacos 集群部署

在生产环境中,Nacos 必须高可用部署。白歌采用的方案是 3 节点 + MySQL 集群。

集群架构:

节点IP端口角色
Nacos-110.0.1.118848Leader / Follower
Nacos-210.0.1.128848Follower
Nacos-310.0.1.138848Follower
MySQL10.0.1.203306配置 + 服务数据持久化

cluster.conf 配置:

# Nacos 集群配置(每个节点上的 cluster.conf 内容一致)
10.0.1.11:8848
10.0.1.12:8848
10.0.1.13:8848

application.properties(生产关键配置):

# 数据源配置(生产必须外接 MySQL)
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://10.0.1.20:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000
db.user=nacos
db.password=${NACOS_DB_PASSWORD}

# Nacos 集群模式启动
nacos.core.auth.enabled=true
nacos.core.auth.system.type=nacos

启动命令:

# 生产模式启动(每个节点都执行)
cd nacos/bin
./startup.sh -m cluster

关键:Nacos 3 节点容忍 1 节点故障。2 节点容错为 0——任意 1 节点挂掉即丧失过半仲裁能力,因此生产环境必须至少 3 节点。

客户端连接配置:

spring:
  cloud:
    nacos:
      discovery:
        server-addr: 10.0.1.11:8848,10.0.1.12:8848,10.0.1.13:8848  # 集群地址
        namespace: prod

Seata Server 集群 + Nacos 高可用

Seata TC(Transaction Coordinator,事务协调器)同样是分布式事务的核心,必须高可用部署。

集群架构:

组件数量说明
Seata Server2+无状态,通过 Nacos 做服务发现
Nacos3 节点Seata Server 注册中心 + 配置中心
MySQL集群global_table / branch_table / lock_table 存储

registry.conf:

registry {
  type = "nacos"
  nacos {
    application = "seata-server"
    serverAddr = "10.0.1.11:8848,10.0.1.12:8848,10.0.1.13:8848"
    group = "SEATA_GROUP"
    namespace = "prod"
    cluster = "default"
  }
}
config {
  type = "nacos"
  nacos {
    serverAddr = "10.0.1.11:8848,10.0.1.12:8848,10.0.1.13:8848"
    group = "SEATA_GROUP"
    namespace = "prod"
  }
}

高可用保障机制:

机制说明
TC 无状态Seata Server 不存储事务状态(全部在 MySQL global_table 中),任意节点宕机后 Nacos 自动踢除
客户端重试RM(Resource Manager,资源管理器)/ TM(Transaction Manager,事务管理器)发现 TC 不可用时自动切换至 Nacos 返回的其他健康 TC 实例
全局锁一致性lock_table 存储在 MySQL 中,所有 TC 共享同一数据源,保证全局锁的分布式一致性
事务恢复TC 宕机后,同一集群中其他 TC 可接管未完成的全局事务(通过 global_table 查询)

RocketMQ Dledger 集群架构

Dledger 是 RocketMQ 4.5+ 引入的基于 Raft(Raft Consensus Algorithm)协议的自动主从切换方案,替代传统人工主从模式。

Dledger 关键配置(broker.conf):

enableDLegerCommitLog=true
dLegerGroup=broker-group-01
dLegerPeers=n0-10.0.1.31:40911;n1-10.0.1.32:40911;n2-10.0.1.33:40911
dLegerSelfId=n0

Dledger vs 传统主从:

维度传统主从(Master-Slave)Dledger(Raft-based)
故障切换人工切换,分钟级自动选举,~10s
数据一致性异步复制可能丢消息Raft 过半提交保证不丢
运维成本高(需人工介入)低(自动恢复)
部署复杂度低中(需至少 3 节点)

监控整合方案

SkyWalking 接入 Spring Cloud Alibaba

SkyWalking(Apache SkyWalking)是开源的应用性能管理(APM,Application Performance Monitoring)系统,通过 Java Agent 探针实现零侵入的链路追踪。

Agent 下载与配置:

# 下载 SkyWalking Agent
wget https://dlcdn.apache.org/skywalking/java-agent/9.3.0/apache-skywalking-java-agent-9.3.0.tgz
tar -xzf apache-skywalking-java-agent-9.3.0.tgz -C /opt/

agent.config 关键配置:

# SkyWalking OAP Server 地址
agent.service_name=${spring.application.name}
collector.backend_service=10.0.1.41:11800

# 采样率(生产环境建议 10%~30%)
agent.sample_n_per_3_secs=30

Java 启动参数:

java -javaagent:/opt/skywalking-agent/skywalking-agent.jar \
     -Dskywalking.agent.service_name=order-service \
     -Dskywalking.collector.backend_service=10.0.1.41:11800 \
     -jar order-service.jar

白歌的运维经验:SkyWalking Agent 对 Spring Cloud Alibaba 组件(Nacos、Sentinel、Feign、RocketMQ)的链路采集是自动的——Agent 内置了对 Nacos 客户端、Sentinel、Feign 客户端、RocketMQ 的拦截插件,开发者无需写任何埋点代码。

SkyWalking 拓扑图中可见的调用链:

Gateway → OrderService → UserService(Feign)
                       → StorageService(Feign)
                       → RocketMQ(发送消息)
UserService → RocketMQ(消费消息)

Sentinel Dashboard + Prometheus + Grafana

Sentinel Dashboard 内置了轻量级监控,但在生产环境中白歌推荐接入 Prometheus(指标采集)+ Grafana(可视化)体系。

Sentinel 暴露 Prometheus 指标:

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-prometheus-metric-exporter</artifactId>
    <version>1.8.6</version>
</dependency>

Prometheus 配置(prometheus.yml):

scrape_configs:
  - job_name: 'sentinel'
    metrics_path: '/actuator/prometheus'
    static_configs:
      - targets: ['10.0.1.11:8719', '10.0.1.12:8719', '10.0.1.13:8719']

PromQL 查询示例:

查询目标PromQL 语句
某资源 QPS(每秒查询数)rate(sentinel_qps_total{resource="getOrder"}[1m])
某资源平均响应时间rate(sentinel_rt_total{resource="getOrder"}[1m]) / rate(sentinel_success_total{resource="getOrder"}[1m])
某资源被限流次数rate(sentinel_blocked_total{resource="getOrder"}[1m])
某资源熔断状态sentinel_degrade_state{resource="getOrder"}(0=CLOSED, 1=OPEN, 2=HALF_OPEN)
服务实例 CPU 使用率system_cpu_usage{instance=~"10.0.1.*"}

Grafana 仪表盘布局建议:

┌───────────────────────────────────────────────────┐
│  第一行:整体概览 QPS / 平均 RT / 错误率 / 熔断状态   │
├───────────────────────┬───────────────────────────┤
│  第二行左:资源级 QPS    │  第二行右:资源级 RT 分布    │
├───────────────────────┼───────────────────────────┤
│  第三行左:限流/熔断趋势  │  第三行右:系统 Load / CPU   │
└───────────────────────┴───────────────────────────┘

关键监控指标速查表

Nacos 监控指标

指标含义告警阈值
nacos_server_connections当前长连接数> 10,000(单节点 2.x gRPC 连接)
nacos_cpu_usageNacos Server CPU 使用率> 80%
nacos_heap_usageJVM 堆内存使用率> 85%
nacos_service_count注册服务总数突变 > 50%(短时间大量服务下线)
nacos_instance_healthy_ratio实例健康率< 80%(大量实例不健康)
nacos_config_push_qps配置推送 QPS> 5000/s(异常配置推送风暴)

Sentinel 监控指标

指标含义告警阈值
sentinel_qps_total资源每秒请求数依据集群容量设定
sentinel_blocked_total被限流/熔断的请求数> 100/s(持续被限制)
sentinel_rt_avg资源平均响应时间> 基准 RT × 3
sentinel_degrade_state熔断器状态(0/1/2)= 1(处于 OPEN 状态)
sentinel_exception_ratio异常比例> 20%

Seata 监控指标

指标含义告警阈值
seata_global_transaction_active活跃全局事务数> 1000
seata_global_transaction_rollback_rate全局事务回滚率> 30%(高频回滚说明业务异常)
seata_lock_conflict_count全局锁冲突次数> 100/min
seata_branch_transaction_timeout_count分支事务超时数> 10/min
seata_global_transaction_avg_rt全局事务平均 RT> 5s(长事务阻塞其他事务)

RocketMQ 监控指标

指标含义告警阈值
rocketmq_broker_tpsBroker 消息 TPS突降 > 50%
rocketmq_producer_tpsProducer 发送 TPS突降 > 50%
rocketmq_consumer_tpsConsumer 消费 TPS连续低于 Producer TPS(消费堆积)
rocketmq_diff_total消息堆积量> 100,000
rocketmq_commitlog_disk_ratioCommitLog 磁盘使用率> 85%

告警规则参考

白歌根据生产经验建立了四级告警体系:

级别响应时间典型触发条件通知方式
P0 紧急5 分钟Nacos 全集群不可用、RocketMQ Broker 不可用、订单 QPS 暴跌 90%电话 + 短信 + 企业微信
P1 严重15 分钟Sentinel 熔断器连续 OPEN、消息堆积 > 10 万、数据库连接池耗尽短信 + 企业微信
P2 一般30 分钟单服务实例不健康、配置灰度推送延迟、少量消息重试企业微信
P3 提醒2 小时CPU / 内存 > 70%、磁盘使用率 > 70%、全局事务回滚率异常波动企业微信(静默模式)

性能调优速查

Nacos 客户端调优

参数默认值建议值说明
spring.cloud.nacos.discovery.heart-beat-interval5000ms3000ms缩短心跳间隔加快故障检测(牺牲少量网络开销)
spring.cloud.nacos.discovery.heart-beat-timeout15000ms10000ms缩短不健康判定时间
spring.cloud.nacos.discovery.ip-delete-timeout30000ms20000ms缩短已挂实例的自动剔除时间
spring.cloud.nacos.config.timeout3000ms5000ms首次拉取配置的超时时间,网络差时适当增大
spring.cloud.nacos.config.refresh-enabledtruetrue(保持)必须保持开启以支持配置自动刷新

本地缓存调优:

spring:
  cloud:
    nacos:
      discovery:
        naming-load-cache-at-start: true       # 启动时立即加载本地缓存,加速首次调用
      config:
        enable-remote-sync-config: true        # 远程配置同步到本地快照,Nacos 宕机时兜底

白歌的实战经验:飞翔科技在一次 Nacos 集群短暂不可用期间(数据库主从切换),依赖本地快照缓存保证所有服务依然能发现彼此——"本地快照就是你的保险绳。"

Sentinel 调优

参数默认值建议值说明
统计窗口 statIntervalMs1000ms1000ms(保持)保持 1s 精度,不建议调大
窗口槽位数 sampleCount22~5越大统计精度越高但内存开销越大
Warm Up 预热时长10s30s(冷启动场景)冷启动时给 JVM 和连接池预留充分预热时间
熔断最小请求数 minRequestAmount520(生产)避免少量异常触发误熔断
集群流控 Token Server 连接超时1000ms500msToken Server 请求应快速失败,避免拖垮业务线程

QPS 阈值参考(基于 4 核 8G 实例):

接口类型建议初始 QPS 阈值说明
简单查询(无 DB)500纯内存/缓存操作
数据库查询200考虑 DB 连接池和查询耗时
复杂计算50涉及文件/网络 IO 或 CPU 密集
第三方 API 调用20下游不可控,保守限流

重要:以上是初始建议值,生产环境必须通过压测确定真实阈值。小崔第一次直接把所有接口限流到 QPS=10,导致正常流量也被拒绝——孔蓝在运营群连发 5 条消息催修复。

Seata 调优

参数默认值建议值说明
client.rm.lock.retryInterval10ms20ms全局锁重试间隔
client.rm.lock.retryTimes3060全局锁重试最大次数(高并发场景适当增大)
client.rm.reportRetryCount55(保持)分支状态上报重试
server.maxCommitRetryTimeout-1(无限)600000ms(10min)TC 发起提交请求的最大等待时间
server.maxRollbackRetryTimeout-1(无限)600000ms(10min)TC 发起回滚请求的最大等待时间
client.tm.commitRetryCount55(保持)全局提交重试
client.tm.rollbackRetryCount55(保持)全局回滚重试

UNDO LOG 定期清理:

-- 清理 7 天前的已完成 UNDO LOG
DELETE FROM undo_log
WHERE log_status = 1  -- 1 = 已完成
  AND log_created < DATE_SUB(NOW(), INTERVAL 7 DAY)
LIMIT 1000;  -- 分批删除,避免锁表

警告:UNDO LOG 不会自动清理!飞翔科技曾经因为 undo_log 表膨胀到 50GB 导致数据库磁盘告警——孔蓝半夜被运维电话叫醒后,给白歌下了一个"每周清理"的死命令。

全局事务超时:

@GlobalTransactional(timeoutMills = 300000)  // 5 分钟超时(默认 60s 可能太短)
public void createOrder(Order order) { ... }

RocketMQ Producer / Consumer 调优

Producer 调优:

参数默认值建议值说明
sendMessageTimeout3000ms5000ms同步发送超时,跨机房场景适当增大
retryTimesWhenSendFailed23发送失败重试
compressMsgBodyOverHowmuch40962048消息体 > 2KB 自动压缩
maxMessageSize4194304(4MB)1048576(1MB)限制消息体大小,避免大消息阻塞

Consumer 调优:

参数默认值建议值说明
consumeThreadMin2010~20最小消费线程数
consumeThreadMax6432~64最大消费线程数
pullBatchSize3216~32每次拉取消息数
consumeMessageBatchMaxSize11~10批量消费上限
maxReconsumeTimes1616(保持)最大重试次数,最终进入死信队列

JVM 通用建议

白歌为各组件制定了 JVM 配置建议:

组件推荐堆内存推荐 GC 策略说明
Nacos Server2G~4GG1GCNacos 对象生灭快,G1GC 的 Region 化管理更合适
Sentinel Dashboard1G~2GG1GC内存中存储大量指标数据
Seata Server2G~4GG1GCTC 处理大量分支事务请求
RocketMQ Broker4G~8GG1GCCommitLog 大量使用堆外内存,堆内存不必过大
RocketMQ NameServer1G~2GG1GC轻量级,内存需求低
业务微服务2G~4GG1GC(JDK 17+ 默认)结合虚拟线程(Virtual Threads)释放传统线程池开销
# 典型 JVM 启动参数示例
java -Xms2g -Xmx4g -XX:+UseG1GC \
     -XX:MaxGCPauseMillis=200 \
     -XX:+HeapDumpOnOutOfMemoryError \
     -XX:HeapDumpPath=/opt/logs/heapdump.hprof \
     -jar order-service.jar

故障排查手册

Nacos 注册失败排查(6 个维度)

小崔某天部署新版本后,订单服务在 Nacos 控制台看不到。白歌带着他按以下维度逐一排查并最终定位。

维度检查项诊断命令/方法修复方案
1. 网络连通性Nacos Server 端口可达telnet 10.0.1.11 8848检查防火墙/安全组放行 8848 端口
2. gRPC 端口Nacos 2.x gRPC 端口telnet 10.0.1.11 9848Nacos 2.x 额外需要 9848(gRPC),这是最常见的遗漏
3. 配置一致性namespace / group 匹配对比 bootstrap.yml 和 Nacos 控制台namespace 必须用 UUID 而非名称;group 大小写敏感
4. 客户端日志Nacos 客户端启动日志grep "nacos" startup.log查找 failed to req API 或 ConnectException
5. 版本兼容性Nacos Client 版本 vs Server 版本cat pom.xml | grep nacosNacos 2.x Client 连 1.x Server 降级为 HTTP,部分功能不可用
6. 认证授权Nacos 账号密码Nacos 控制台检查2.x 默认开启认证,确保 username / password 配置正确

最常见问题 Top 3:① gRPC 9848 端口未放行(2.x 专属);② namespace 填名称而非 UUID;③ spring.application.name 未配置。

Sentinel 规则不生效排查(5 个维度)

维度检查项诊断命令/方法修复方案
1. Dashboard 连接客户端是否成功注册到 DashboardDashboard 机器列表查看检查 transport.dashboard 配置和 transport.port
2. 资源名匹配规则中的 resource 名和实际资源名是否一致查看 Dashboard 簇点链路核对 @SentinelResource("getOrder") 与 Dashboard 规则中资源名
3. 规则类型流控模式/效果是否匹配预期Dashboard 规则详情确认 grade(QPS/线程)、strategy(直接/关联/链路)、controlBehavior(快速/WarmUp/排队)
4. REST URLURL 资源是否默认被 Sentinel Web Filter 拦截curl http://localhost:8080/getOrder 看响应REST URL 无需 @SentinelResource 即自动作为资源;但需要 blockHandler 则必须注解
5. 规则持久化是否为拉取到了持久化规则查看应用日志中 DataSource 输出确认 Nacos DataSource 配置正确
6. Sentinel 日志本地日志中有无异常${user.home}/logs/csp/sentinel-record.loggrep "ERROR" sentinel-record.log

Sentinel 诊断命令(本地接口):

# 查看所有已加载的流控规则
curl http://localhost:8719/getRules?type=flow

# 查看某资源的实时 QPS
curl http://localhost:8719/cnode?id=getOrder

# 查看客户端与 Dashboard 的连接状态
curl http://localhost:8719/getDashboardServer

Seata 回滚失败排查(5 个维度)

维度检查项诊断方法修复方案
1. undo_log 表是否存在且结构完整SHOW TABLES LIKE 'undo_log'; DESCRIBE undo_log;每个业务库都要创建,对照 Seata 官方 DDL
2. 前镜像序列化前镜像是否成功保存SELECT * FROM undo_log WHERE xid='xxx'检查 rollback_info 字段是否非空
3. 全局锁冲突回滚时是否被其他事务持有锁SELECT * FROM lock_table WHERE row_key='xxx'超时后 TC 自动释放,或手动清理
4. 补偿 SQL 执行反向 SQL 是否生成并执行成功业务日志中查找 rollback undo log表结构变更后前镜像的反向 SQL 可能失败(字段类型不兼容)
5. TC 端驱动TC 是否成功发起了回滚指令TC 日志 grep "rollback" seata-server.logTC 与 RM 的 gRPC 连接是否中断

Seata 错误码对照:

错误码/异常含义处理方案
LockConflictException全局锁冲突增大 lock.retryTimes 或检查是否有死锁
BranchRollbackFailed_Retriable分支回滚失败可重试TC 会自动重试,检查 RM 日志
ShouldNeverHappenExceptionUNDO LOG 前镜像与当前数据不一致(脏写)严重:数据已被非 Seata 事务修改,需人工介入
GlobalTransactionNotFoundXID 对应的全局事务不存在TC 数据已被清理或 XID 传递丢失

RocketMQ 消息丢失排查(4 个丢失环节)

环节丢失原因修复方案
① 发送环节异步发送 + 网络抖动(sendStatus 非 SEND_OK)改用同步发送 sync: true;检查 sendResult.getSendStatus()
② 存储环节异步刷盘 + Broker 宕机改为同步刷盘 flushDiskType=SYNC_FLUSH(牺牲吞吐)
③ 投递环节主从异步复制 + Master 宕机后 Slave 没有全部数据使用 Dledger(Raft 过半提交)或同步复制 brokerRole=SYNC_MASTER
④ 消费环节Consumer 自动确认 + 业务异常未处理Consumer 改为手动确认模式;或集群消费重试 16 次后进入死信队列

发送端保障(同步发送 + 重试):

// Producer 同步发送 + 结果检查
SendResult result = rocketMQTemplate.syncSend("order-topic", message);
if (!result.getSendStatus().equals(SendStatus.SEND_OK)) {
    log.error("消息发送失败: {}", result);
    // 写入本地失败表,定时补偿
    failedMessageMapper.insert(order.getId(), message, result);
}

消息重复消费——幂等性设计方案

RocketMQ 的至少一次(At-Least-Once)语义意味着消息可能被重复消费。白歌为团队设计了三种幂等方案。

方案一:数据库唯一索引去重

-- 在业务表中使用消息 ID 做唯一约束
CREATE TABLE order_event (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    msg_id VARCHAR(128) NOT NULL,
    order_id BIGINT NOT NULL,
    status VARCHAR(32),
    UNIQUE KEY uk_msg_id (msg_id)     -- 消息 ID 唯一,重复抛异常
);
@Bean
Consumer<Message<Order>> input() {
    return message -> {
        String msgId = message.getHeaders().get("ROCKET_MQ_MESSAGE_ID");
        try {
            orderEventMapper.insert(msgId, message.getPayload());
        } catch (DuplicateKeyException e) {
            log.warn("消息重复消费,已跳过: {}", msgId);
        }
    };
}

方案二:Redis SETNX(原子性不存在则写入)

String msgKey = "msg:dedup:" + msgId;
Boolean success = redisTemplate.opsForValue()
    .setIfAbsent(msgKey, "1", Duration.ofHours(24));
if (Boolean.FALSE.equals(success)) {
    log.info("消息已处理,跳过");
    return;
}
// 执行业务逻辑...

方案三:消息 ID + 业务状态查重

// 先查业务状态,已处理则跳过
if (orderService.isAlreadyProcessed(orderId)) {
    log.info("订单已处理,跳过: {}", orderId);
    return;
}
orderService.process(order);

故障排查速查表

现象优先排查组件典型根因
所有服务调用失败NacosNacos 集群不可用或网络不通
部分服务调用失败Nacos服务实例不健康、Group 不匹配
请求被拒绝返回 429Sentinel流控/熔断规则触发
订单创建成功但库存没扣Seata 或 RocketMQ全局事务回滚失败 / 消息丢失
消息发了但消费者没收到RocketMQConsumer Group 不同、Tag 过滤不匹配、消费堆积
系统响应越来越慢Sentinel + JVM未配置限流导致线程池耗尽
配置改了没生效Nacos Config未加 @RefreshScope、Data ID 不匹配
服务重启后规则丢失Sentinel规则未持久化到 Nacos

面试体系化梳理

白歌在帮助团队几位同事准备面试时,系统整理了以下考点。这些内容既是对前面八章的复习提纲,也是面试的高频提问方向。

组件级面试

Nacos

Q1:Nacos 的 AP/CP 双模式是什么意思?各自适用什么场景?

  • AP 模式(Distro 协议,默认):优先保证可用性(Availability)和分区容错性(Partition Tolerance),牺牲强一致性。适用于服务注册与发现——宁可短暂不一致(查到已下线的实例),也不能完全不返回实例。
  • CP 模式(Raft 协议):优先保证一致性(Consistency)和分区容错性,牺牲可用性。适用于配置管理——配置数据的强一致性必须保障,Leader 选举期间短暂不可写。
  • 可以在同一个 Nacos 集群中共存:临时实例走 AP,持久化实例和配置走 CP。

Q2:Nacos 1.x 与 2.x 的通信协议有何变化?

维度1.x2.x
服务注册/心跳HTTP 短连接(5s 一次心跳请求)gRPC 长连接(双向流,单 TCP 连接复用)
配置推送HTTP 长轮询(Long Polling,30s 超时)gRPC 双向流(同一个长连接即推送)
连接数每个实例 1 个 HTTP 心跳连接 + 1 个长轮询连接每个实例 1 个 gRPC 连接(复用)
端口88488848(HTTP)+ 9848(gRPC)

Q3:Nacos 的保护阈值是什么?触发后会发生什么?

保护阈值(Protection Threshold)是一个 0-1 之间的浮点数。当健康实例占比低于保护阈值时,Nacos 触发保护模式:不再剔除任何实例(即使是不健康的),同时返回所有实例(健康 + 不健康)给消费者,由消费者自行判断。

为什么需要保护模式? 防止因网络波动导致大量实例被误剔——比如 10 个实例中 5 个因网络短暂不通被标记不健康,如果此时剔除这 5 个,剩余 5 个直接被流量冲垮,引发雪崩。

Sentinel

Q1:Sentinel 的 Slot Chain(插槽链)用了什么设计模式?核心 Slot 有哪些?

使用责任链模式(Chain of Responsibility Pattern)。每个 Slot 有明确的职责,按固定顺序执行,支持通过 SPI(Service Provider Interface)机制扩展。

核心 Slot 及其职责:

Slot职责
NodeSelectorSlot构建调用链路树,记录资源间调用关系
ClusterBuilderSlot构建 ClusterNode 聚合同一资源所有链路的指标
StatisticSlot核心统计插槽:记录 QPS / RT / 异常数
FlowSlot流量控制判定
DegradeSlot熔断降级判定
AuthoritySlot黑白名单授权
SystemSlot系统自适应保护

Q2:LeapArray 滑动窗口的底层原理是什么?

LeapArray 是基于环形数组 + 滑动窗口的统计算法。以默认配置(1s 周期 / 2 个窗口)为例:

  • 环形数组有 2 个槽位,每个槽位对应 500ms 的时间窗口
  • 当前时间通过 currentTimeMillis / 500 % 2 定位当前槽位
  • 每 500ms 窗口滑动一次,最旧槽位被重置复用
  • 统计时累加所有槽位数据,覆盖最近 1s 的精确窗口

为什么不用简单计数器? 简单计数器在跨秒边界精度崩溃——前一秒最后 100ms + 后一秒前 100ms 如果都计数,合并计算会翻倍。滑动窗口不存在此问题。

Q3:四种流控效果的区别?

效果行为适用场景
快速失败(Fast Fail)直接抛出 FlowException秒杀、对超出流量直接拒绝
Warm Up(预热)阈值从 阈值/coldFactor 逐步升至设定值服务刚启动时逐步放开流量
排队等待(Rate Limiter)请求以恒定速率通过,多余的排队等待需要流量整形的场景(如外部 API 调用)
Warm Up + 排队等待预热 + 恒定速率冷启动 + 流量整形的综合场景

Seata

Q1:AT 模式二阶段的"二阶段"与 XA 的"二阶段"有何本质区别?

维度AT 模式XA
一阶段直接提交了本地事务(释放数据库行锁),同步保存 UNDO LOG仅 Prepare 本地事务,数据库行锁一直持有
二阶段全局提交:异步删除 UNDO LOG;全局回滚:根据前镜像反向补偿全局提交:正式提交本地事务(释放行锁);全局回滚:回滚本地事务
锁持有时间短(一阶段提交后释放)长(直到二阶段完成后才释放)
性能高低(长事务锁持有影响并发)

关键差异:AT 模式在一阶段就已提交本地事务,锁持有时间远短于 XA。代价是如果二阶段回滚前发生了脏写(其他事务修改了同一行数据),回滚会失败。

Q2:TCC 模式的三大核心问题是什么?如何解决?

问题场景解决方案
空回滚Try 未执行(网络超时),但 Cancel 却到达在 Cancel 中查询 Try 是否执行,未执行则插入空回滚记录直接返回
悬挂Cancel 先于 Try 到达(Cancel 被重发绕过 Try)Try 执行前检查是否有空回滚记录,有则阻止 Try 执行
幂等同一个 Try/Confirm/Cancel 被重复执行用事务控制表的状态字段做幂等判断(如 TRY→CONFIRM→CANCEL 状态流转)

Q3:Seata 的全局锁机制如何工作?

全局锁存储在 lock_table 中,键为 row_key(resourceId + tableName + pk)。一阶段提交前 RM 向 TC 申请全局锁:

  • 无冲突 → 插入 lock_table 记录,申请成功
  • 有冲突 → 等待重试(默认 30 次,间隔 10ms)→ 超时抛 LockConflictException

全局锁的作用是防止多个全局事务并发修改同一行数据导致的脏写问题。事务完成后 RM 通知 TC 释放锁。

RocketMQ

Q1:RocketMQ 事务消息的"半消息"机制是如何工作的?

事务消息分为三个阶段:

1. Producer 发送半消息(Half Message)→ Broker
   半消息对 Consumer 不可见(不会投递)
2. Producer 执行本地事务
   - 成功 → 向 Broker 发送 COMMIT → 半消息变为可见,投递给 Consumer
   - 失败 → 向 Broker 发送 ROLLBACK → 半消息被删除
3. 如果 Broker 未收到二次确认(网络问题/Producer 宕机)→ Broker 发起回查
   → Producer 的 checkLocalTransaction() 返回最终状态

Q2:RocketMQ 如何保证分区顺序消息?

  • 生产者端:发送时指定 hashKey(如订单 ID),RocketMQ 按 hashKey 取模将消息路由到固定的 MessageQueue
  • Broker 端:同一 MessageQueue 内消息按写入顺序存储(FIFO)
  • 消费者端:Consumer 使用有序消费模式(ORDERLY),同一 MessageQueue 同一时刻只被一个线程消费

Q3:RocketMQ 如何保证消息可靠性?

逐层保障:

层级保障机制
Producer同步发送 + 失败重试(默认 2 次)
Broker 写入同步刷盘(SYNC_FLUSH):写入 Page Cache 后还强制 fsync 落盘
Broker 复制同步复制(SYNC_MASTER)或 Dledger(Raft 过半提交)
Consumer手动确认 + 消费重试(默认 16 次)→ 死信队列兜底

架构级面试

Q1:Spring Cloud 原生方案 vs Spring Cloud Alibaba 全家桶如何选型?

从四个维度展开分析:

1. 组件功能维度

需求原生方案Alibaba 方案建议
注册 + 配置Eureka + Config + Bus(三个组件拼接)Nacos(一个组件搞定)Alibaba
流控/熔断Hystrix(停更)Sentinel(规则更丰富、Dashboard 可视化)Alibaba
分布式事务无原生方案Seata(AT/TCC/Saga/XA 全覆盖)Alibaba
消息驱动Spring Cloud Stream + RabbitMQ / KafkaSpring Cloud Stream + RocketMQ(事务消息、延迟消息原生支持)按需,阿里系选 RocketMQ

2. 项目活跃度维度

  • Netflix OSS 系列(Eureka、Hystrix、Ribbon)已相继停更或进入维护模式
  • Alibaba 系列由阿里巴巴持续维护,双十一核心链路验证,迭代活跃
  • Sentinel GitHub Star 数远超 Hystrix

3. 国产化与合规维度

  • 全部为中国主导的开源项目(归属 Apache 或阿里巴巴),中文文档完善
  • 符合信创(信息技术应用创新)政策导向
  • 阿里云 MSE 企业版提供商业兜底支持

4. 生态整合维度

  • Alibaba 全家桶内部深度整合:Nacos 同时作为 Sentinel 规则持久化数据源、Seata TC 注册中心、RocketMQ 可选服务发现
  • 四个中间件(Nacos + Sentinel + Seata + RocketMQ)覆盖全部 MSA 需求,减少运维组件数量

面试加分回答:如果面试官追问"有没有场景适合继续用 Spring Cloud 原生方案",可以说:"存量系统中,如果已深度定制了 Eureka 的客户端行为、或者团队对 Hystrix 的参数调优非常有经验,迁移成本可能高于收益。但对于新项目或即将重构的系统,Alibaba 方案更全面、更活跃。"

Q2:如何设计一个高可用的微服务治理体系?

从五个维度构建完整方案:

1. 注册中心高可用

Nacos 3 节点集群 + MySQL 集群
  ├── 服务发现:AP 模式(Distro),保证可用性
  ├── 配置管理:CP 模式(Raft),保证一致性
  └── 本地快照:Nacos 宕机时各客户端本地缓存兜底

2. 配置动态刷新

Nacos Config + @RefreshScope
  ├── 配置集中管理 + 版本回滚
  ├── 敏感信息加密(Jasypt / Vault)
  └── 灰度配置:按标签向指定实例推送

3. 熔断降级

Sentinel + Dashboard
  ├── 流控规则:QPS 限流 + 排队等待 + Warm Up 预热
  ├── 熔断降级:慢调用比例 / 异常比例 / 异常数
  ├── 系统保护:Load / CPU / RT 维度自适应保护
  ├── 集群流控:Token Server 统一计数
  └── Feign 整合:降级方法 FallbackFactory

4. 分布式事务

Seata AT 模式(默认)或 TCC(高性能场景)
  ├── undo_log 表 + 全局锁 table
  ├── TC 高可用(Seata Server 集群注册到 Nacos)
  └── 事务日志定期清理(global_table / branch_table / lock_table)

5. 监控告警

SkyWalking(链路追踪)+ Prometheus(指标采集)+ Grafana(可视化)
  ├── 自动采集 Nacos/Sentinel/Feign/RocketMQ 调用链
  ├── Sentinel 指标 PromQL 查询 + Grafana 仪表盘
  └── P0~P3 四级告警:电话 → 短信 → 企业微信 → 静默

Q3:单体迁移微服务的演进路线图

各阶段关键决策:

阶段典型动作核心技术适用范围
单体—Spring Boot 单应用 + 单数据库创业初期、团队 < 5 人
垂直拆分前后端分离 + 抽取公共模块Spring Cloud Gateway + 共享 JAR团队 10 人左右
服务化核心业务拆分为独立微服务SCA 全家桶(Nacos + Sentinel + Seata + RocketMQ)团队 20+ 人,多业务线
网格化治理能力下沉 SidecarIstio / MSE 服务网格 + Kubernetes团队 50+ 人,多语言/跨国部署

白歌的忠告:不要一上来就上网格化——大多数公司永远停在服务化阶段就够了。单体→服务化是质的飞跃,服务化→网格化只是运维模式的微调。

场景题

场景1:双十一大促——如何用 Sentinel + RocketMQ 扛住瞬时流量峰值?

问题:双十一零点的流量是平时的 50 倍,如何保证核心下单链路不雪崩?

设计方案:

用户请求
  │
  ▼
Gateway(Sentinel 网关流控)
  │  QPS = 10,000(集群 Token Server 统一计数)
  │  超出 → HTTP 429 "活动太火爆,请稍后再试"
  ▼
下单服务(Sentinel 流控)
  │  QPS = 5,000
  │  排队等待模式(Rate Limiter)
  │  超出 → 返回降级提示
  ▼
下单业务逻辑
  │  ① 校验库存(Redis 缓存预扣)
  │  ② 发送 RocketMQ 事务消息(半消息)
  │  ③ 写订单 DB
  │  ④ 提交事务消息
  ▼
RocketMQ(削峰填谷)
  │  Broker 暂存消息
  │  Consumer 匀速消费(库存真实扣减、积分发放)
  ▼
异步消费者
      ├── 库存服务:真实扣减 DB 库存
      ├── 积分服务:发放积分
      └── 通知服务:发送短信/推送

关键设计点:

设计点方案
前端分流商品详情页静态化 + CDN;下单按钮点击后显示"排队中"
网关限流Sentinel Gateway 流控,集群 QPS = 10,000,超出直接 429
业务限流下单接口排队等待(Rate Limiter),平滑流量而非拒绝
削峰不直接调库存/积分服务,而是发 RocketMQ 消息异步处理
库存预热Redis 缓存库存计数,减少 DB 压力;下单时 Redis 先扣,异步更新 DB
熔断兜底库存服务慢调用比例 > 30% → Sentinel 熔断 → 走排队重试
降级方案积分服务不可用 → 降级为"积分稍后到账"通知

场景2:跨机房部署——Nacos 多数据中心 + 就近路由

问题:飞翔科技业务扩展到全国,需要在北京、上海、广州三个数据中心部署微服务。用户如何就近路由?

方案:Nacos 多数据中心就近路由

北京数据中心                 上海数据中心                广州数据中心
┌──────────────┐          ┌──────────────┐          ┌──────────────┐
│ Nacos-1      │◄────────►│ Nacos-2      │◄────────►│ Nacos-3      │
│ (Raft CP)    │  跨机房    │ (Raft CP)    │  跨机房    │ (Raft CP)    │
└──────────────┘  复制     └──────────────┘  复制     └──────────────┘
      │                         │                         │
  服务实例                     服务实例                   服务实例
  cluster: BJ                 cluster: SH               cluster: GZ

配置路由规则(Spring Cloud LoadBalancer):
  - 北京用户 → 优先路由到 cluster=BJ 的实例
  - 北京实例全挂 → 降级路由到 cluster=SH
  - 心跳就近上报(实例只向本地 Nacos 节点发心跳)

关键配置:

spring:
  cloud:
    nacos:
      discovery:
        server-addr: local-nacos.bj.datacenter:8848  # 就近连接本地 Nacos
        metadata:
          cluster: BJ                                 # 集群标记
        cluster-name: BJ

场景3:分布式事务选型——什么场景用 AT、什么场景用 TCC、什么场景用可靠消息?

白歌画了下面这张决策图:

              ┌── 需要强一致实时回滚?
              │
         ┌────┴────┐
         │  是      │  否(可接受最终一致)
         └────┬────┘          │
              │               ▼
         ┌────┴────┐    使用可靠消息最终一致性
         │ 业务代码  │    (RocketMQ 事务消息)
         │ 能改造?  │    示例:积分发放、通知推送、日志
         └────┬────┘
              │
     ┌────能───┴───不能(或数据库交互复杂)───┐
     │                                      │
     ▼                                      ▼
  TCC 模式                              AT 模式
  示例:金融转账                         示例:电商下单扣库存
  (需要显式冻结/解冻资源)                (基于关系型数据库的微服务)
场景推荐模式原因
电商下单(订单+库存+账户)AT 模式基于关系型数据库,SQL 单一,代码零侵入
金融转账(冻结→扣款→解冻)TCC 模式需要显式资源冻结和确认,性能要求高
积分发放、通知推送可靠消息最终一致性非关键链路,允许短暂不一致
长流程订单(创建→支付→发货→完成)Saga 模式每个步骤独立提交,失败后正向补偿

学习路径与后续进阶

推荐学习顺序

白歌为团队制定的学习路径(同时也是本教程的章节阅读顺序):

阶段一:概述
  └── 第 1 章:Spring Cloud Alibaba 概述与技术选型
        ├── 理解全家桶定位
        └── 掌握版本体系

阶段二:基础设施
  ├── 第 2 章:Nacos 注册中心(服务发现基础)
  └── 第 3 章:Nacos 配置中心(配置管理基础)

阶段三:稳定性
  ├── 第 4 章:Sentinel 流量控制(流量防护第一道防线)
  └── 第 5 章:Sentinel 降级与熔断(防止级联雪崩)

阶段四:关键能力
  ├── 第 6 章:Seata 分布式事务(数据一致性保障)
  └── 第 7 章:RocketMQ 消息驱动(异步解耦 + 削峰)

阶段五:综合实战
  └── 第 8 章:综合案例:电商微服务全栈实战
        └── 所有组件的整合验证

收尾:最佳实践
  └── 第 14 章:最佳实践与面试考点(本章)
        ├── 生产部署架构
        ├── 监控整合 + 性能调优 + 故障排查
        └── 面试体系化梳理

进阶方向

方向核心技术说明
云原生网关Higress阿里巴巴开源的云原生网关,基于 Istio + Envoy,支持 Wasm 插件扩展
AI 微服务Spring AI Alibaba基于 Spring AI 框架,将通义千问等大模型作为微服务体系的一等公民
企业级微服务引擎阿里云 MSE(Microservice Engine)Nacos 企业版、全链路灰度、无损上下线、服务鉴权、云原生网关
可观测性SkyWalking + Prometheus + Grafana + ELK链路追踪 + 指标监控 + 日志聚合,三支柱全覆盖
容器化编排Kubernetes + KubeVela将所有 SCA 微服务容器化并编排部署

配套实践项目建议

白歌建议每位读者完成以下三个层次的实践:

Level 1:基础实践(必做)

  • [ ] 搭建 Nacos 单机 Server + Spring Boot 服务注册/发现
  • [ ] 使用 Nacos Config 实现配置动态刷新
  • [ ] 搭建 Sentinel Dashboard + 配置 QPS 流控规则
  • [ ] 编写 Seata AT 模式电商下单示例(含 undo_log)

Level 2:进阶实践(推荐)

  • [ ] Nacos 3 节点集群 + MySQL 持久化部署
  • [ ] Sentinel 集群流控(Token Server 模式)
  • [ ] RocketMQ 事务消息 + 订单状态机
  • [ ] TCC 模式金融转账示例(冻结→确认→解冻)
  • [ ] 全链路压测(JMeter 模拟大促流量 + Sentinel Dashboard 观测)

Level 3:生产级实践(选做)

  • [ ] SkyWalking + Prometheus + Grafana 全栈可观测性
  • [ ] Nacos + Sentinel + Seata 规则全量持久化到 Nacos
  • [ ] 多机房就近路由 + 全链路灰度发布
  • [ ] Spring AI Alibaba 大模型接入 + Sentinel 保护
  • [ ] Kubernetes 集群部署 + MSE 微服务引擎

本章小结:从生产部署架构到故障排查手册,从性能调优速查到面试体系化梳理,本章将前面八章的知识点整合为可落地的生产实践和面试指南。CTO 大翔看完后对白歌说了一句话:"这份文档,值三个架构师的年薪。"

教程完:感谢你学完 Spring Cloud Alibaba 独立教程。这是一个以飞翔科技团队故事串联的微服务全家桶教程,从概述到最佳实践,覆盖了 Nacos、Sentinel、Seata、RocketMQ 四大核心组件的完整学习路径。预祝你在微服务架构的道路上越走越远。

[memory_id: memory_00_8u9RKB0pxBPUy0Bm0zxz0289]

上一页
其他组件速览