[{"data":1,"prerenderedAt":294},["ShallowReactive",2],{"\u002Fjava-interview\u002Fmicroservices":3,"java-interview-search:\u002Fjava-interview\u002Fmicroservices":249},{"id":4,"title":5,"body":6,"category":235,"cover":236,"date":237,"description":238,"extension":239,"group":240,"meta":241,"navigation":242,"order":243,"path":244,"seo":245,"sitemap":246,"stem":247,"__hash__":248},"javaInterview\u002Fjava-interview\u002Fmicroservices.md","微服务：拆分、通信与稳定性治理",{"type":7,"value":8,"toc":221},"minimark",[9,13,18,21,24,27,30,34,37,40,43,46,50,53,56,59,62,66,69,72,75,95,99,102,105,108,111,115,118,121,124,127,131,134,137,144,147,151,154,157,160,163,166,179,182,185],[10,11,12],"p",{},"微服务题的重点不是组件清单，而是「拆不拆、怎么通、出错怎么办」。下面按这三个问题展开，组件只作为实现手段出现。",[14,15,17],"h2",{"id":16},"_1-微服务应该怎么拆什么时候不该拆","1. 微服务应该怎么拆？什么时候不该拆？",[10,19,20],{},"常见依据是业务能力与限界上下文：一个服务应拥有相对完整的一块业务和它的数据，能独立部署、独立演进。也可以按组织结构和变更频率拆，让经常一起改的代码待在一起。",[10,22,23],{},"判断边界时问三个问题：这块能力是否有独立的生命周期？是否有清晰的数据所有权？跨边界的调用是否足够少？如果一个变更总要同时改五个服务，说明边界切错了。",[10,25,26],{},"不该拆的情况同样重要：团队规模小、领域还没稳定、强事务要求高、流量很低。此时模块化单体往往更划算，等边界清晰后再拆，比一开始拆错再合并容易。",[10,28,29],{},"还要警惕「按技术分层拆」：用户服务、订单服务之外再拆出「查询服务」「写入服务」，会把一次业务变更拉成跨团队协作，收益通常抵不过成本。",[14,31,33],{"id":32},"_2-spring-cloud-常见组件分别解决什么问题","2. Spring Cloud 常见组件分别解决什么问题？",[10,35,36],{},"网关负责统一入口、路由、鉴权、限流和灰度；注册中心负责服务实例的注册与发现，常见有 Nacos、Consul、Eureka；客户端负载均衡负责在实例列表中选择目标，Spring Cloud LoadBalancer 已替代 Ribbon。",[10,38,39],{},"声明式调用用 OpenFeign，把 HTTP 调用封装成接口；容错限流可以用 Sentinel 或 Resilience4j；配置中心负责动态配置；链路追踪在 Spring Boot 3 时代通常用 Micrometer Tracing 对接 OpenTelemetry。",[10,41,42],{},"要注意版本配套：Spring Boot 3 \u002F Spring Cloud 2022+ 使用 Jakarta 命名空间，旧版 Sleuth 已不再是主线。选组件时优先看团队是否真的会用，而不是把全家桶一次性引入。",[10,44,45],{},"组件越多，故障面越大。一个只有三个服务的小系统，可能只需要网关、注册中心和基础监控。",[14,47,49],{"id":48},"_3-服务注册发现和负载均衡是怎么工作的","3. 服务注册发现和负载均衡是怎么工作的？",[10,51,52],{},"服务启动时把地址、端口、元数据注册到注册中心，并定期发送心跳；消费者拉取或订阅实例列表，缓存在本地，调用时按负载均衡策略选一个实例。",[10,54,55],{},"注册中心通常区分临时实例和持久实例：临时实例靠心跳续约，失联后被剔除；持久实例需要显式注销。健康检查有客户端心跳和服务端探测两种方式。",[10,57,58],{},"选型会涉及 CAP：Eureka 偏向可用性，允许短时间读到旧列表；ZooKeeper 偏向一致性，网络分区时可能拒绝写；Nacos 默认偏 AP，也提供 CP 模式。",[10,60,61],{},"客户端负载均衡不需要额外的代理进程，但每个消费者都要维护实例列表和健康判断。服务端负载均衡（如 Nginx、云负载均衡）把选择集中在一处，运维简单但多一跳。",[14,63,65],{"id":64},"_4-dubbo-和-openfeign-有什么区别spi-有什么不同","4. Dubbo 和 OpenFeign 有什么区别？SPI 有什么不同？",[10,67,68],{},"OpenFeign 基于 HTTP，语义通用、调试方便、跨语言友好，适合对外接口和异构系统；代价是文本协议和每次调用的连接、序列化开销相对高。",[10,70,71],{},"Dubbo 是 RPC 框架，默认走二进制协议和 TCP 长连接，性能通常更好，提供服务治理能力（超时、重试、路由、负载均衡、熔断）。它更适合内部高频调用，但要求双方使用兼容的协议和序列化方式。",[10,73,74],{},"Dubbo 3 支持 Triple 协议，兼容 gRPC 和 HTTP\u002F2，跨语言能力比早期版本好很多。选型不能只看性能，还要看团队对协议、序列化和治理的掌握程度。",[10,76,77,78,82,83,86,87,90,91,94],{},"SPI 方面，JDK SPI 通过 ",[79,80,81],"code",{},"META-INF\u002Fservices"," 加载，一次性实例化所有实现，无法按需选择；Dubbo SPI 用 ",[79,84,85],{},"@SPI"," 指定默认实现，",[79,88,89],{},"@Adaptive"," 做自适应扩展，",[79,92,93],{},"@Activate"," 做条件激活，支持按名称获取和包装扩展，灵活得多。",[14,96,98],{"id":97},"_5-超时重试熔断限流应该怎么配","5. 超时、重试、熔断、限流应该怎么配？",[10,100,101],{},"超时应该自下而上设置：下游超时小于上游，并留出处理余量。更好的做法是传递截止时间（deadline），让整条调用链共享同一个预算，而不是每层各自设一个固定值。",[10,103,104],{},"重试只对幂等操作开启，并且要限制次数、加退避和抖动。同步调用链上层层重试会造成放大效应，三层各重试两次就是八倍流量，容易把已经过载的下游彻底压垮。",[10,106,107],{},"熔断器有闭合、打开、半开三个状态：失败率超阈值后打开，快速失败；经过冷却期进入半开，放少量请求试探。它保护的是调用方，也给了下游恢复时间。",[10,109,110],{},"限流常用令牌桶（允许突发）和漏桶（平滑输出），还要考虑单机限流与集群限流的差别。降级方案要提前设计好返回值，不能等故障时临时决定。",[14,112,114],{"id":113},"_6-分布式事务有哪些方案seata-at-的边界在哪","6. 分布式事务有哪些方案？Seata AT 的边界在哪？",[10,116,117],{},"强一致方案主要是 2PC\u002FXA：协调者统一提交或回滚，实现简单但有同步阻塞、协调者单点和性能问题。3PC 缓解阻塞，仍不能很好应对网络分区。",[10,119,120],{},"柔性事务包括 TCC、Saga、本地消息表和可靠消息。TCC 需要业务实现 Try\u002FConfirm\u002FCancel，要处理空回滚、悬挂和幂等；Saga 用一系列本地事务加补偿，隔离性弱，适合长流程；本地消息表靠最终一致，工程上最常用。",[10,122,123],{},"Seata AT 通过解析 SQL 生成前后镜像，提交本地事务并记录 undo log，失败时反向补偿。它默认不提供强隔离，读到中间状态需要配合全局锁或业务设计；复杂 SQL、存储过程、非事务表都可能失效。",[10,125,126],{},"选择方案的顺序应该是：能不能不分布式事务（合并服务、调整边界）→ 能否最终一致 → 最后才考虑强一致方案。",[14,128,130],{"id":129},"_7-微服务可观测性要建设哪些能力","7. 微服务可观测性要建设哪些能力？",[10,132,133],{},"三根支柱是日志、指标和链路追踪。日志要结构化，并带上 traceId、用户标识和业务单号；指标关注流量、错误率、延迟和饱和度；链路追踪要能串起跨服务调用，定位是哪一跳变慢。",[10,135,136],{},"指标命名可以套用 RED（请求速率、错误、耗时）和 USE（使用率、饱和度、错误）；告警要基于症状（用户可感知的错误率和延迟），而不是只看 CPU。",[10,138,139,140,143],{},"OpenTelemetry 正在成为事实标准，trace context 通过 W3C ",[79,141,142],{},"traceparent"," 头传递。采样策略要平衡成本与可观测性，错误请求和慢请求应提高采样率。",[10,145,146],{},"可观测性不是装个 APM 就结束：要有统一的检索入口、清晰的仪表盘和可执行的 Runbook，否则故障时仍然靠猜。",[14,148,150],{"id":149},"_8-网关层要做哪些事鉴权怎么设计","8. 网关层要做哪些事？鉴权怎么设计？",[10,152,153],{},"网关适合做与业务无关的横切能力：路由转发、TLS 终止、统一鉴权、限流熔断、跨域、请求日志、灰度分流和协议转换。它不适合承载业务逻辑，否则会成为新的单体。",[10,155,156],{},"鉴权可以在网关做粗粒度的身份校验（验签、解析 token、拦截未登录请求），细粒度的权限判断仍应放在服务内，因为服务需要知道「这个用户能否操作这个资源」。",[10,158,159],{},"JWT 自带声明、便于水平扩展，但撤销困难；常见做法是短有效期加刷新令牌，敏感操作再查一次权限或黑名单。传统 Session 依赖集中存储，撤销容易但需要共享会话。",[10,161,162],{},"内部服务之间建议使用 mTLS 或服务身份令牌，不要默认「内网可信」。网关还要防止把外部请求头原样透传，避免伪造身份字段。",[14,164,165],{"id":165},"易错点与自测",[167,168,169,173,176],"ul",{},[170,171,172],"li",{},"拆分不是越细越好，数据所有权和变更边界比「服务数量」更重要。",[170,174,175],{},"重试是放大器，没有幂等和退避的重试是故障加速器。",[170,177,178],{},"分布式事务没有银弹，先问业务能否接受最终一致。",[10,180,181],{},"自测：① 说明客户端负载均衡与服务端负载均衡的差异；② 画出熔断器的三个状态及迁移条件；③ 解释 Seata AT 为什么默认不是强隔离。",[14,183,184],{"id":184},"参考资料",[167,186,187,197,205,213],{},[170,188,189,196],{},[190,191,195],"a",{"href":192,"rel":193},"https:\u002F\u002Fspring.io\u002Fprojects\u002Fspring-cloud",[194],"nofollow","Spring Cloud 官方文档"," — 各组件与版本对应关系",[170,198,199,204],{},[190,200,203],{"href":201,"rel":202},"https:\u002F\u002Fdubbo.apache.org\u002Fen\u002Foverview\u002F",[194],"Apache Dubbo 官方文档"," — 协议、SPI 与服务治理",[170,206,207,212],{},[190,208,211],{"href":209,"rel":210},"https:\u002F\u002Fseata.apache.org\u002Fdocs\u002Foverview\u002Fwhat-is-seata\u002F",[194],"Seata 官方文档"," — AT、TCC、Saga 的模式与约束",[170,214,215,220],{},[190,216,219],{"href":217,"rel":218},"https:\u002F\u002Fopentelemetry.io\u002Fdocs\u002F",[194],"OpenTelemetry 文档"," — 链路、指标与日志的统一采集",{"title":222,"searchDepth":223,"depth":223,"links":224},"",2,[225,226,227,228,229,230,231,232,233,234],{"id":16,"depth":223,"text":17},{"id":32,"depth":223,"text":33},{"id":48,"depth":223,"text":49},{"id":64,"depth":223,"text":65},{"id":97,"depth":223,"text":98},{"id":113,"depth":223,"text":114},{"id":129,"depth":223,"text":130},{"id":149,"depth":223,"text":150},{"id":165,"depth":223,"text":165},{"id":184,"depth":223,"text":184},"java-interview",null,"2026-10-24","从服务边界、Spring Cloud 组件到 Dubbo、超时重试与分布式事务，梳理微服务面试的主线与常见误区","md","分布式与工程",{},true,"110","\u002Fjava-interview\u002Fmicroservices",{"title":5,"description":238},{"loc":244},"java-interview\u002Fmicroservices","aRBlrkBh77MOx-xHJaG2vYyVVzsaJVAgpGyBGmW23ew",[250,254,258,262,266,270,274,278,282,286,290],{"id":244,"title":5,"titles":251,"content":252,"level":253},[],"从服务边界、Spring Cloud 组件到 Dubbo、超时重试与分布式事务，梳理微服务面试的主线与常见误区 微服务题的重点不是组件清单，而是「拆不拆、怎么通、出错怎么办」。下面按这三个问题展开，组件只作为实现手段出现。",1,{"id":255,"title":17,"titles":256,"content":257,"level":223},"\u002Fjava-interview\u002Fmicroservices#_1-微服务应该怎么拆什么时候不该拆",[5],"常见依据是业务能力与限界上下文：一个服务应拥有相对完整的一块业务和它的数据，能独立部署、独立演进。也可以按组织结构和变更频率拆，让经常一起改的代码待在一起。 判断边界时问三个问题：这块能力是否有独立的生命周期？是否有清晰的数据所有权？跨边界的调用是否足够少？如果一个变更总要同时改五个服务，说明边界切错了。 不该拆的情况同样重要：团队规模小、领域还没稳定、强事务要求高、流量很低。此时模块化单体往往更划算，等边界清晰后再拆，比一开始拆错再合并容易。 还要警惕「按技术分层拆」：用户服务、订单服务之外再拆出「查询服务」「写入服务」，会把一次业务变更拉成跨团队协作，收益通常抵不过成本。",{"id":259,"title":33,"titles":260,"content":261,"level":223},"\u002Fjava-interview\u002Fmicroservices#_2-spring-cloud-常见组件分别解决什么问题",[5],"网关负责统一入口、路由、鉴权、限流和灰度；注册中心负责服务实例的注册与发现，常见有 Nacos、Consul、Eureka；客户端负载均衡负责在实例列表中选择目标，Spring Cloud LoadBalancer 已替代 Ribbon。 声明式调用用 OpenFeign，把 HTTP 调用封装成接口；容错限流可以用 Sentinel 或 Resilience4j；配置中心负责动态配置；链路追踪在 Spring Boot 3 时代通常用 Micrometer Tracing 对接 OpenTelemetry。 要注意版本配套：Spring Boot 3 \u002F Spring Cloud 2022+ 使用 Jakarta 命名空间，旧版 Sleuth 已不再是主线。选组件时优先看团队是否真的会用，而不是把全家桶一次性引入。 组件越多，故障面越大。一个只有三个服务的小系统，可能只需要网关、注册中心和基础监控。",{"id":263,"title":49,"titles":264,"content":265,"level":223},"\u002Fjava-interview\u002Fmicroservices#_3-服务注册发现和负载均衡是怎么工作的",[5],"服务启动时把地址、端口、元数据注册到注册中心，并定期发送心跳；消费者拉取或订阅实例列表，缓存在本地，调用时按负载均衡策略选一个实例。 注册中心通常区分临时实例和持久实例：临时实例靠心跳续约，失联后被剔除；持久实例需要显式注销。健康检查有客户端心跳和服务端探测两种方式。 选型会涉及 CAP：Eureka 偏向可用性，允许短时间读到旧列表；ZooKeeper 偏向一致性，网络分区时可能拒绝写；Nacos 默认偏 AP，也提供 CP 模式。 客户端负载均衡不需要额外的代理进程，但每个消费者都要维护实例列表和健康判断。服务端负载均衡（如 Nginx、云负载均衡）把选择集中在一处，运维简单但多一跳。",{"id":267,"title":65,"titles":268,"content":269,"level":223},"\u002Fjava-interview\u002Fmicroservices#_4-dubbo-和-openfeign-有什么区别spi-有什么不同",[5],"OpenFeign 基于 HTTP，语义通用、调试方便、跨语言友好，适合对外接口和异构系统；代价是文本协议和每次调用的连接、序列化开销相对高。 Dubbo 是 RPC 框架，默认走二进制协议和 TCP 长连接，性能通常更好，提供服务治理能力（超时、重试、路由、负载均衡、熔断）。它更适合内部高频调用，但要求双方使用兼容的协议和序列化方式。 Dubbo 3 支持 Triple 协议，兼容 gRPC 和 HTTP\u002F2，跨语言能力比早期版本好很多。选型不能只看性能，还要看团队对协议、序列化和治理的掌握程度。 SPI 方面，JDK SPI 通过 META-INF\u002Fservices 加载，一次性实例化所有实现，无法按需选择；Dubbo SPI 用 @SPI 指定默认实现，@Adaptive 做自适应扩展，@Activate 做条件激活，支持按名称获取和包装扩展，灵活得多。",{"id":271,"title":98,"titles":272,"content":273,"level":223},"\u002Fjava-interview\u002Fmicroservices#_5-超时重试熔断限流应该怎么配",[5],"超时应该自下而上设置：下游超时小于上游，并留出处理余量。更好的做法是传递截止时间（deadline），让整条调用链共享同一个预算，而不是每层各自设一个固定值。 重试只对幂等操作开启，并且要限制次数、加退避和抖动。同步调用链上层层重试会造成放大效应，三层各重试两次就是八倍流量，容易把已经过载的下游彻底压垮。 熔断器有闭合、打开、半开三个状态：失败率超阈值后打开，快速失败；经过冷却期进入半开，放少量请求试探。它保护的是调用方，也给了下游恢复时间。 限流常用令牌桶（允许突发）和漏桶（平滑输出），还要考虑单机限流与集群限流的差别。降级方案要提前设计好返回值，不能等故障时临时决定。",{"id":275,"title":114,"titles":276,"content":277,"level":223},"\u002Fjava-interview\u002Fmicroservices#_6-分布式事务有哪些方案seata-at-的边界在哪",[5],"强一致方案主要是 2PC\u002FXA：协调者统一提交或回滚，实现简单但有同步阻塞、协调者单点和性能问题。3PC 缓解阻塞，仍不能很好应对网络分区。 柔性事务包括 TCC、Saga、本地消息表和可靠消息。TCC 需要业务实现 Try\u002FConfirm\u002FCancel，要处理空回滚、悬挂和幂等；Saga 用一系列本地事务加补偿，隔离性弱，适合长流程；本地消息表靠最终一致，工程上最常用。 Seata AT 通过解析 SQL 生成前后镜像，提交本地事务并记录 undo log，失败时反向补偿。它默认不提供强隔离，读到中间状态需要配合全局锁或业务设计；复杂 SQL、存储过程、非事务表都可能失效。 选择方案的顺序应该是：能不能不分布式事务（合并服务、调整边界）→ 能否最终一致 → 最后才考虑强一致方案。",{"id":279,"title":130,"titles":280,"content":281,"level":223},"\u002Fjava-interview\u002Fmicroservices#_7-微服务可观测性要建设哪些能力",[5],"三根支柱是日志、指标和链路追踪。日志要结构化，并带上 traceId、用户标识和业务单号；指标关注流量、错误率、延迟和饱和度；链路追踪要能串起跨服务调用，定位是哪一跳变慢。 指标命名可以套用 RED（请求速率、错误、耗时）和 USE（使用率、饱和度、错误）；告警要基于症状（用户可感知的错误率和延迟），而不是只看 CPU。 OpenTelemetry 正在成为事实标准，trace context 通过 W3C traceparent 头传递。采样策略要平衡成本与可观测性，错误请求和慢请求应提高采样率。 可观测性不是装个 APM 就结束：要有统一的检索入口、清晰的仪表盘和可执行的 Runbook，否则故障时仍然靠猜。",{"id":283,"title":150,"titles":284,"content":285,"level":223},"\u002Fjava-interview\u002Fmicroservices#_8-网关层要做哪些事鉴权怎么设计",[5],"网关适合做与业务无关的横切能力：路由转发、TLS 终止、统一鉴权、限流熔断、跨域、请求日志、灰度分流和协议转换。它不适合承载业务逻辑，否则会成为新的单体。 鉴权可以在网关做粗粒度的身份校验（验签、解析 token、拦截未登录请求），细粒度的权限判断仍应放在服务内，因为服务需要知道「这个用户能否操作这个资源」。 JWT 自带声明、便于水平扩展，但撤销困难；常见做法是短有效期加刷新令牌，敏感操作再查一次权限或黑名单。传统 Session 依赖集中存储，撤销容易但需要共享会话。 内部服务之间建议使用 mTLS 或服务身份令牌，不要默认「内网可信」。网关还要防止把外部请求头原样透传，避免伪造身份字段。",{"id":287,"title":165,"titles":288,"content":289,"level":223},"\u002Fjava-interview\u002Fmicroservices#易错点与自测",[5],"拆分不是越细越好，数据所有权和变更边界比「服务数量」更重要。 重试是放大器，没有幂等和退避的重试是故障加速器。 分布式事务没有银弹，先问业务能否接受最终一致。 自测：① 说明客户端负载均衡与服务端负载均衡的差异；② 画出熔断器的三个状态及迁移条件；③ 解释 Seata AT 为什么默认不是强隔离。",{"id":291,"title":184,"titles":292,"content":293,"level":223},"\u002Fjava-interview\u002Fmicroservices#参考资料",[5],"Spring Cloud 官方文档 — 各组件与版本对应关系 Apache Dubbo 官方文档 — 协议、SPI 与服务治理 Seata 官方文档 — AT、TCC、Saga 的模式与约束 OpenTelemetry 文档 — 链路、指标与日志的统一采集",1793263559811]