SpringCloud 微服务架构核心组件
❓ 面试官:你们项目用的微服务架构是怎样的?包含哪些核心组件?
频率:🔥🔥🔥🔥🔥
💡 一句话总结(先抛结论): 我们项目采用的是 Spring Cloud Alibaba 体系(目前国内最主流)。核心组件包括:Nacos(注册中心与配置中心)、OpenFeign(服务间远程调用)、Sentinel(限流熔断降级)、Gateway(API 网关)、以及 Seata(分布式事务)。
📝 各大组件作用通俗解析:
- Nacos(通讯录/大管家):以前 A 服务调用 B 服务,A 需要把 B 的 IP 写死在代码里(极度耦合)。现在 B 启动时把自己的 IP 告诉 Nacos;A 想找 B,直接去 Nacos 这个“通讯录”里按名字(服务名)查,动态获取 IP。
- OpenFeign(假装在调本地方法):在 A 服务里写一个接口,打上
@FeignClient("service-B")。然后在代码里直接像调本地 Service 一样调这个接口,底层它会自动帮你把参数序列化成 HTTP 强求发给 B 服务,极大简化了远程调用代码。 - Gateway(小区保安大门):前端 App 不可能记住微服务内部几十个 IP 端口。所有外部请求统一先打到网关,由网关进行统一的 鉴权(Token 校验)、跨域处理、日志记录,然后再路由转发给后端的具体微服务。
- Sentinel(保险丝):如果 B 服务突然宕机或者巨慢无比,A 还在疯狂调用 B,会导致 A 的线程池也被拖死(服务雪崩)。Sentinel 可以配置:当 B 服务出错率超过 50% 时,直接熔断,A 不再去调 B,而是快速返回一个默认的降级数据(如“当前人多拥挤”),保全了 A 服务。
❓ 面试官:能详细说说 Nacos 作为注册中心,它的服务发现和心跳机制是怎么样的吗?【中高级】
频率:🔥🔥🔥🔥
💡 一句话总结(先抛结论): Nacos 的服务注册是服务提供者在启动时向 Nacos 发送 REST 请求注册自身信息。为了保证服务高可用,Nacos 引入了客户端定时发送心跳包以及服务端主动剔除不健康节点的机制,同时通过 UDP 推送 + 客户端轮询 双重保障机制,将节点变化快速通知给服务消费者。
📝 详细原理解析:
- 心跳机制(保活):
- 服务提供者(比如订单服务)启动后,会启动一个定时任务,每隔 5 秒 向 Nacos Server 发送一个心跳包("我还活着")。
- 如果 Nacos Server 超过 15 秒 没收到心跳,就会把该实例标记为“不健康”。
- 如果超过 30 秒 还没收到,就会彻底把它从注册表中“剔除”。
- 动态感知(消费者如何知道节点挂了?):
- 推(Push):一旦 Nacos 注册表发生变化(比如某个节点挂了被剔除),Nacos 会立刻通过 UDP 协议将最新的实例列表推送给消费者。
- 拉(Pull):为了防止 UDP 丢包,消费者自己也会每隔 10 秒 定时向 Nacos 拉取最新的注册表信息,缓存在自己本地的 JVM 内存中。
- 这也是为什么当某个服务刚宕机时,消费者有时还会调用失败(因为心跳超时检测需要时间,且本地缓存还没更新),这时候通常依赖 Feign 的重试机制或 Sentinel 降级来兜底。
❓ 面试官:Sentinel 和以前的 Hystrix 有什么区别?为什么要换 Sentinel?【中级】
频率:🔥🔥🔥
💡 一句话总结(先抛结论): Hystrix 是老一代组件,目前已停止维护。Sentinel 是阿里开源的新一代流量防卫兵。相比 Hystrix 采用线程池隔离(极耗资源),Sentinel 默认采用信号量隔离(极轻量),且提供了极其丰富的限流规则和友好的可视化控制台页面。
📝 详细对比核心点:
| 维度 | Hystrix | Sentinel |
|---|---|---|
| 隔离策略 | 线程池隔离(为每个依赖分配独立的线程池,优点是隔离彻底,缺点是线程上下文切换开销巨大,影响并发) | 信号量隔离(不创建新线程,只通过计数器限制并发数,轻量高效) |
| 流控粒度 | 只能基于服务接口 | 支持基于 QPS、并发线程数、甚至具体的方法参数、系统整体 Load 进行限流 |
| 熔断策略 | 仅支持异常比例 | 支持慢调用比例、异常比例、异常数 |
| 控制台控制 | 简陋的 DashBoard | 强大的控制台,支持实时监控、在线动态修改规则且立即生效 |
❓ 面试官:你们项目中是怎么使用 Seata 解决分布式事务的?【高级】
频率:🔥🔥🔥🔥
💡 一句话总结(先抛结论): 我们在一些跨服务的强一致性场景(如“下单扣库存扣余额”)中使用了 Seata。主要采用它最无侵入的 AT 模式(两阶段提交的变种)。它的核心原理是拦截业务 SQL,自动生成反向回滚的 Undo Log,一旦某个微服务报错,利用 Undo Log 自动回滚所有节点的数据。
📝 AT 模式底层流转(背诵模板): 涉及三个核心角色:TC(事务协调者,Seata Server)、TM(事务管理器,你的主业务代码)、RM(资源管理器,各个微服务的数据库)。
- 一阶段(执行并提交本地事务):
- 主业务(TM)向 TC 申请开启一个全局事务,拿到一个全局 XID。
- 微服务(RM)在执行业务 SQL(比如
update 库存 = 库存-1)之前,Seata 会拦截这句 SQL。 - Seata 去库里查出修改前的数据(Before Image),再查出修改后的数据(After Image),把它们拼装成一条 Undo Log,和业务数据在同一个本地数据库事务里提交。
- 此时,数据的锁已经被释放,极大提高了并发性能(这是它比传统 XA 事务快的原因)。
- 二阶段(决断:全局提交或回滚):
- 情况 A(全成功):TM 告诉 TC 大家都执行成功了。TC 通知所有 RM:可以收工了。RM 就会异步地去把刚才记录的 Undo Log 删掉。
- 情况 B(有人报错):比如积分服务报错了,抛出异常。TM 捕获到异常,向 TC 申请全局回滚。TC 通知所有参与过的 RM:开始回滚!RM 就会拿着一阶段记录的 Undo Log,生成一条反向补偿 SQL(比如把刚才扣的库存再加回去)并执行,从而实现数据最终一致性。