Skip to content

微服务与分布式系统面试题 ​

生成时间:2026-06-19 16:29 | 共 10 题 | 难度递进:基础 → 进阶 → 高阶


【面试题】1. 服务网关在微服务体系里扮演什么角色?Gateway 和 Zuul 的核心差异是什么? ​

【标准答案】网关就是整个微服务体系的"大门",所有外部请求先进网关,再由网关转发到对应服务。三个核心作用:路由转发——根据 URL 把请求路由到不同服务;统一横切处理——认证鉴权、限流、日志、跨域全在网关层搞定,不用每个服务重复写;协议转换——外部 HTTP 进来,内部可能转成 Dubbo/gRPC 调用。Gateway 和 Zuul 的核心差异:编程模型——Gateway 基于 Spring 5 + WebFlux 响应式编程,非阻塞 IO,线程开销低;Zuul 1.x 基于 Servlet 同步阻塞,Zuul 2.x 虽然也做 NIO 但落地远不如 Gateway。性能上 Gateway 高并发场景 QPS 明显更高。生态上 Gateway 和 Spring Cloud 全家桶集成更丝滑。一句话:新项目无脑选 Gateway,老项目如果绑 Zuul 1.x 也没必要为换而换。


【面试题】2. 服务端负载均衡和客户端负载均衡有什么不同?一致性哈希适合什么场景? ​

【标准答案】服务端负载均衡(Nginx、F5):请求先打到 LB,LB 再分发给后端,客户端不感知后端有多少实例。优点是简单、客户端无感知;缺点是 LB 本身可能成瓶颈。客户端负载均衡(Ribbon、LoadBalancer):客户端从注册中心拉服务列表,自己选一个实例发起调用。优点是去中心化,没有单点瓶颈;缺点是客户端变重了,需要感知注册中心。一致性哈希的关键场景是有状态服务或缓存集群扩容缩容——比如分布式缓存加一个节点,普通哈希会导致大部分 key 映射错乱引发缓存雪崩,一致性哈希只影响相邻节点的数据迁移量,大幅降低缓存大面积失效的风险。面试官爱听这句:一致性哈希解决了"加机器别影响太大"的问题,Dubbo 的一致性哈希负载均衡就是用来粘会话、粘缓存的。


【面试题】3. 雪花算法原理是什么?时钟回拨问题有哪几种解法? ​

【标准答案】雪花算法把一个 64 位 Long 做位拆分:1 位不用 + 41 位时间戳(毫秒) + 10 位机器 ID + 12 位序列号。保证单机每毫秒生成 4096 个 ID,全局趋势递增。优点是本地生成、高性能、不需要依赖数据库或 Redis。核心痛点是时钟回拨——NTP 对时把机器时间往回拨了,可能导致 ID 重复。三种解法:一是抛异常等时钟追上来(最粗暴);二是预留一定回拨容忍窗口,比如回拨 5 秒以内用之前的时间戳继续累加序列号;三是用 Leaf 的优化方案——把机器 ID 做成 ZK 临时节点,回拨时换一个新的 workerId。美团的 Leaf 方案是"双 buffer 优化号段模式 + 雪花算法混合",号段模式批量从 DB 取号段再本地发放,雪花算法作为高性能补充。实际项目用小雪花足够了,大厂上 Leaf。


【面试题】4. 可观测性三支柱 Logging、Metrics、Tracing 各自关注什么?三者如何协同排查一次线上慢请求? ​

【标准答案】Logging 是"谁在什么时候干了什么"——记录离散事件,比如下单成功、参数错误,适合定位已知问题的上下文。Metrics 是"系统整体状态怎么样"——聚合数值,比如 QPS、RT、错误率,适合发现问题和告警。Tracing 是"一个请求经历了什么"——全链路追踪,适合定位单个请求的瓶颈。三者协同排查慢请求的黄金路径:第一步,Metrics 告警——"订单服务 P99 延迟从 200ms 飙升到 2s",你发现异常了,但不知道具体哪个请求慢;第二步,Tracing 定位——顺着慢请求的 TraceId 打开链路,发现瓶颈在库存服务的 MySQL 查询用了 1.8s;第三步,Logging 深挖——按 TraceId 去查库存服务的日志,看到那条 SQL 的入参和执行计划,发现表没走索引。三支柱不是三选一,是三维一体:Metrics 发现问题,Tracing 定界定位,Logging 给根因。


【面试题】5. 单体拆微服务怎么动手?拆的粒度和原则怎么把握? ​

【标准答案】拆之前先别急着动代码,第一步是"懂业务"——把核心业务流程(比如下单、退款)梳理清楚,画出领域模型。第二步"找边界"——用 DDD 的限界上下文来识别聚合根。比如"订单"和"库存"是两个上下文,中间通过事件或接口耦合。第三步"拆数据库"——最难的不是拆代码而是拆表,原来一个 join 搞定的现在要跨服务调用。原则三条:一是先拆边缘(用户、通知),再拆核心(订单、支付);二是以数据为边界,一个服务只持有自己的数据库,其他服务的数据库通过接口调用;三是粒度看团队规模——一个团队能端到端维护 2-3 个微服务是理想状态。千万别拆太碎——一个微服务一个接口的"微服务地狱"比单体还恐怖,拆到每个服务有自己完整的业务闭环为止。


【面试题】6. 服务雪崩是怎么发生的?如何在项目里系统性防止级联故障? ​

【标准答案】雪崩的传染链条:服务 A 调用 B,B 调用 C。C 因为慢 SQL 变慢了,线程池沾满,B 调 C 超时线程也占满,A 调 B 超时线程继续占满,最终整条链路全瘫——这就是级联故障。防止三板斧:第一板斧"熔断"——B 检测到 C 连续超时,直接熔断不再调 C,快速失败,保护自己线程池不被打满。第二板斧"限流"——A 在入口限流,超过阈值的请求直接拒绝,不给下游压力。第三板斧"隔离"——线程池隔离(每个下游服务用独立线程池互不影响)和信号量隔离,Hystrix 和 Sentinel 都支持。额外亮点:加降级兜底——C挂了返回"暂无推荐"而不是报错;加超时控制——别永等,设置合理超时时间。一句话:不要信任任何一个下游,每个调用都要有"它可能挂"的预期。


【面试题】7. 缓存穿透、缓存击穿、缓存雪崩怎么区分?各自怎么解决? ​

【标准答案】三个症状很像但根因不同。缓存穿透:查询一个根本不存在的 key,缓存里没有,每次请求直接穿透到 DB。典型攻击:拿 -1 或随机不存在的商品 ID 疯狂刷。解法:布隆过滤器——先判断 key 是否可能存在,不存在直接拒绝;或者空值缓存——查不到也缓存一个 null,存活时间短点(1-5 分钟)。缓存击穿:一个热 key 过期瞬间,大量并发请求同时去查 DB。比如秒杀商品的缓存刚好在抢购高峰过期。解法:互斥锁——第一个请求去查 DB 并重建缓存,其他请求等它完成;或者"永不过期"——物理过期但逻辑上异步续期。缓存雪崩:大量 key 同时过期,或者 Redis 挂了,请求全砸到 DB。解法:过期时间加随机值散开,避免同一时刻大批量过期;Redis 高可用集群 + 本地缓存多级兜底。


【面试题】8. 微服务架构下,跨服务数据一致性怎么保证?有没有比分布式事务更轻量的方案? ​

【标准答案】说实话,不是所有跨服务场景都要上分布式事务。先分清场景:强一致场景(钱相关)才需要 2PC/TCC 这些重型方案;大部分业务场景用"最终一致 + 补偿"就够了。轻量方案两种:一是本地消息表 + MQ——订单服务先写订单表和一条"待发消息",然后异步发送给 MQ,积分服务消费后处理。关键点:发消息和本地事务绑定在同一 DB 事务,保证消息一定发出(Emitlog 技术);消费端做幂等,用唯一消息 ID 防重。二是业务对账——不做实时事务,T+1 跑对账脚本,发现不一致就补偿修复。这种方案在一致性要求不极端的场景(如用户等级升级、推荐数据同步)特别好用。面试亮点:一致性不是二元的,是渐进的——"实时强一致"、"准实时最终一致"、"离线对账补偿",选择取决于业务容忍度。


【面试题】9. 线上服务器 CPU 突然飙到 100%,你怎么排查?排查思路和常用命令是什么? ​

【标准答案】上来先别慌,也别上来就重启——重启了现场就没了。第一步,top 命令看是哪个进程吃的 CPU,找到对应的 Java 进程 PID。第二步,top -Hp <PID> 看进程里哪个线程 CPU 最高,记下线程 ID(转为十六进制)。第三步,jstack <PID> 把线程堆栈 dump 下来,按十六进制的线程 ID 搜 nid,找到那个线程所在的方法栈——大概率是死循环、GC 频繁或者正则匹配的大字符串。第四步,jstat -gc <PID> 1s 实时看 GC 频率,如果 FullGC 每秒都在跑,说明内存吃紧,进一步 jmap -dump 看对象分布。高频根源:正则表达式回溯爆炸、HashMap 死循环(JDK7)、Stream 并行处理大量数据、JSON 大对象频繁序列化。Arthas 的 thread -n 3 能直接帮你列出 CPU 最高的 3 个线程不用手动转十六进制,效率拉满。


【面试题】10. 从 0 到 1 做一个新项目,你如何规划微服务技术选型和落地方案? ​

【标准答案】面试官问这题不是要标准答案,是看你有没有全局视角。我的回答思路分五步:第一步"评估是否真的需要微服务"——团队 5 人以下、业务验证期、功能简单,果断单体/模块化单体起步,别上来就微服务。"先跑通业务再拆"是铁律。第二步"基础设施先行"——注册中心 Nacos、配置中心、网关 Gateway、链路追踪 SkyWalking,这几个不先搭好后面全是坑。第三步"统一技术栈和规范"——异常处理统一封装、日志规范(TraceId 必带)、接口返回体统一定义、API 文档自动生成,这些比选什么框架更重要。第四步"选核心链路试点"——比如电商先拆订单服务和商品服务,边拆边验证,而不是一次性全拆。第五步"部署与发布"——容器化部署(Docker + K8s 或简单 Docker Compose)、CI/CD 流水线、灰度发布策略。亮点收尾:技术选型没有最好只有最合适,小团队别上 K8s,MySQL + Redis + RocketMQ 三板斧远比花里胡哨的技术栈靠谱。