从网络协议到微服务治理 —— TCP/UDP → 服务治理 → 注册中心 → 熔断限流
10 题 · 平均 2.7/5 · low 2.75 · medium 2.5 · high 3 · 第 1 轮
**核心考点定位**:考察 TCP/UDP 两种传输层协议的核心机制差异,以及背后"可靠性 vs 性能"的设计权衡思想。
**知识点拆解**:
1. **连接模型**:TCP 是有连接的(三次握手建立、四次挥手断开),通信双方必须先握手才能传输;UDP 是无连接的,直接发数据报,没有连接建立和释放过程。
2. **可靠性保障**:TCP 通过序列号 + ACK 确认 + 超时重传 + 校验和实现可靠传输;UDP 仅有校验和(且可选),不保证送达、不保证顺序、不重传。
3. **首部开销**:TCP 首部 20~60 字节,UDP 首部固定 8 字节。对小报文 UDP 优势明显(DNS 单条请求常小于 512 字节)。
4. **有序性**:TCP 通过序列号保证有序到达,乱序包会缓存重排;UDP 保持发送顺序,到达顺序不保证。
5. **流控与拥塞控制**:TCP 有滑动窗口流量控制(接收方通告窗口大小)和拥塞控制(慢启动、拥塞避免、快重传快恢复、AIMD);UDP 都没有。
6. **数据模型**:TCP 面向字节流(丢失消息边界),UDP 面向数据报(保留消息边界)。
> 递进:从"是什么"(连接性、可靠性)→ "怎么做"(握手/重传/流控/拥塞控制)→ "为什么"(首部开销差异导致的应用场景差异)。
**考察方向**:
- **深度**:不只是背差异表,要理解为什么可靠性需要这么多机制(握手建连接状态、序号排顺序、重传保送达、拥塞控制防堵死)
- **广度**:延伸到 HTTP 为什么选 TCP、QUIC 为什么选 UDP 承载、gRPC 底层为什么是 HTTP/2 over TCP
- **应用**:业务选型(RPC、消息推送、实时音视频)、协议栈调优(SO_KEEPALIVE、TCP_NODELAY)
**延伸递进面试题**:
1. **QUIC 为什么基于 UDP 而不是 TCP?**
- 解答要点:TCP 的握手需要 1 RTT 建连、队头阻塞在传输层、无法自定义拥塞控制算法(内核实现改不了);QUIC 用 UDP 承载,把可靠性和拥塞控制上移到用户态,握手可以和 TLS 握手合并到 0~1 RTT,每个流独立避免队头阻塞。
2. **TCP 为什么会队头阻塞?QUIC 如何解决?**
- 解答要点:TCP 是单一字节流有序到达,前面包丢了后面包必须缓存等待,导致后续字节全被堵住;QUIC 在 UDP 之上定义独立 stream,每个流有序,流之间互不阻塞。
3. **你在生产环境遇到过 TCP 相关问题吗?如何排查?**
- 解答要点:TIME_WAIT 过多(`ss -s` 查看,可 sysctl 调 tw_reuse)、SYN 半连接队列满(`tcp_max_syn_backlog`、syncookies)、连接泄漏(netstat -an 看 CLOSE_WAIT)、丢包重传(`netstat -s | grep retrans`、mtr 看链路)。
面试官您好,TCP 和 UDP 最本质的区别是**可靠 vs 性能**,这个权衡决定了一切。
第一个维度是**连接性**。TCP 是有连接的,先三次握手建立连接,再传数据,最后四次挥手释放。这就带来一个好处——连接建立后有一个稳定的上下文。UDP 无连接,直接发数据报,没有握手过程。
第二个维度是**可靠性**。TCP 通过序列号 + ACK 确认 + 超时重传 + 校验和实现可靠传输,保证数据不丢、不重复、有序到达。UDP 只有一个可选的校验和,其他什么都不做。
第三个维度是**首部开销**。TCP 首部 20 字节起,UDP 固定 8 字节。对小报文,比如 DNS 一条查询几十字节,UDP 的优势明显。
第四个维度是**流控和拥塞控制**。TCP 有滑动窗口做流量控制,接收方控制发送速度;还有慢启动、拥塞避免、快重传快恢复做拥塞控制,防止把网络打爆。UDP 都没有,应用自己负责。
第五个维度是**数据模型**。TCP 是字节流,会丢失消息边界;UDP 是数据报,保留消息边界,一发一收对应。
应用场景上,HTTP、SSH、数据库协议都选 TCP,因为要可靠;DNS 短查询选 UDP、视频直播、实时音视频、游戏选 UDP,因为丢了不重要、速度更重要。现在 QUIC 用 UDP 承载,把可靠性和拥塞控制上移到用户态,就是为了绕开内核 TCP 的限制,做到握手和 TLS 合并、避免队头阻塞。
**核心考点定位**:考察 TCP 连接建立与释放的具体报文交换流程、状态机流转,以及设计背后的原因。
**知识点拆解**:
1. **三次握手流程**(建立连接):SYN → SYN+ACK → ACK,双方通过交换初始序列号确认彼此的收/发能力。
2. **为什么是三次**:两次不行——服务端可能重复建立早已失效的历史连接,浪费资源;三次是最少的可靠握手次数(每次交互双方各确认一次收发能力,需要 3 次报文才能完成)。
3. **四次挥手流程**(释放连接):FIN → ACK → FIN → ACK,被动方需要独立回 ACK 因为它可能还有数据要发完。
4. **为什么挥手是四次**:TCP 是全双工,双向连接要分别关闭。FIN 表示"我这边没数据要发了",而 ACK 表示"我知道你要关了",两者不能合并(因为 ACK 时可以还有数据待发)。
5. **TIME_WAIT 与 2MSL**:主动关闭方进入 TIME_WAIT 状态等待 2MSL(Linux 默认 60s)。目的是(1)保证最后一个 ACK 到达,若丢失被动方可重发 FIN;(2)让旧连接的延迟报文在网络中自然消亡,避免污染新连接。
6. **异常场景**:SYN Flood 攻击(半连接队列被打满)、TIME_WAIT 过多(大量短连接导致)、CLOSE_WAIT 堆积(应用层未 close socket 代码 bug)。
> 递进:握手是"三次因为要确认双向收发",挥手是"四次因为全双工要分开关"。
**考察方向**:
- **深度**:状态机流转、SYN/FIN/ACK 标志位含义、MSL 定义
- **广度**:QUIC 如何把握手和 TLS 合并到 0-1 RTT、HTTP 长连接如何复用 TCP 连接
- **应用**:生产环境 TIME_WAIT 过多的排查与调优、SYN Flood 防御
**延伸递进面试题**:
1. **两次握手为什么不行?**
- 解答要点:客户端发的 SYN 如果在网络中延迟,服务端以为要建连回 SYN+ACK,客户端不会理睬;服务端却进入 ESTABLISHED 状态浪费资源。三次握手中客户端收到迟到的 SYN+ACK 会回 RST。
2. **生产环境大量 TIME_WAIT 怎么办?**
- 解答要点:查看 `ss -s`、`netstat -an | grep TIME_WAIT | wc -l`;调 `sysctl.net.ipv4.tcp_tw_reuse=1`(4.12+)复用 TIME_WAIT socket;根本方案是复用连接(HTTP Keep-Alive、连接池)。
3. **CLOSE_WAIT 堆积说明什么?**
- 解答要点:对方已发 FIN 但自己应用未调用 close(),通常是代码 bug 或 socket 未关闭导致的泄漏,需检查应用代码。
4. **如何防止 SYN Flood 攻击?**
- 解答要点:SYN cookies(`tcp_syncookies=1`)、增加半连接队列 `tcp_max_syn_backlog`、缩短 `tcp_synack_retries`、用 iptables 限速。
面试官您好,TCP 三次握手和四次挥手我分开讲。
**三次握手**:目的是双向确认彼此的收发能力。
- 第一次:客户端发 `SYN, seq=x`,进入 `SYN_SENT` 状态;
- 第二次:服务端回 `SYN+ACK, seq=y, ack=x+1`,进入 `SYN_RCVD`,既确认了客户端的 SYN,也把自己的 SYN 发出去;
- 第三次:客户端回 `ACK, ack=y+1`,进入 `ESTABLISHED`,服务端收到 ACK 后也进入 `ESTABLISHED`。
**为什么是三次**:两次不够,如果客户端的 SYN 在网络中延迟到达,服务端可能建立一条已经没用的连接。三次是"每次交互双方各确认一次"的最小交互次数。
**四次挥手**:连接是全双工的,要分别关,所以不能像握手那样合起来。
- 第一次:主动方发 `FIN`,进入 `FIN_WAIT_1`;
- 第二次:被动方回 `ACK`,进入 `CLOSE_WAIT`,主动方进入 `FIN_WAIT_2`;(这时候被动方可能还有数据要发,所以不能把 FIN 合并到 ACK)
- 第三次:被动方数据发完,发 `FIN`,进入 `LAST_ACK`;
- 第四次:主动方回 `ACK`,进入 `TIME_WAIT`,等 2MSL 后 CLOSE;被动方收到 ACK 后 CLOSE。
**TIME_WAIT 为什么要等 2MSL**:一是保证最后一个 ACK 能到达被动方,如果丢了被动方会重发 FIN;二是让旧连接的所有报文都自然消亡,避免污染同一个四元组的新连接。生产上如果 TIME_WAIT 太多,通常意味着大量短连接,可以开启 `tcp_tw_reuse` 或者复用连接。
**CLOSE_WAIT 堆积**是另一种异常,说明应用代码没 close socket,通常是 bug。
**核心考点定位**:考察对微服务本质的理解,是否清楚演进动因、核心特征、优势代价的权衡,而非仅仅背一堆名词。
**知识点拆解**:
1. **演进脉络**:单体 → 垂直拆分(按功能层)→ SOA(企业服务总线) → 微服务(轻量通信 + DevOps)。微服务不是新技术,是新的**组织与治理方式**。
2. **7 大核心特征**(Martin Fowler):围绕业务组织、去中心化治理、去中心化数据、智能端点 + 轻量通信、基础设施自动化、设计失败(每个服务可以独立失败演进)、组合而非继承。
3. **5 大优势**:独立部署、故障隔离、按需扩展、团队独立、技术栈灵活。
4. **5 大代价**:分布式一致性、跨服务调用损耗、服务治理复杂度、可观测性挑战、分布式事务。
5. **拆分边界**:DDD 领域驱动设计,按业务限界上下文(Bounded Context)拆分,而不是按技术层(web/service/dao)拆。
> 递进:从"为什么拆"(单体瓶颈)→ "拆成什么样"(业务边界)→ "拆完要付出什么"(分布式复杂度)。
**考察方向**:
- **深度**:DDD 限界上下文划分方法、服务边界如何定义
- **广度**:与 SOA、Serverless、Service Mesh 的关系
- **应用**:拆分原则、什么时候不该用微服务、单体优先原则
**延伸递进面试题**:
1. **什么时候不该用微服务?**
- 解答要点:团队小于 8 人、业务没跑通、迭代频繁还未稳定、性能敏感场景。Amazon 有 "Monolith First, Microservices Second" 的原则。
2. **拆分微服务有哪些原则?**
- 解答要点:高内聚低耦合、单一职责、避免共享状态和数据库、避免循环依赖、按业务能力而非技术层拆、控制爆炸半径。
3. **微服务如何通信?同步 vs 异步怎么选?**
- 解答要点:强一致、需要同步返回 → REST/gRPC;解耦、削峰、最终一致 → MQ。远程调用要超时 + 重试 + 熔断 + 幂等。
4. **康威定律是什么?为什么对微服务重要?**
- 解答要点:系统架构最终会反映组织的沟通结构。所以微服务的拆分必须匹配团队边界,一个团队负责一个服务,避免跨团队调用。
面试官您好,微服务是从单体演进出来的架构风格。
**演进过程**是这样:最早单体一个大应用,简单好上手;单机有瓶颈,就把多个单体实例放多台机器做横向扩容;但整体部署导致无法按需扩缩容——用户服务要 20 副本,支付服务只要 2 副本,被迫一起扩,资源浪费;再往后按功能域拆分成多个独立部署的小服务,就是微服务。
**特点**上我记 7 条:围绕业务能力构建、去中心化治理、去中心化数据(每个服务自己的 DB)、智能端点 + 轻量通信(HTTP/gRPC/消息)、基础设施自动化(CI/CD)、可以设计失败、组合而非继承。
**优势**主要是:
1. 独立部署——支付改了只发支付,不影响用户;
2. 故障隔离——一个服务挂了不拖垮整个系统;
3. 按需扩展——按业务量给服务单独扩缩容;
4. 多团队并行——一个团队一个服务,符合康威定律;
5. 技术栈灵活——支付可以用 Go,用户可以用 Java。
**代价**要正视:
1. 分布式一致性——数据不在一起了,2PC/TCC/SAGA/本地消息表各种方案;
2. 跨服务调用有网络开销,比内调用慢;
3. 服务治理成本——注册中心、网关、熔断、限流、链路追踪都要搭;
4. 排查复杂——一个请求跨 5 个服务,出问题很难定位。
**实践上**:团队小、业务没跑通,先做单体(Monolith First);只有当单体真的扛不住(比如团队大于 20 人、某个模块需要独立扩展),再按 DDD 的限界上下文拆分。拆得太细和没拆,都是坑。
**核心考点定位**:考察对 Nacos 定位的清晰认识——它是"注册中心 + 配置中心"二合一的组件,以及 AP/CP 双模式的设计理念。
**知识点拆解**:
1. **定位**:Nacos 是阿里开源的动态服务发现、配置和服务中心(Dynamic Naming and Configuration Service),Spring Cloud Alibaba 生态的核心组件。
2. **服务注册与发现**:
- 客户端模式:服务启动时把自身注册到 Nacos,通过 SDK 拉取服务列表并缓存本地,定期(默认 10s 心跳,15s 判定不健康)
- 服务端模式:Nacos 主动推送给消费端(1.4 版本引入,基于 UDP)
3. **配置中心**:
- 命名空间(Namespace)→ 分组(Group)→ DataId → Group 层级管理
- 支持热更新:`@NacosValue(autoRefreshed=true)` 或 Spring Cloud 的 `@RefreshScope`
- 1.x 用 HTTP 长轮询(30s),2.x 用 gRPC 长连接推送
4. **临时/永久实例**:
- 临时实例:AP(Distro 协议,异步复制),适合有生命周期管理的服务实例
- 永久实例:CP(Raft 协议,强一致),适合 DB 主库、消息队列等有状态节点
5. **AP/CP 双模式**:Nacos 通过实例类型决定用哪种一致性,这是它最大的差异化设计
> 递进:从"是什么"(命名 + 配置二合一)→ "怎么用"(注册 + 配置)→ "怎么保证一致"(AP/CP 双模式)。
**考察方向**:
- **深度**:Distro vs Raft 一致性协议、临时/永久实例切换
- **广度**:与 Eureka(AP-only)、Zookeeper(CP-only)、Consul 的对比
- **应用**:Nacos 集群部署、配置灰度发布、集群容灾
**延伸递进面试题**:
1. **Nacos 是 AP 还是 CP?**
- 解答要点:都支持,取决于实例类型。临时实例用 Distro(AP),永久实例用 Raft(CP)。这是 Nacos 相比 Eureka/Zookeeper 的独特之处。
2. **Nacos 如何做高可用部署?**
- 解答要点:至少 3 节点集群,客户端配置多地址;依赖 MySQL 或内嵌 Derby(生产必须外置 MySQL);用 gRPC 端口(8848 主端口 + 2 个偏移端口 9848/9849)。
3. **Nacos 和 Eureka 有什么区别?**
- 解答要点:Eureka 是纯 AP,Nacos 是 AP/CP 双模式;Eureka 无配置中心,Nacos 有;Eureka 客户端有自我保护机制,Nacos 通过健康检查;Nacos 支持配置中心,功能更全。
4. **Nacos 2.x 相比 1.x 有哪些改进?**
- 解答要点:长轮询改为 gRPC 长连接,降低网络开销、支持大流量推送;性能提升 10 倍;支持 Raft/JRaft 实现 CP 一致性;提供 Raft 集群容灾能力。
面试官您好,Nacos 是阿里开源的动态服务发现和配置中心(Dynamic Naming and Configuration Service),是 Spring Cloud Alibaba 的核心组件,把注册中心和配置中心合二为一。
**两大核心功能**:
1. **服务注册与发现**:微服务启动时把自己注册到 Nacos,其他服务通过 Nacos 拿到可用实例列表;支持临时/永久两种实例,临时实例靠心跳续约(默认 15s 判定不健康自动摘除);
2. **配置中心**:把配置从代码里抽出来集中管理,通过命名空间/分组/DataId 组织,支持 properties/yml/json 格式;配置变更后自动推送给客户端,配合 `@NacosValue(autoRefreshed=true)` 或 `@RefreshScope` 实现热更新,不用重启服务。
**Nacos 最大亮点是 AP/CP 双模式**:
- 临时实例走 Distro 协议(AP,异步复制),节点挂掉自动摘除,适合无状态服务;
- 永久实例走 Raft/JRaft 协议(CP,强一致),适合数据库主库等有状态节点。
- 这一点上 Nacos 比 Eureka(纯 AP)和 Zookeeper(纯 CP)都灵活。
**版本演进**:
- 1.x:HTTP 长轮询拉取配置,UDP 推送服务列表;
- 2.x:改为 gRPC 长连接,性能提升 10 倍,支持 Raft 强一致;
- 3.x:加入 Kubernetes 兼容、多租户治理、AI 推理服务注册等。
**部署建议**:生产至少 3 节点集群,用外置 MySQL 存元数据,客户端配置多个 Nacos 地址;监听端口 8848(HTTP)+ 9848/9849(gRPC)。
**核心考点定位**:考察对微服务通信模式的完整认知,不只是列举几个名字,而是理解同步/异步的本质差异和选型权衡。
**知识点拆解**:
1. **同步通信**:请求-响应模式,调用方阻塞等待返回。
- **RESTful HTTP + JSON**:简单、跨语言、易调试,OpenFeign/RestTemplate/WebClient 是主要客户端
- **gRPC**:HTTP/2 + Protobuf,多路复用、二进制压缩、双向流(Unary/Server-Stream/Client-Stream/Bidirectional)
- **Dubbo**:阿里开源,Java 生态,Netty + 自定义协议,支持多种负载均衡和容错策略
- **Thrift**:Facebook 开源,跨语言强,Facebook/Meta 内部主力
2. **异步通信**:发布-订阅模式,双方解耦。
- **消息队列**:Kafka(日志)、RabbitMQ(路由)、RocketMQ(事务消息)、Pulsar(分层存储)
- **事件驱动**:Event Bus、Event Sourcing,服务发布领域事件,其他服务订阅
3. **反模式**:
- 共享数据库(DB as Message Bus):数据强一致但强耦合,通常不推荐
- 直接调用内部函数:无法解耦、无法独立部署,违背微服务初衷
4. **选型原则**:
- 强一致 + 实时返回 → 同步(HTTP/gRPC)
- 解耦 + 削峰 + 最终一致 → 异步(MQ)
- 高性能 + 强类型契约 → gRPC/Dubbo
- 快速迭代 + 灵活查询 → GraphQL
> 递进:先分"同步 vs 异步",再在同步下细分协议,异步下细分 MQ。每种方式的治理策略也不同。
**考察方向**:
- **深度**:gRPC 4 种流模式、Protobuf 编码原理、HTTP/2 多路复用
- **广度**:与 HTTP/2、HTTP/3/QUIC 的演进关系
- **应用**:同步调用的治理(超时/重试/熔断/幂等)、异步消息的可靠投递(at-least-once)
**延伸递进面试题**:
1. **HTTP 调用为什么还需要治理?"不用额外处理"错在哪?**
- 解答要点:跨网络调用要考虑超时(默认不设导致线程池打满)、重试(网络抖动)、熔断(下游挂了要快速失败)、幂等(重试要安全)、链路追踪(traceId 透传)。HTTP 只是协议,治理是必需的。
2. **gRPC 相比 HTTP/JSON 好在哪?**
- 解答要点:HTTP/2 多路复用避免队头阻塞、Protobuf 二进制压缩率高、强类型契约(.proto)、支持双向流式通信、跨语言自动代码生成。
3. **什么场景必须用异步消息?**
- 解答要点:下单后通知库存扣减、通知积分、通知风控——这些是副作用,可以延迟;下游挂了不能阻塞下单主流程;MQ 削峰,避免秒杀流量打爆下游。
4. **Feign 和 RestTemplate 和 WebClient 有什么区别?**
- 解答要点:Feign 是声明式(写接口就行,OpenFeign + 负载均衡)、RestTemplate 是命令式(编程式,同步阻塞)、WebClient 是响应式(基于 Netty,支持 HTTP/2 多路复用)。Spring 官方推荐用 WebClient 替代 RestTemplate。
面试官您好,微服务调用方式我按**同步 vs 异步**两大类来讲。
**同步通信**:请求-响应,调用方阻塞等待。
- **RESTful HTTP + JSON**:最简单,OpenFeign、WebClient 是主要客户端,几乎所有语言都支持,易调试;
- **gRPC**:HTTP/2 + Protobuf 二进制,多路复用、强类型契约、支持 4 种流模式(Unary/Server-Stream/Client-Stream/Bidirectional);性能比 HTTP/JSON 高,但可读性差;
- **Dubbo**:阿里开源,Java 生态成熟,Netty + 自定义协议,支持丰富的负载均衡和容错;
- **Thrift**:Facebook 出品,跨语言强,海外用得更多。
**异步通信**:发布-订阅,解耦。
- **消息队列**:Kafka(日志流)、RabbitMQ(路由复杂)、RocketMQ(事务消息)、Pulsar(分层存储);
- **事件驱动**:Event Bus + Event Sourcing,服务发领域事件,其他服务订阅;
- **反模式**:共享数据库(DB as Message Bus),强耦合,一般不推荐。
**选型**:
- 强一致 + 实时返回(查询订单、支付确认)→ HTTP/gRPC;
- 解耦 + 削峰 + 最终一致(下单后扣库存、发通知、积分变动)→ MQ;
- 高性能强类型内部通信 → gRPC/Dubbo。
**同步调用必须有治理**:不能"直接调接口"就算了。要设超时(默认不设会线程池打满)、按幂等做重试、配熔断(Sentinel/Hystrix/Resilience4j)、限流、traceId 透传做链路追踪。这几点不做,生产必出问题。
**核心考点定位**:考察对 Nacos 客户端与集群两端交互全流程的深入理解,尤其是心跳续约和健康检查机制。
**知识点拆解**:
1. **服务注册流程**:服务启动 → 上报实例(IP/port/权重/metadata)→ Nacos 集群同步(Distro/Raft)→ 客户端心跳续约(5s/次,15s 判不健康,30s 剔除)→ 优雅关闭时主动反注册。
2. **服务发现流程**:消费端启动 → 拉取服务列表并本地缓存 → 建立监听(长轮询或 gRPC push)→ 变化时更新缓存 → 负载均衡选实例发起调用。
3. **心跳 vs 健康检查**:临时实例走客户端推(心跳),永久实例走服务端拉(TCP check)。
4. **集群内同步**:
- Distro:临时实例用,AP 一致性,异步复制,容错好
- Raft/JRaft:永久实例用,CP 一致性,强一致,性能稍低
5. **配置监听**:1.x 长轮询(30s 挂起),2.x gRPC 长连接(推送更快、开销更小)
6. **本地缓存**:客户端缓存 Nacos 数据(文件缓存),Nacos 集群挂了仍能读到最近一次的服务列表,实现降级。
> 递进:注册是"上报+心跳续约",发现是"拉取+监听+本地缓存"。Nacos 用双一致性模型支撑两类实例。
**考察方向**:
- **深度**:心跳机制的三级判定(healthy → suspicious → un-healthy)、Distro 协议如何保证 AP 一致
- **广度**:Eureka 的自我保护、Zookeeper 的 Watch 机制、Consul 的健康检查方式对比
- **应用**:生产环境 Nacos 集群挂了怎么办、如何优雅下线、如何排查服务列表不更新
**延伸递进面试题**:
1. **临时实例和永久实例有什么区别?心跳机制为什么重要?**
- 解答要点:临时实例用 Distro(AP)+ 心跳续约,节点挂掉自动摘除,适合无状态服务;永久实例用 Raft(CP)+ 服务端主动 check,不自动剔除,适合数据库等有状态节点。心跳是临时实例存活的证明。
2. **Nacos 集群挂了,服务还能继续通信吗?**
- 解答要点:可以,客户端本地有缓存,服务列表最近一次的快照能读;已建立的连接不受影响;只是新的实例变化感知不到,健康状态也不会更新。所以生产 Nacos 至少 3 节点。
3. **Nacos 1.x 和 2.x 的服务发现机制有什么区别?**
- 解答要点:1.x 用 HTTP 长轮询(30s),2.x 用 gRPC 长连接推送,性能提升 10 倍;2.x 支持 Raft 强一致,1.x 只支持 Distro;2.x 端口多 9848/9849 两个 gRPC 端口。
4. **Nacos 服务发现的推送机制和 Eureka 的自我保护有什么区别?**
- 解答要点:Nacos 是实时推送,客户端本地缓存;Eureka 是客户端主动拉取 + 自我保护(30 秒内 15% 掉线不摘除,防止网络抖动误杀)。Eureka 只适合短连接 + 客户端拉取场景。
面试官您好,Nacos 的服务注册和发现是两个方向相反的交互流程,我分开讲。
**服务注册**分 4 步:
1. **启动上报**:服务启动时通过 SDK 调 `NamingService.registerInstance()`,底层是 HTTP PUT `/nacos/v1/ns/instance`(2.x 是 gRPC),把自身 IP、端口、权重、metadata 上报给 Nacos;
2. **集群同步**:Nacos 接收后,临时实例走 Distro 协议把数据异步复制到集群其他节点(AP 最终一致),永久实例走 Raft(CP 强一致);
3. **心跳续约**:客户端每 5 秒发一次心跳 `/nacos/v1/ns/instance/beat`;Nacos 判 15 秒没心跳标记为不健康、30 秒还没心跳就自动剔除;
4. **优雅下线**:服务关闭时调 `DeregisterInstance` 接口主动反注册,避免被误杀。
**服务发现**分 3 步:
1. **首次拉取**:消费端启动时调 `getInstances()` 或 `subscribe()`,HTTP GET `/nacos/v1/ns/instance/list?serviceName=xxx` 拿到全部健康实例,**本地缓存**这份列表;
2. **监听变化**:1.x 用长轮询(30 秒挂起连接,有变化立即返回),2.x 用 gRPC 长连接(服务端 push);有实例上下线时立即更新本地缓存;
3. **负载均衡调用**:消费端从本地缓存里按轮询/随机/权重/一致性哈希选实例发起实际调用。
**两个关键点**:
- **客户端本地缓存很重要**:Nacos 集群挂了,客户端还能读缓存,服务发现降级不断;
- **临时/永久实例区别**:临时走 AP + 心跳续约,永久走 CP + 服务端主动 check。
**核心考点定位**:考察对负载均衡本质(分发流量提高可用性)和主流算法适用场景的理解。
**知识点拆解**:
1. **负载均衡三层**:
- **网络层**:LVS(四层)、F5(七层硬件)
- **应用层**:Nginx、HAProxy(七层,HTTP/gRPC)
- **客户端**:Ribbon、Spring Cloud LoadBalancer、Dubbo Consumer
2. **常见算法**:
- **轮询**:无状态无感知,机器同构时最简单
- **加权轮询**:机器异构(8C16G vs 4C8G)时按权重分配
- **随机**:数学上均衡,但短期可能有波动
- **一致性哈希**:节点上下线只影响 N/K 请求,避免缓存击穿;配合虚拟节点避免数据倾斜
- **最少响应时间**:适合机器性能差异大的场景
- **最少活跃连接**:适合长连接、后端有队列的场景
3. **取模的问题**:节点数变化时,几乎所有数据都要重新分布,不适合缓存场景
4. **一致性哈希原理**:把所有节点映射到哈希环,请求也映射到环上顺时针取第一个节点;扩容时只影响新节点和邻居节点之间的请求
> 递进:先按"负载均衡位置"分(网络层/应用层/客户端),再按算法分(简单→复杂→动态)。
**考察方向**:
- **深度**:一致性哈希的虚拟节点机制、取模在扩缩容时的重新分布问题
- **广度**:与流量调度、Service Mesh(Istio sidecar)的关系
- **应用**:不同业务场景选什么算法、Nginx upstream 配置、Dubbo 负载均衡配置
**延伸递进面试题**:
1. **一致性哈希如何解决数据倾斜?**
- 解答要点:引入虚拟节点,每个真实节点在环上生成 100-200 个虚拟节点,让数据分布更均匀。扩容时新节点抢占原有虚拟节点的数据范围。
2. **取模在节点扩缩容时有什么问题?**
- 解答要点:假设有 N 台机器,取模 N 分配;扩容到 N+1 后,几乎所有 key 的取模结果都变了,导致所有缓存失效、请求雪崩到后端。一致性哈希只影响 N/(N+1) 的请求。
3. **客户端 LB 和服务端 LB 有什么区别?**
- 解答要点:客户端 LB 无第三方,性能高,但每个客户端都要实现;服务端 LB 集中在网关/LB,运维简单,但多一跳。Service Mesh(Istio)把客户端 LB 下沉到 sidecar。
4. **Nginx 配置 upstream 时如何选算法?**
- 解答要点:`ip_hash` 让同一 IP 命中同一后端(会话保持);`least_conn` 最少连接;`hash $uri` 一致性哈希(Nginx 1.9.0+);`balance` 是阿里云自研的一致性哈希。
面试官您好,负载均衡是分布式系统里把流量分发到多个后端实例的机制,目的是提高吞吐、隐藏单点故障、支持水平扩展。
**核心定义**:通过算法把请求分给多台机器,让每台机器的负载接近。
**位置分 3 层**:
- **网络层**:LVS(四层)、F5(七层硬件 LB)
- **应用层**:Nginx、HAProxy(七层,支持 HTTP/gRPC)
- **客户端**:Ribbon、Spring Cloud LoadBalancer、Dubbo Consumer
**常见算法**:
1. **轮询(Round Robin)**:最简单,默认算法,同构机器时均衡性好;
2. **加权轮询**:机器异构(8C16G vs 4C8G)时按权重分配,8C16G 权重 4,4C8G 权重 2;
3. **随机/加权随机**:统计上均衡,实现简单;
4. **一致性哈希**:节点扩缩容时只影响 N/K 的请求,避免缓存击穿,配合虚拟节点(一般 150 个/节点)避免数据倾斜;
5. **最短响应时间**:按历史响应时间选,适合后端性能差异大;
6. **最少活跃连接**:按当前并发数选,适合长连接、后端有队列的场景。
**典型场景选型**:
- 无状态 API 服务 → 轮询/随机最简单;
- 会话保持(登录后一直走同一台)→ 一致性哈希 + IP hash;
- 缓存场景(Redis 分片、Memcached)→ 一致性哈希,避免扩缩容全量失效;
- 机器性能差异大 → 加权轮询或最短响应时间;
- 有长连接后端(如 MQ Consumer)→ 最少活跃连接。
**取模的坑**:节点数变了几乎所有 key 都要重分,缓存全失效,所以缓存场景不用取模。
**核心考点定位**:考察对三种流量治理策略本质区别、使用场景、组合方式和主流实现工具的理解。
**知识点拆解**:
1. **限流(Rate Limiting)**:控制入口流量,防止系统被打爆。作用于**本服务**。
- 算法:计数器(简单但边界突发)、漏桶(恒定速率出)、令牌桶(允许突发)、滑动窗口(精细统计)
- 层级:单机限流(Guava RateLimiter)、集群限流(Redis + Lua、Sentinel 集群限流)
2. **熔断(Circuit Breaking)**:保护下游依赖,防止调用失败拖垮调用方。作用于**下游服务**。
- 三态:CLOSED → OPEN → HALF-OPEN → CLOSED
- 触发条件:错误率、错误数、慢调用比例
- 探测机制:OPEN 后等待恢复期,切 HALF-OPEN 放少量请求探测
3. **降级(Fallback/Degrade)**:兜底策略,让系统在异常下仍可用。作用于**本服务对外接口**。
- 类型:服务降级(返回兜底值)、功能降级(隐藏非核心功能如推荐/评论)、数据降级(返回缓存旧数据)、排队降级(进队列稍后处理)、消息降级(同步转异步)
4. **三者关系**:
- 限流 = 入口守门员(控制总流量)
- 熔断 = 下游保险丝(保护调用方)
- 降级 = 兜底策略(保证可用)
5. **主流工具**:
- Hystrix(Netflix,已停止维护,但概念经典)
- Sentinel(阿里,功能更全面:限流/熔断/降级/热点参数)
- Resilience4j(Hystrix 替代,Java 8+,模块化)
> 递进:从"三种策略是什么"→ "各自作用点在哪"→ "如何在生产组合使用"。
**考察方向**:
- **深度**:熔断三态迁移细节、Sentinel 的自适应限流(自适应流量控制)
- **广度**:与网关限流、K8s 服务治理、Service Mesh 的关系
- **应用**:不同业务场景选限流还是熔断、阈值如何确定
**延伸递进面试题**:
1. **熔断三态具体怎么迁移?**
- 解答要点:CLOSED(正常放行)→ 触发阈值(如 10s 内错误率>50%)→ OPEN(快速失败,不再调用)→ 等恢复期(如 10s)→ HALF-OPEN(放一半请求探测)→ 探测成功回 CLOSED / 失败回 OPEN。
2. **Hystrix 熔断和 Sentinel 熔断有什么区别?**
- 解答要点:Hystrix 用滑动时间窗口的孤立线程池隔离,Sentinel 用信号量隔离(无线程切换开销);Hystrix 已停止维护,Sentinel 是当前主流;Sentinel 支持热点参数限流、系统自适应保护等。
3. **什么时候用限流而不是熔断?**
- 解答要点:本服务流量过载用限流(入口保护);下游服务不稳定用熔断(依赖保护);两者互补。典型组合:网关限流 + 服务熔断 + 熔断后降级。
4. **生产环境如何确定限流阈值和熔断阈值?**
- 解答要点:压测(JMeter/AB)确定单机 QPS 上限,取 80% 作为限流阈值;熔断阈值参考 P95 错误率,一般 50% 持续 10s 触发;恢复期一般 10-30s;Sentinel 自适应规则可动态调整。
面试官您好,限流、降级、熔断不是三个阶段,而是三种不同的防护策略,作用点不同。
**限流(Rate Limiting)**:控制入口流量,防止系统被打爆。作用于**本服务**。算法有计数器、漏桶、令牌桶、滑动窗口;实现上单机用 Guava RateLimiter,集群用 Redis + Lua 或 Sentinel 集群限流。典型场景:秒杀接口防刷、登录接口防暴力破解。
**熔断(Circuit Breaking)**:保护下游依赖,防止下游不稳定拖垮调用方。作用于**下游服务**。核心是三态机:
- CLOSED:正常放行,统计错误率
- OPEN:错误率超阈值(如 10s 内>50%),快速失败,不再调用
- HALF-OPEN:等恢复期(如 10s)后放少量请求探测,成功回 CLOSED / 失败回 OPEN
**降级(Fallback/Degrade)**:兜底策略,让系统异常下仍可用。作用于**本服务对外接口**。类型有:
- 服务降级:返回兜底值/错误提示(我做过三方接口挂了降级为随机推荐位)
- 功能降级:隐藏非核心功能(推荐位挂了、评论区挂了)
- 数据降级:返回缓存旧数据(库存查询挂了返回上次缓存)
- 排队降级:同步转异步,进入队列稍后处理
- 消息降级:同步转异步
**三者关系**:限流是入口守门员,熔断是下游保险丝,降级是兜底策略。典型组合是**网关限流 + 服务熔断 + 熔断后降级**,形成三层保护。
**主流工具**:
- Hystrix:Netflix 经典,已停止维护,概念最清晰
- Sentinel:阿里,功能最全,支持热点参数限流、自适应保护、熔断规则多样
- Resilience4j:Java 8+ 模块化方案
生产上阈值一般:限流阈值 = 压测 80%,熔断阈值 = 50% 错误率持续 10s,恢复期 = 10-30s,探测成功连续 N 次后回 CLOSED。
**核心考点定位**:考察对高性能分布式系统的完整方法论,包括"量化目标→架构设计→各层优化→治理运维"的系统性思考。
**知识点拆解**:
1. **量化先行**(80% 的回答都缺这步):
- **QPS/TPS**:目标 10 万 QPS
- **P99 延迟**:目标 <100ms
- **可用性**:99.99%(允许 4.3 分钟/年不可用)
- **错误率**:<0.1%
- 有了目标才能推导架构和选型
2. **网络接入层**:
- **CDN**:静态资源全球加速
- **DDoS 防护**:Cloudflare、高防 IP
- **网关**:Nginx/APISIX/Spring Cloud Gateway(限流、鉴权、路由)
3. **负载均衡层**:
- L4(LVS)+ L7(Nginx)+ 客户端 LB(Ribbon/LoadBalancer)
- 一致性哈希、会话保持
4. **缓存层**:
- 多级缓存:本地(Caffeine)→ 分布式(Redis Cluster)→ 数据库
- 缓存穿透/击穿/雪崩防护(布隆过滤器、互斥锁、随机过期时间)
5. **数据层**:
- 读写分离、分库分表、CQRS
- 连接池(HikariCP)、慢查询监控、批量操作
- 冷热数据分离(ES/HBase 存冷数据)
6. **异步与削峰**:
- MQ(Kafka/RocketMQ)吸收流量峰值
- 事件驱动、最终一致性
7. **协议与序列化**:
- HTTP/2 多路复用、gRPC、Protobuf
- TCP 长连接、HTTP keep-alive
- gzip/zstd 压缩
8. **线程模型**:
- Netty Reactor(Boss + Worker)
- 虚拟线程(JDK21)应对高并发 IO
- 线程池隔离(避免共享池打满)
9. **可观测性**:
- 三大支柱:Metrics(Prometheus)、Tracing(SkyWalking/Jaeger)、Logging(ELK)
- 容量规划:压测、水位告警
10. **韧性设计**:
- 限流/熔断/降级、超时/重试/幂等
- 优雅启停、灰度发布
> 递进:从"量化目标"→ "架构分层"→ "各层优化手段"→ "可观测性"→ "韧性设计",是完整的系统思考。
**考察方向**:
- **深度**:多级缓存的一致性、读写分离的延迟、CQRS 的最终一致
- **广度**:与新基础设施(Service Mesh、Serverless、eBPF)的关系
- **应用**:真实业务(秒杀/直播/支付)如何设计、如何做容量规划
**延伸递进面试题**:
1. **你说 P99 目标 100ms,如何验证?**
- 解答要点:压测工具(JMeter/AB),指标采集(SkyWalking APM),看 P50/P95/P99 分布;容量规划(单机 QPS * 80% * 机器数 = 系统 QPS)。
2. **多级缓存如何保证一致性?**
- 解答要点:Cache-Aside 模式(先查缓存,未命中查库并回写);更新时"先更库再删缓存";延迟双删;Redis 发布订阅通知本地缓存失效。
3. **数据库是瓶颈时怎么办?**
- 解答要点:先看慢查询(SHOW SLOW QUERIES)、加索引、读写分离、分库分表、热点数据缓存、离线任务(ETL 到 ES/HBase)、异步写入(先写 MQ 再异步落库)。
4. **虚拟线程能解决所有高并发问题吗?**
- 解答要点:虚拟线程对 IO 密集型有效,CPU 密集型无效(还是受限于 CPU 核数);需要 JDK21+;对 synchronized 有 pinning 问题,建议用 ReentrantLock。
面试官您好,设计一个高性能分布式系统,我会从"量化目标 → 架构分层 → 各层优化 → 治理运维"四个维度来做。
**第一步,量化目标**:先和 PM 对齐 SLA。比如 QPS 10 万、P99 延迟 100ms、可用性 99.99%、错误率 <0.1%。有了目标才能推导架构和选型。
**第二步,架构分层**(自上而下):
1. **接入层**:CDN(静态加速)+ DDoS 防护 + 网关(限流/鉴权/路由)
2. **负载均衡层**:L4(LVS)+ L7(Nginx)+ 客户端 LB,用一致性哈希
3. **业务层**:无状态微服务,水平扩展
4. **缓存层**:多级缓存(Caffeine 本地 + Redis 分布式)
5. **数据层**:MySQL 分库分表 + ES(搜索)+ HBase(冷数据)
6. **异步层**:Kafka/RocketMQ 削峰、事件驱动
**第三步,各层优化**:
- **网络**:HTTP/2 多路复用、TCP 长连接、keep-alive、HTTP 压缩(zstd)
- **序列化**:Protobuf 替代 JSON,体积小 3-10 倍
- **缓存**:多级缓存(先本地后分布式后数据库),缓存穿透用布隆过滤器,击穿用互斥锁,雪崩用随机 TTL
- **数据库**:HikariCP 连接池调优、索引优化、慢查询监控、批量写入、读写分离
- **异步**:耗时操作进 MQ,事件驱动,最终一致性
- **线程模型**:Netty Reactor、虚拟线程(JDK21)应对 IO 密集
**第四步,韧性 + 可观测性**:
- 韧性:限流(Sentinel 令牌桶)+ 熔断(Hystrix/Sentinel)+ 降级(兜底值)+ 超时/重试/幂等
- 可观测:Prometheus 指标、SkyWalking 链路、ELK 日志
**举例**:秒杀场景。用户下单峰值 10 万 QPS,通过 CDN + Nginx 限流 → 网关做黑名单过滤 → Kafka 削峰 → 后端按 1000 QPS 消费落库 → Redis 库存预扣(Lua 原子操作)→ 订单 MQ 异步持久化。P99 延迟 <200ms。
**核心考点定位**:考察对主流注册中心的深入对比、CAP 权衡的业务理解,以及结合团队实际的技术决策能力。
**知识点拆解**:
1. **CAP 本质**:分布式系统无法同时满足一致性(C)、可用性(A)、分区容错(P)。网络分区不可避免(P 必选),所以只能在 C 和 A 之间选。
2. **主流注册中心对比**:
- **Eureka**:Netflix 出品,纯 AP,客户端推送 + 自我保护机制(30 秒内 15% 掉线不摘除),Spring Cloud 早期主力,2018 年后停止维护。
- **Zookeeper**:CP,ZAB 协议,Leader 挂掉会阻塞,不适合大量服务注册场景,但在 Dubbo 老生态中广泛使用。
- **Nacos**:阿里出品,AP/CP 双模式,临时实例走 Distro(AP)+ 永久实例走 Raft(CP),自带配置中心,Spring Cloud Alibaba 主力。
- **Consul**:HashiCorp 出品,AP/CP 双模式(Session 是 AP,KV 是 CP),支持健康检查、多数据中心、Serf 协议,多云场景常用。
- **Etcd**:K8s 底层组件,CP 强一致,一般不做业务注册中心。
3. **业务场景选型**:
- **微服务无状态服务**(用户/订单/支付)→ AP,选 Nacos/Eureka
- **数据库主从切换** → CP,选 Zookeeper/Consul
- **微服务全家桶**(注册+配置) → Nacos
- **多云、K8s 混合** → Consul
4. **集群部署**:
- Eureka:3 节点,自我保护机制
- Zookeeper:3/5 节点(奇数),ZAB 选主
- Nacos:3 节点(Raft 需要多数派)
- Consul:3/5 节点
5. **一致性 vs 可用性的取舍**:
- 微服务场景一般 AP 优先:注册中心挂了服务还能用最后一次缓存,短暂延迟发现变化可以接受
- 只有强一致需求(如分布式锁、数据库主从)才用 CP
> 递进:从"CAP 本质"→ "主流产品对比"→ "业务场景选型"→ "集群部署考虑"。
**考察方向**:
- **深度**:Eureka 自我保护机制、Zookeeper 的 Watch、Nacos 的 Distro/Raft 双协议
- **广度**:与 Service Mesh(Istio 用 Envoy + 控制面)的关系
- **应用**:如何在生产做注册中心的高可用、灰度、灾备
**延伸递进面试题**:
1. **Eureka 的自我保护机制是什么?什么时候会触发?**
- 解答要点:30 秒内,如果注册到某个 Eureka Server 的实例掉线比例超过 15%,触发自我保护,暂停剔除实例,防止网络分区导致服务被误摘除。
2. **为什么 Zookeeper 不适合做微服务注册中心?**
- 解答要点:ZK 是 CP,Leader 挂掉要选主(可能几十秒阻塞);写操作需要 2/3 节点确认,性能有限;微服务高频上下线不适合强一致。
3. **Nacos 集群挂了服务还能通信吗?**
- 解答要点:能,客户端本地有缓存,服务列表最近一次快照能读;已建立连接不受影响;但新的实例变化感知不到,健康状态不更新。
4. **生产环境 Nacos 如何做高可用?**
- 解答要点:至少 3 节点,客户端配多地址;外置 MySQL 存元数据;监听端口 8848(HTTP)+ 9848/9849(gRPC);定期备份 MySQL。
面试官您好,注册中心选型我从"CAP 本质 → 主流产品对比 → 业务场景 → 集群部署"四步来做。
**第一步,CAP 权衡**:分布式系统 P 必选(网络分区不可避免),只能在 C(一致性)和 A(可用性)之间选。微服务场景一般 AP 优先——注册中心短暂不可用时,客户端本地缓存仍能支撑服务通信。
**第二步,主流产品对比**:
- **Eureka**:AP,客户端推送 + 自我保护机制(30s 内 15% 掉线不摘除),Netflix 出品,2018 年后停止维护。
- **Zookeeper**:CP,ZAB 协议,Leader 挂掉要选主,性能一般,老 Dubbo 生态常用,不太适合微服务高频上下线。
- **Nacos**:AP/CP 双模式,临时实例走 Distro(AP)+ 永久实例走 Raft(CP),自带配置中心,Spring Cloud Alibaba 主力。
- **Consul**:HashiCorp 出品,AP/CP 双模式,支持健康检查、多数据中心,多云场景常用。
**第三步,业务场景选型**:
- 微服务无状态服务 → AP(Nacos/Eureka)
- 数据库主从切换/分布式锁 → CP(Zookeeper/Consul)
- 微服务全家桶(注册 + 配置) → Nacos
- 多云、K8s 混合 → Consul
**第四步,集群部署**:
- Eureka 3 节点,注意自我保护
- Zookeeper 3/5 节点(奇数)
- Nacos 3 节点,客户端配多地址,外置 MySQL,端口 8848 + gRPC 9848/9849
- Consul 3/5 节点,Raft 需多数派
**我们的选择**:生产用 **Nacos**,理由:
1. AP/CP 双模式满足绝大部分场景;
2. 注册 + 配置二合一,减少组件数量;
3. Spring Cloud Alibaba 生态成熟,文档齐全;
4. 阿里系业务背景,稳定性经过验证;
5. 2.x gRPC 长连接,性能比 1.x 提升 10 倍。
Eureka 已停止维护不再考虑;Zookeeper 只在分布式锁、数据库主从这类 CP 场景才用;Consul 在多云或 K8s 混合场景值得引入。