Skip to content

【面试题】1. 微服务拆分时,DDD 的限界上下文到底怎么落地?能不能举个例子? ​

【标准答案】限界上下文的核心就一句话:同一个业务概念在不同上下文里含义可以不同。比如"订单"在交易上下文里关注金额、状态;在履约上下文里关注收货地址、物流;在结算上下文里关注佣金、分成。它们都是"订单",但属性、行为完全不同。落地步骤:先事件风暴画领域事件→识别出哪些概念是一伙的→以数据强一致边界为底线切服务。实操技巧:看数据库表的外键——被外键关联的几张表大概率在同一个上下文里。千万别看类图切服务,那是陷阱。拆分原则:强一致在服务内,最终一致在服务间。宁可微服务稍大一点后期再拆,也别一上来切太细搞成分布式单体,100 个微服务的团队大多数最后都在还债。

【面试题】2. 服务注册发现的健康检查,Nacos 的临时实例和持久化实例有什么区别? ​

【标准答案】Nacos 的实例分两种,对应两种健康检查模式。临时实例(ephemeral=true,默认):客户端主动心跳上报,Nacos 超过 15 秒没收到心跳就踢掉,踢掉后客户端下线,自动摘除流量——这叫"客户端上报模式",是 AP 模型,适合弹性扩缩的微服务。持久化实例(ephemeral=false):Nacos 主动探测实例健康状态,探测失败只标记不健康但不下线——这叫"服务端探测模式",是 CP 模型,适合基础设施(数据库、缓存、MQ)这些 IP 不变但偶尔假死的场景。记忆诀窍:服务愿意自己报心跳用临时,服务可能假死但不该被踢用持久化。生产踩坑:临时实例心跳间隔默认 5 秒,别调太小,Nacos 服务端扛不住大量心跳风暴。

【面试题】3. CAP 理论说分布式系统只能三选二,但实际中 P 往往是必须的,那 C 和 A 的取舍怎么落地? ​

【标准答案】P(分区容错)在分布式系统里你躲不掉——网络可能丢包、交换机可能故障、跨机房链路可能中断。所以现实中的选择题是 CP 还是 AP。CP 选一致性:发生网络分区时宁可不可用也要数据不错,典型场景是银行转账、库存扣减,数据错了比不可用更严重。AP 选可用性:分区时宁可短暂数据不一致也要接口正常返回,典型场景是社交动态、商品浏览,用户刷不出来比数据不同步更让人暴躁。BASE 理论就是 AP 的实践版——Basically Available(基本可用)、Soft state(柔性状态)、Eventually consistent(最终一致)。面试加分项:不是二选一,而是按业务场景差异化——下单扣库存走 CP,订单列表查详情的缓存走 AP,同一系统不同接口做不同取舍,这才是架构师的判断力。

【面试题】4. 服务网关 Spring Cloud Gateway 对比 Zuul 1.x,为什么 Gateway 性能更好? ​

【标准答案】根因两个字:阻塞。Zuul 1.x 基于 Servlet,每个请求绑定一个线程,线程数受限于 Tomcat 线程池(默认 200),高并发下线程上下文切换 CPU 飙升,线程耗尽整个网关就堵死了。Gateway 基于 Spring 5 的 WebFlux + Reactor Netty,异步非阻塞 I/O——请求来了不需要独占线程等待后端返回,少量事件循环线程就能处理成千上万个连接。举个例子:1000 并发、后端延迟 100ms,Zuul 1.x 需要 1000 个线程;Gateway 可能 10 个线程就够了,CPU 和内存开销不在一个量级。Gateway 的另一个优势是函数式路由定义,可以动态刷新路由规则不重启。Zuul 2.x 也改成了 Netty 异步但有兼容包袱,社区重心已移到 Gateway。选型:新项目无脑 Gateway。

【面试题】5. 一致性哈希负载均衡和普通哈希有什么区别?解决了什么实际问题? ​

【标准答案】普通哈希(hash(key) % N)在节点数量 N 变化时,几乎所有 key 的映射都会变——加一台缓存节点,缓存全量失效,数据库瞬间被打爆,这就是缓存雪崩的经典触发器。一致性哈希把节点也哈希到一个 0~2^32 的环上,key 落到环上后顺时针找最近的节点。这样加减节点时,只影响相邻一小段环上的 key,大部分缓存不失效。用虚拟节点优化:物理节点映射为环上多个虚拟位置(例如 150 个),让数据分布更均匀,避免了"哈希倾斜"——少数节点扛大部分流量。常见场景:Redis Cluster 的 slot 分配、Dubbo 的一致性哈希负载、CDN 节点路由。一句话总结:一致性哈希不是不让缓存失效,是把失效范围控制在最小。

【面试题】6. Nacos 和 Apollo 做配置中心,业务上怎么选?各有啥优缺点? ​

【标准答案】Apollo 是携程开源,最成熟老牌的配置中心,亮点是 Portal 管理界面好用——支持配置灰度发布(按 IP、按百分比)、配置审批流、版本回滚和一键对比,对运维和产品经理极度友好。但只有 HTTP 拉取,没有原生长轮询,客户端依赖定时轮询或自己搭长连接。Nacos 是阿里开源,一个服务做注册+配置两件事,深度集成 Spring Cloud Alibaba 生态,部署轻量,原生支持长轮询实时推送配置变更。缺点也很明显:配置管理界面比 Apollo 粗糙,权限控制弱、没有审批流程,多人协作容易改出线上事故。选型:团队有运维规范、需要审批和灰度用 Apollo;追求轻量、注册和配置一把梭、项目初期快速落地用 Nacos。别两个都上,运维成本翻倍。

【面试题】7. Sentinel 的滑动窗口限流跟普通计数器限流有什么本质不同?为什么更精准? ​

【标准答案】计数器限流是"固定窗口"——比如 QPS=100 拆成每秒一个窗口,第 1 秒最后 0.1 秒突增 100 个请求,第 2 秒最早 0.1 秒又来 100 个,计数器会说两秒都 OK,但实际上 0.2 秒内打了 200 个请求,系统早崩了。这是固定窗口的"临界突变"问题。滑动窗口把 1 秒拆成多个小格(Sentinel 默认 2 个,可调),窗口随当前时间滑动。统计 QPS 时不是看固定秒,而是看"过去 1 秒内所有格子的总数"。这样临界点的突发流量被精确捕获,不会漏过。Sentinel 用 LeapArray 数据结构实现,O(1) 更新和查询。面试加分:滑动窗口解决的是"临界问题",但这还不够——配合 Sentinel 的排队等待(匀速器模式)把突发流量削峰填谷,才是生产级限流。

【面试题】8. 分布式事务三大方案(2PC / TCC / 可靠消息最终一致性)怎么选?画出你的决策树。 ​

【标准答案】决策三步走。第一步看强一致性要求:必须即时一致?用 2PC(Seata AT 模式),比如跨行转账不卖空,但要做好性能评估——2PC 持有锁时间长,高并发场景可能拖垮整个链路。第二步看业务能否接受中间态回滚:能接受用 TCC,业务代码实现 Try/Confirm/Cancel 三阶段,典型是下单扣库存——Try 预扣、Confirm 确认扣减、Cancel 释放。TCC 性能好但侵入性强,每个服务都要写补偿代码。第三步看能否接受异步最终一致:能用消息触发就用"可靠消息最终一致性",核心思路——本地事务和消息投递绑定在一起(事务消息表/RocketMQ 事务消息),下游消费消息做本地事务,失败重试加人工对账兜底。一句话口诀:一致性要求越高方案越重越复杂,能最终一致就别碰 TCC,能 TCC 就别碰 2PC。

【面试题】9. Redisson 分布式锁的"看门狗"机制是怎么防止锁过期的?不用看门狗会有什么问题? ​

【标准答案】问题场景:你设了锁 30 秒过期,但业务逻辑跑了 35 秒——锁在第 30 秒自动释放了,另一个线程抢到锁,两人同时操作同一资源,分布式锁形同虚设。Redisson 的看门狗(Watch Dog)是这样工作的:你加锁时不设过期时间,Redisson 默认给 30 秒,同时后台启动一个定时任务每 10 秒(internalLockLeaseTime/3)检查这把锁还在不在,还在就续期到 30 秒。业务执行完 unlock 时,看门狗自动停掉。这就是"自动续期",让你不必纠结锁的过期时间。注意三点:① 看门狗只在未显式指定 leaseTime 时生效;② 续期有主从延迟风险,Redis 主节点挂了锁可能丢失,极端场景加 RedLock;③ 别把看门狗当万能,业务代码还是尽量在锁过期时间内跑完,续期是兜底不是依赖。

【面试题】10. 线上微服务调用链超时,怎么排查是哪个环节慢了? ​

【标准答案】三步定位法。第一步看链路追踪:SkyWalking/Zipkin/Pinpoint 拉这次请求的 Trace 链路图,一眼看出哪个 Span 耗时占比最大、哪个服务在拖后腿。没有链路追踪?那就是第一个要补的债。第二步锁定耗时源头后分层排查:如果是数据库查询慢——查慢 SQL 日志,看是不是新上的接口没走索引或者说 SQL 产生了大量回表;如果是远程调用慢——看是不是下游服务被限流/熔断了,线程池满了排队,或者序列化反序列化开销大;如果是 GC 停顿——查 GC 日志,确认是不是 Young GC 频繁或 Full GC 导致 STW。第三步交叉验证:同一时间点查系统监控(CPU/内存/磁盘 IO/网络带宽)和 JVM 监控(堆内存/线程状态),看是不是资源瓶颈导致连锁反应。核心思想:Trace 定位→Metrics 定性→Logs 定因,三支柱联动排查,缺一个都得慢半拍。