SpringCloud 面试
SpringCloud 面试
综合
【中等】Spring Cloud 有哪些核心组件?
Spring Cloud 的核心组件主要包括以下几个:
- 服务注册与发现:Eureka、Consul、Nacos
- 负载均衡:Ribbon(停更)、Spring Cloud LoadBalancer
- 配置中心:Spring Cloud Config、Apollo、Nacos
- 服务调用:Feign(停更)、OpenFeign(声明式 HTTP 客户端)
- 熔断与限流:Hystrix(停更)、Resilience4j、Sentinel
- 网关:Zuul(停更)、Spring Cloud Gateway
- 消息驱动:Spring Cloud Stream(整合 Kafka、RabbitMQ 等)
- 链路追踪:Spring Cloud Sleuth(整合 Zipkin、Jaeger)
- 监控与管理:Spring Boot Admin、Spring Cloud Bus
总结来看,Spring Cloud 的核心组件就是围绕:服务治理、配置管理、流量控制、链路追踪、网关、消息驱动、监控 这几大类来解决微服务的一些问题的。
注意,Spring Cloud 很多组件其实都停更了,现在公司用 Spring Cloud Alibaba 的会多一些:Nacos(注册 + 配置)+ Sentinel(熔断限流)+ Gateway(网关)+ OpenFeign(调用)。
一个真实的调用链大概如下:
- 用户请求进来,先过 Spring Cloud Gateway 网关,网关查路由、做认证,还用 Sentinel 限流熔断,防流量高峰。
- 网关从 Nacos/Eureka 查服务地址,用 LoadBalancer 挑一个均衡的实例。
- 服务间调用用 OpenFeign,写接口像本地调用,底层带重试。
- 配置从 Nacos Config 拉,变化时 Spring Cloud Bus 广播刷新所有实例。
- 如果下游服务慢或挂,Resilience4j/Sentinel 熔断,返回默认结果。
- 非实时任务丢到 Spring Cloud Stream(用 Kafka),异步处理解耦。
- 全链路用 Sleuth + Zipkin/Jaeger,问题时看日志链。
- Spring Boot Admin 监控集群健康,指标报警。
【中等】Spring Cloud 的优缺点有哪些?
优点
- 生态完整:提供微服务全栈组件,开箱即用。
- 开发高效:基于 Spring Boot 自动配置,集成简单。
- 社区强大:文档丰富,问题易排查。
- 技术统一:与 Spring 生态无缝融合,学习成本低。
- 组件灵活:支持替换 Netflix 套件(如 Nacos、Resilience4j)。
缺点
- 技术栈锁定:深度绑定 Java/Spring,不适合多语言异构系统。
- 版本兼容复杂:Spring Boot 与 Cloud 版本需严格匹配,升级风险高。
- 运维成本高:微服务组件需独立部署维护,分布式复杂性未降低。
- 性能开销:组件间调用、代理等引入额外延迟和资源消耗。
- 排障难度大:自动配置和动态代理隐藏细节,问题定位需深入底层。
- 组件维护状态:部分组件(如 Hystrix、Zuul 1.x)已停止更新,迁移需改造。
【中等】Spring Boot 和 Spring Cloud 之间的区别?
- Spring Boot:快速构建单个微服务的开发框架,专注于简化配置、快速启动。
- Spring Cloud:协调和管理微服务集群的治理套件,专注于分布式系统的通信与协调。
- Spring Cloud 依赖 Spring Boot 运行,但 Spring Boot 可独立使用。
分布式协同
【简单】什么是 Seata?
Seata 是开源的分布式事务解决方案,致力于为微服务架构提供高性能、易用的一站式分布式事务服务。
它通过引入事务协调者(TC)、**事务管理器(TM)和资源管理器(RM)**这三个核心组件来管理全局事务。
其核心价值在于将对分布式事务的处理从业务代码中抽象出来,让开发者能像使用本地事务一样处理跨服务的数据一致性问题。
Seata 提供了四种核心的事务模式,以满足不同业务场景的需求。
| 模式 | 核心原理 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| AT 模式 | 通过解析业务 SQL,自动生成回滚快照(before/after image),记录在undo_log表中,实现二阶段补偿。基于改进后的两阶段提交协议(2PC)。 | 对业务代码无侵入,学习成本低,性能较高。 | 需要数据库额外建立undo_log表,存在短暂的数据不一致窗口(AP 模型)。 | 适用于绝大多数高并发的互联网场景,允许最终一致性。 |
| TCC 模式 | 要求业务系统自行实现三个方法:Try(预留/检查资源)、Confirm(确认提交)、Cancel(补偿回滚)。 | 性能比 AT 模式更高(无全局锁),可灵活控制业务资源。 | 对业务代码侵入性强,开发复杂度高,需处理空回滚、幂等、防悬挂等问题。 | 适用于对性能要求极高,或需对底层资源进行精确控制的场景。 |
| SAGA 模式 | 将长事务拆分为多个有补偿逻辑的本地子事务,通过状态机或事件驱动依次执行。正向失败时,反向调用补偿操作。 | 适合长事务,性能高,模型简单。 | 需自行实现补偿逻辑,无法保证隔离性(需业务层控制)。 | 适用于业务流程长、需要与外部服务交互(如调用支付宝支付后补偿退款)的场景。 |
| XA 模式 | 基于数据库标准 XA 协议实现的两阶段提交,由事务管理器协调资源 [。事务管理器协调资源。 | 强一致性(CP 模型),对业务无侵入。 | 性能低(资源锁持有到二阶段结束),依赖于数据库对 XA 的支持。 | 适用于金融、交易等对数据一致性要求极高、并发量不高的核心场景。 |
核心工作流程
- 开启全局事务:TM 向 TC 申请开启全局事务,TC 返回一个全局唯一的 XID。
- 分支事务注册:XID 在微服务调用链中传播。每个服务(RM)执行业务操作时,会向 TC 注册分支事务。
- 全局提交/回滚:TM 根据业务执行结果,向 TC 发起全局提交或回滚决议。
- 协调分支事务:TC 根据决议,协调所有 RM 完成二阶段提交或回滚(如 AT 模式根据
undo_log补偿)。
实际集成注意事项
- 组件部署:TC 是独立部署的服务端,负责维护全局事务状态。
- 数据表:使用 AT 模式时,每个业务数据库都需要创建
undo_log表。若使用文件/数据库模式存储事务日志,TC 服务端也需对应的global_table、branch_table等表。 - 配置:需要配置 TC 的服务地址、事务分组,并将应用的数据源代理为
DataSourceProxy,以让 Seata 能拦截 SQL。
【中等】Seata 支持哪些模式的分布式事务?
Seata 支持四种事务模式:AT、TCC、Saga、XA。
- AT 模式:通过代理数据源自动管理事务。在业务 SQL 执行前后自动记录数据快照到 undo_log 表,提交时直接提交本地事务,回滚时用快照生成反向 SQL 还原数据。业务侵入最小,加个
@GlobalTransactional注解就行。 - TCC 模式:是两阶段提交的业务层实现。把一个操作拆成 Try 预留资源、Confirm 确认提交、Cancel 回滚释放三步,每一步都要业务代码自己实现。侵入性大,但性能最好,适合高并发场景。
- Saga 模式:是长事务解决方案。把全局事务拆成多个有序的小事务,每个事务配一个补偿操作。某个事务失败了,按相反顺序依次执行补偿操作回滚之前的变更。适合流程长、参与方多的业务。
- XA 模式:基于数据库原生的 XA 协议。一阶段执行 SQL 后 XA prepare,资源一直锁着,等 TC 统一下发 commit 或 rollback。强一致性,但性能最差,适合对一致性要求极高的场景。
| 模式 | 侵入性 | 性能 | 一致性 | 适用场景 |
|---|---|---|---|---|
| AT | 低 | 高 | 最终 | 大部分业务 |
| TCC | 高 | 最高 | 最终 | 高并发交易 |
| Saga | 中 | 高 | 最终 | 长事务、跨系统 |
| XA | 低 | 低 | 强 | 传统迁移、强一致 |
【中等】了解 Seata 的实现原理吗?
Seata 是一款开源的分布式事务解决方案,其实现原理基于改进型的两阶段提交协议,核心目标是让分布式事务的使用体验与本地事务一样简单。
核心组件
- TC (Transaction Coordinator):独立部署的中心控制器,管理全局事务状态,协调分支二阶段提交或回滚。
- TM (Transaction Manager):嵌入业务服务,通过注解标记事务边界,向 TC 发起开启、提交、回滚请求。
- RM (Resource Manager):嵌入数据层,代理数据源,注册分支事务并记录回滚日志,执行 TC 下发指令。
协同:TM 申请开启 → RM 注册分支并上报 → TC 决策并通知 RM 统一提交或回滚。
Seata 工作流程
- 开启事务:TM 向 TC 申请创建全局事务,获取 XID。
- 执行业务:XID 透传,RM 向 TC 注册分支事务;执行数据库操作并写入回滚日志,提交本地事务。
- 全局决策:业务结束,TM 向 TC 发起全局提交或回滚。
- 协调分支:TC 通知所有 RM 执行二阶段操作(提交/回滚)。
- 结果确认:RM 执行完毕并反馈 TC,TC 更新最终状态。
Seata 四种事务模式
- AT 模式:自动代理 SQL,利用
undo_log实现回滚,对业务无侵入。 - TCC 模式:业务需手动实现 Try-Confirm-Cancel 三阶段,资源控制精准,性能高但代码侵入强。
- SAGA 模式:将长事务拆分为有正向和补偿操作的小事务,适合复杂业务流程。
- XA 模式:基于标准 2PC 协议,提供强一致性,但性能较低。
【中等】Seata 的事务回滚是怎么实现的?
Seata 四种事务模式回滚机制
- AT 模式:依赖
undo_log表记录数据修改前后的快照。回滚时,RM 读取快照,通过逆向 SQL 将数据还原至原始状态。 - TCC 模式:回滚由业务代码实现。TC 触发全局回滚时,调用各分支的
Cancel方法,撤销Try阶段预留的资源。 - SAGA 模式:每个子事务对应一个补偿操作。回滚时,按执行顺序的相反方向依次调用已成功子事务的补偿方法,恢复初始状态。
- XA 模式:基于标准 XA 协议。TC 决定回滚后,通知所有 RM 执行
ROLLBACK,由数据库自身通过 XA 机制将未提交的事务回滚。
分布式调度
【简单】Spring Cloud 有哪些注册中心?
Spring Cloud 通过服务发现抽象支持多种注册中心,主流方案有以下几种:
- Eureka:Netflix 出品,AP 模型,通过客户端心跳保活,是早期的 Spring Cloud 标配,目前已进入维护状态。
- Consul:HashiCorp 出品,CP 模型,基于 Raft 协议,内置了健康检查、KV 存储和多数据中心能力。
- Zookeeper:Apache 顶级项目,CP 模型,强一致性的分布式协调服务,通过临时节点实现服务注册。
- Nacos:阿里巴巴开源,支持 AP/CP 动态切换,集服务发现与配置管理于一身,是国内 Spring Cloud Alibaba 生态的首选。
- Kubernetes Service:云原生环境下的特殊方案,利用 K8s 内置的 Service 和 Endpoints 机制实现服务发现,无需额外部署注册中心。
核心对比与选型
| 特性维度 | Eureka | Consul | Zookeeper | Nacos |
|---|---|---|---|---|
| CAP 模型 | AP(可用性优先) | CP(一致性优先) | CP(一致性优先) | AP/CP 可切换 |
| 健康检查 | 客户端心跳 | 多种主动探测 | 会话(Session)保持 | 多种模式 |
| 配置中心 | 无 | 内置 KV Store | 需自研 | 内置 |
| 管理界面 | 简单 UI | 功能完善 | 无 | 功能完善 |
- 新项目选型:国内 Java 技术栈首选 Nacos(功能全,社区活跃);若追求强一致性或有多数据中心需求,可选 Consul。
- 维护中项目:若已有 Eureka 或 Zookeeper,可继续沿用,需注意 Eureka 已停更,Zookeeper 不适合频繁的服务注册场景。
- 云原生环境:可直接采用 Kubernetes Service,简化运维。
【简单】什么是 Eureka?
Eureka 是 Netflix 开源的服务注册与发现组件,曾是 Spring Cloud 的核心。
- Server:注册中心,接收服务注册、维护心跳、剔除失效实例。
- Client:内嵌在服务中,负责注册、心跳续约(默认 30 秒)、拉取注册表并缓存(默认 30 秒更新)。
- 关键机制:AP 模型(可用性优先)、自我保护(网络异常时不轻易剔除实例)。
- 现状:2.0 已停止更新,仅建议现有项目沿用,新项目优先考虑 Nacos 或 Consul。
一句话:Eureka 是经典的服务发现框架,采用 AP 设计和自我保护机制,现已进入维护期。
【简单】Eureka 的实现原理说一下?
Eureka 的实现原理可以拆成三个核心机制来看:服务注册发现、心跳续约、服务剔除。
- 服务注册发现:服务实例启动后,Eureka Client 会向 Eureka Server 发送一个 POST 请求,把自己的元数据注册上去,包括服务名、IP、端口、健康检查地址这些信息。Server 把这些信息存到内存里的注册表 registry 中。服务消费者从 Server 拉取服务列表,缓存到本地,之后的服务调用就基于这份本地缓存做负载均衡选择实例。
- 心跳续约:注册完成后,Client 每隔 30 秒向 Server 发送一次心跳,本质上是个 PUT 请求。Server 收到后更新这个实例 Lease 中的 lastUpdateTimestamp,表示它还活着。心跳机制保证了注册表里的数据是相对新鲜的。
- 服务剔除:如果 Server 连续 90 秒没收到某个实例的心跳,就会把它标记为过期。Server 有个后台任务,每 60 秒扫一次,把过期的实例从注册表里删掉。不过如果触发了自我保护机制,剔除动作会被暂停。
【中等】Spring Cloud 如何实现服务注册?
核心实现步骤
无论使用哪种注册中心,在服务提供者端的实现逻辑基本一致:
- 添加依赖:在项目的
pom.xml中引入对应注册中心的 Starter 依赖。 - 配置地址:在
application.yml或bootstrap.yml中指定注册中心的地址,并配置服务名(spring.application.name)。 - 启用注解:在启动类上添加
@EnableDiscoveryClient或特定注册中心的注解(如@EnableEurekaClient),以开启服务注册与发现功能。
主流注册中心的实现差异
不同注册中心在具体实现上略有不同,主要体现在依赖和配置项上。
| 注册中心 | 核心依赖 | 关键配置项 (示例) | 启用注解 |
|---|---|---|---|
| Eureka | spring-cloud-starter-netflix-eureka-client | eureka.client.serviceUrl.defaultZone=http://... | @EnableEurekaClient |
| Nacos | spring-cloud-starter-alibaba-nacos-discovery | spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 | @EnableDiscoveryClient |
| Consul | spring-cloud-starter-consul-discovery | spring.cloud.consul.host=127.0.0.1 spring.cloud.consul.port=8500 | @EnableDiscoveryClient |
| Zookeeper | spring-cloud-starter-zookeeper-discovery | spring.cloud.zookeeper.connect-string=127.0.0.1:2181 | @EnableDiscoveryClient |
底层工作机制
服务注册不仅是配置,其背后有一套标准的生命周期管理:
- 服务注册:服务启动时,客户端(如 Eureka Client)向注册中心(如 Eureka Server)发起请求,将自己的服务名、IP 地址、端口号等元数据信息注册上去。注册中心将这些信息存储在一个双层 Map 中(第一层 key 是服务名,第二层 key 是实例名)。
- 服务续约:注册成功后,客户端会定期(如默认 30 秒)发送心跳包到注册中心,以告知自身状态正常,这个过程叫“心跳续约”。
- 服务同步:在注册中心集群模式下,一个节点收到注册信息,会将该信息同步给集群中其他节点,保证注册表数据一致。
【简单】Consul 是什么?
Consul 是由 HashiCorp 公司开发的一款服务网格解决方案,在微服务领域,它最广为人知的身份是一个功能全面的服务注册中心。
它的核心功能主要体现在三个方面:
- 服务发现:作为注册中心,服务启动时向 Consul 注册信息,客户端通过 DNS 或 HTTP API 查询服务地址。
- 健康检查:支持多种主动探测方式(如 HTTP 返回码、TCP 端口、脚本执行),比单纯的心跳机制更可靠,能准确判断服务真实状态。
- KV 存储:内置键值存储,可用于动态配置、协调信息等,部分场景下可替代轻量级配置中心。
在一致性模型上,Consul 采用 Raft 协议,属于 CP 模型,保证了数据强一致性,适用于对一致性要求较高的生产环境。
与 Spring Cloud 集成时,只需引入 spring-cloud-starter-consul-discovery 依赖并配置 Consul 地址即可。
一句话总结:Consul 是一个 CP 模型、功能丰富、支持多数据中心的服务发现与配置工具,其强一致性和完善的健康检查机制是区别于 Eureka 的核心特点。
【简单】Nacos 中的 Namespace 是什么?
Nacos 中的 Namespace 是用于环境隔离和资源隔离的逻辑单元,是实现多租户和多环境管理的基础。
它的核心作用如下:
- 环境隔离:通过 Namespace 可以将同一套 Nacos 集群划分为多个相互隔离的逻辑环境。例如,创建
dev、test、prod三个 Namespace,不同环境的服务和配置数据在物理上虽然存储在同一集群,但在逻辑上完全隔离,互不可见。 - 多租户支持:在 SaaS 或企业内部多团队场景中,可以为每个团队或每个租户分配独立的 Namespace。团队 A 只能操作自己的 Namespace,无法感知或修改团队 B 的服务与配置。
- 资源唯一性:在 Nacos 中,一个资源的完整定位由 Namespace + Group + Data ID 三元组唯一确定。不同 Namespace 下可以有相同的 Group 和 Data ID,这为多环境部署相同的配置文件提供了便利。
- 默认 Namespace:Nacos 初始化时会自动创建一个名为
public的默认 Namespace,如果不显式指定,所有服务和配置都会归属于这个公共空间。
在 Spring Cloud 中,可以通过配置 spring.cloud.nacos.discovery.namespace 和 spring.cloud.nacos.config.namespace 来指定服务注册和配置拉取所属的 Namespace。
【简单】什么是 Hystrix?
Hystrix 是 Netflix 开源的容错库,核心功能如下:
- 断路器:失败率达阈值自动熔断,防止雪崩。
- 资源隔离:通过线程池或信号量隔离依赖,避免相互影响。
- 降级回退:熔断或异常时执行预定义的 Fallback 逻辑。
目前 Hystrix 已进入维护状态,Spring Cloud 官方推荐替代品为 Resilience4j。
【中等】Sentinel 是怎么实现限流的?
Sentinel 的限流实现基于责任链模式,核心是围绕资源的 Entry 申请过程,通过一系列 Slot 进行规则检查与统计。具体实现分为以下几个核心维度:
限流统计维度和算法
- QPS 限流:采用滑动时间窗口算法。
- 通过
LeapArray结构将时间划分为多个小窗口(如 1 秒拆成 2 个 500ms 窗口),动态统计请求量,实现更精准的流量控制。
- 通过
- 线程数限流:采用信号量隔离机制。
- 统计当前资源的并发线程数,超过阈值则直接拒绝新请求。相比 Hystrix 的线程池隔离,这种方式无额外线程切换开销,适用于控制长耗时操作的并发度。
- 热点参数限流:结合 LRU + 令牌桶算法。
- 统计传入参数中的热点值(如商品 ID),针对特定参数值进行精细化的并发数或 QPS 控制,防止单一热点值打垮系统。
限流效果控制策略
- 快速失败:默认模式,超出阈值直接拒绝,抛出
FlowException。 - 预热模式:冷启动时,流量阈值从
1/3的设定值开始,在预热时长内线性增长到设定值,避免刚启动时被突发流量打垮。 - 匀速排队:严格控制请求通过间隔(如 QPS=100 则间隔 10ms),让请求以均匀速度通过,用于消息队列削峰填谷。
规则管理
- 动态规则配置:支持通过文件、Nacos、Apollo 等数据源动态推送和加载限流规则,无需重启应用。
- 集群限流:通过 Token Server 协调集群中各节点的流量,实现精确的集群整体流量控制。
核心执行流程
- 请求进入
SphU.entry()后,会经过ProcessorSlotChain(责任链):NodeSelectorSlot:为资源构建调用树节点。StatisticSlot:执行实时统计(pass/block 计数)。FlowSlot:根据限流规则(QPS/并发数)判断是否限流。- 若规则触发,抛出
BlockException;否则请求通过,继续执行业务逻辑。
总结:Sentinel 限流的本质是 “实时统计 + 规则校验”,通过滑动窗口统计实时指标,利用责任链模式执行校验,并支持多种流量整形策略来适应不同场景。
【中等】Sentinel 是怎么实现集群限流的?
Sentinel 集群限流核心机制
- 引入 Token Server:独立部署的全局流量协调者,负责维护全局限流状态(如集群 QPS 总量)并做出最终决策。
- Token Client 工作机制:业务节点处理请求时,向 Token Server 申请令牌。若 Server 可用,则根据其响应决定放行或拒绝;若 Server 不可用或超时,自动退化成本地限流规则,保证系统基础可用。
- 性能优化:采用批量拉取策略(如一次申请多个令牌在本地消费),大幅减少网络通信开销。
- 高可用保障:支持多 Server 集群部署,客户端本地限流兜底。
一句话总结:通过 Token Server 集中协调全局流量统计,配合客户端批量拉取和本地降级机制,实现精准的集群总体流量控制。
【中等】Sentinel 与 Hystrix 的区别是什么?
| 维度 | Sentinel | Hystrix |
|---|---|---|
| 设计理念 | 流量控制 + 熔断降级 + 系统保护 | 以隔离和熔断为主的容错机制 |
| 隔离策略 | 信号量隔离(并发线程数限流) | 线程池隔离(默认) / 信号量隔离 |
| 熔断策略 | 慢调用比例、异常比例、异常数 | 异常比例为主 |
| 限流能力 | 丰富(热点限流、匀速排队、预热模式) | 有限支持 |
| 系统保护 | 系统自适应保护(Load/CPU) | 不支持 |
| 控制台 | 完善,动态规则配置、实时监控 | 较弱,需自行集成 |
| 活跃度 | 活跃维护(阿里) | 已进入维护状态(Netflix) |
核心差异总结:
- 隔离机制:Hystrix 线程池隔离成本高,Sentinel 信号量隔离更轻量。
- 限流能力:Sentinel 支持丰富的流量整形,Hystrix 基本不具备。
- 系统级防护:Sentinel 提供自适应系统保护,Hystrix 无。
- 生态与现状:Sentinel 持续活跃,Hystrix 已停更,新项目选 Sentinel。
分布式治理
【简单】Spring Cloud 可以选择哪些 API 网关?
核心网关对比
- Spring Cloud Gateway:官方主推,基于 WebFlux/Netty 的异步非阻塞网关,与 Spring Cloud 生态(Nacos、Sentinel 等)集成无缝,Java 技术栈首选。
- Kong:基于 Nginx + OpenResty 的高性能网关,单机 QPS 10 万+,插件生态丰富;二次开发需 Lua,Java 开发者门槛较高。
- Apache APISIX:同属 Nginx/Lua 路线,性能和 Kong 相当,支持多语言插件(Java/Go/Python),配置通过 etcd 热更新,国内应用广泛。
- Zuul:Netflix 早期网关,1.x 为同步阻塞模型,性能瓶颈明显,整体已进入维护模式,新项目不推荐。
- Envoy:C++ 底层,CNCF 毕业项目,适合服务网格及多语言架构,二次开发难度大。
选型建议
- 纯 Java 技术栈:首选 Spring Cloud Gateway。
- 极致性能或多语言架构:Kong 或 Apache APISIX。
- 服务网格场景:Envoy 为更优选择。
【简单】什么是 Spring Cloud Gateway?
Spring Cloud Gateway 是基于 Spring WebFlux 和 Netty 构建的响应式 API 网关,提供异步非阻塞 I/O,是 Spring Cloud 生态的官方入口解决方案。
Spring Cloud Gateway 是微服务架构的统一流量入口,集路由、断言、过滤于一体,兼具高性能与生态集成度,是 Java 技术栈的首选网关。
核心组件
- 路由:基础单元,包含 ID、目标 URI、断言集合和过滤器集合。
- 断言:匹配请求条件(如路径、Header、参数),决定路由目标。
- 过滤器:在请求路由前后执行处理(如鉴权、限流、修改请求/响应)。
工作流程
- 请求进入网关
- 断言匹配路由
- 执行 Pre 过滤器链
- 转发到下游服务
- 执行 Post 过滤器链
- 返回响应
关键特性
- 高性能:基于 Netty 的非阻塞模型,优于传统 Servlet 网关。
- 动态路由:支持从注册中心(Nacos/Eureka)动态发现服务。
- 内置断言/过滤器工厂:Path、Method、Header、RateLimiter、Retry、CircuitBreaker 等。
- 易扩展:可自定义断言和过滤器。
与 Zuul 对比
- Zuul 1.x:同步阻塞模型,已进入维护状态。
- Spring Cloud Gateway:异步非阻塞,性能更高,官方推荐。
【中等】你项目里为什么选择 Gateway 作为网关?
项目选择 Spring Cloud Gateway 的核心原因:
- 生态集成度高:项目基于 Spring Cloud 技术栈,Gateway 与 Nacos、Sentinel、Spring Security 等组件无缝配合,开发运维成本最低。
- 异步非阻塞高性能:基于 WebFlux + Netty 的响应式模型,处理高并发时线程开销小,优于 Zuul 1.x 的同步阻塞模型。
- 路由与过滤能力灵活:内置丰富的断言和过滤器工厂,支持灰度发布、限流熔断、跨域处理等复杂需求,且易于自定义扩展。
- 非功能性能力整合:可便捷集成限流熔断(如 Sentinel)、日志审计、统一鉴权等横切关注点。
- 社区活跃且持续演进:作为 Spring 官方主推网关,版本迭代有保障,长期维护风险低。
【中等】Dubbo 和 Spring Cloud Gateway 有什么区别?
Dubbo 与 Spring Cloud Gateway 对比:
| 对比维度 | Dubbo | Spring Cloud Gateway |
|---|---|---|
| 核心定位 | RPC (远程过程调用) 框架 | API 网关 (流量入口) |
| 核心功能 | 服务间高性能调用、服务治理 | 请求路由、过滤链(安全、限流、日志) |
| 解决需求 | 服务之间如何调用 (东西向流量) | 外部请求如何进入微服务集群 (南北向流量) |
| 工作层次 | 服务层 (Service-to-Service) | 入口层 (Edge Service) |
| 关键能力 | 服务发现、负载均衡、容错、熔断 | 动态路由、身份认证、权限校验、限流 |
| 通信协议 | 默认 Dubbo 协议 (TCP)、HTTP、gRPC | HTTP、HTTPS (基于 WebFlux) |
总结与关系:在现代微服务架构中,二者是互补而非替代的关系。通常由 Spring Cloud Gateway 作为统一网关接收和处理所有外部请求,然后通过 Dubbo 在内部微服务之间进行高效、可靠的方法调用和治理。
【简单】什么是 Spring Cloud Zuul?
Zuul 是 Netflix 开源的一款基于 JVM 的 API 网关,在微服务架构中充当系统对外的统一入口 。它的核心作用是为后端服务提供路由和过滤功能 。
其主要作用包括:
- 动态路由:作为所有外部请求的入口,根据配置的路由规则(如 URL 路径),将请求自动转发到后端的指定微服务 。这实现了内部服务的调用细节对外部客户端的隐藏。
- 请求过滤:通过其强大的过滤器机制,在请求被路由前后执行统一的处理逻辑 。这通常用于实现身份认证、安全校验、请求日志记录、性能监控等横切关注点 。
- 负载均衡:集成 Ribbon,能够将请求负载均衡地分发到同一服务的多个实例上 。
- 服务容错:集成 Hystrix,为路由提供熔断和降级保护,防止后端服务故障引发级联雪崩 。
- 安全与监控:可在网关层统一进行访问控制和流量统计,收集关于请求和响应的数据,用于监控和分析 。
Zuul 的核心是其可插拔的过滤器链架构 。开发者通过实现自定义的过滤器,可以在请求生命周期的不同阶段(前置、路由、后置、错误)插入各种处理逻辑,从而使其功能具有很强的扩展性 。
【简单】你知道 Nacos 配置中心的实现原理吗?
Nacos 配置中心的核心机制可以概括为:客户端长轮询 + 服务端事件驱动 + 推拉结合。
核心机制分解
- 客户端侧
- 长轮询:发送本地配置 MD5 值,请求挂起 30 秒,服务端有变更立即返回
- 本地快照:配置在本地存有快照文件,服务端不可用时作为容灾保障
- 监听触发:收到变更通知后主动拉取最新配置,发布事件刷新
@RefreshScope的 Bean
- 服务端侧
- 事件驱动:配置变更先写入数据库,再发布变更事件
- 唤醒长轮询:事件唤醒挂起的长轮询请求,立即通知客户端
- 集群同步:变更事件同步到集群其他节点,保持全局一致性
核心要点
- 推拉结合:长轮询实现准实时推送,客户端主动拉取具体变更内容
- MD5 比对:通过 MD5 值判断配置是否变化,避免无效传输
- 本地快照:保证 Nacos 宕机时应用仍能加载最后配置
【简单】Spring Cloud Config 是什么?
Spring Cloud Config 是一套分布式配置中心解决方案,分为 Config Server 和 Config Client 两部分:
- Config Server 是一个集中式的配置服务器,所有微服务的配置文件都往这里存,底层默认用 Git 来管理配置内容,所以配置的版本控制天然就有了,谁改了什么、什么时候改的,一清二楚。
- Config Client 跑在每个微服务里,负责从 Config Server 拉取配置。服务启动时,根据自己的应用名和环境标识去请求对应的配置,拿到后直接加载到 Spring Environment 里用。
整体架构就是:
- Git 仓库存储各环境的配置文件
- Config Server 启动后连接 Git 仓库并暴露 HTTP 接口
- Config Client 启动时向 Config Server 发送请求,带上 application name 和 profile
- Config Server 从 Git 拉取对应的配置文件返回给 Client
- Client 将配置加载到 Spring Environment 中
【中等】Spring Cloud 支持哪些链路追踪方案?
Spring Cloud 生态里常用的链路追踪方案有这么几个:
- Spring Cloud Sleuth + Zipkin,这是 Spring Cloud 生态最经典的组合。Sleuth 负责在每个请求里自动生成 TraceId 和 SpanId,Zipkin 负责收集和展示追踪数据。
- Jaeger,CNCF 托管的分布式追踪系统,比 Zipkin 更适合大规模系统,支持几十万级别的 span 存储和查询。Spring Cloud Sleuth 也能和 Jaeger 对接。
- SkyWalking,Apache 开源的 APM 平台,不光能做链路追踪,还支持指标监控、告警、服务依赖分析,功能比较全。它用 Java Agent 方式接入,代码零侵入。
- OpenTelemetry,由 OpenTracing 和 OpenCensus 合并而来,是现在云原生应用推荐的追踪标准,跨平台跨语言支持好,是未来的主流方向。
分布式通信
【简单】什么是 Feign?
Feign 是一个声明式的 HTTP 客户端,旨在简化微服务之间的远程调用。开发者只需定义 Java 接口并通过注解描述请求细节,Feign 在运行时动态生成实现,完成实际的 HTTP 请求。
核心特性
- 声明式编程:使用
@FeignClient注解声明客户端,接口方法映射为 HTTP 请求,大幅降低代码量。 - 负载均衡:默认集成 Ribbon,通过服务名自动发现实例并轮询调用。
- 与 Spring MVC 兼容:复用
@RequestMapping、@PathVariable等注解,学习成本低。 - 可插拔编解码:支持 Jackson、Gson 等消息转换器,灵活处理请求/响应体。
工作原理
- 启动时扫描
@FeignClient接口,为其生成动态代理。 - 调用接口方法时,代理根据注解构建请求 URL、参数、头信息。
- 通过 Ribbon 选择目标服务实例,执行 HTTP 调用。
- 将响应反序列化为方法返回类型。
关键注意点
- 参数注解:
@RequestParam必须指定 name,否则可能失败。 - 复杂参数:默认以 POST 发送 JSON,服务端需使用
@RequestBody接收。 - 超时配置:需在配置文件中设置
ribbon.ReadTimeout和ribbon.ConnectTimeout。 - 熔断降级:早期集成 Hystrix,Spring Cloud 2020.0.0+ 推荐使用 Resilience4j。
Feign 的核心价值在于将远程调用封装成本地接口,让微服务间通信变得直观、高效。
【中等】Feign 是如何实现负载均衡的?
Feign 本身是一个声明式 HTTP 客户端,不直接实现负载均衡,而是通过集成 Ribbon(或较新版本中的 Spring Cloud LoadBalancer)来完成客户端负载均衡。
核心实现原理
- 动态代理拦截:Feign 在运行时为接口生成动态代理,每次方法调用被拦截后,根据
@FeignClient注解中的服务名(name或value)构造请求 URL。 - 服务发现获取列表:Feign 会从服务注册中心(如 Nacos、Eureka)拉取该服务名对应的所有可用实例列表。
- 负载均衡器选择实例:Feign 将服务名和实例列表交给内置的负载均衡器(如 Ribbon 的
ILoadBalancer),由负载均衡器根据配置的策略(轮询、随机、响应时间加权等)选出一个目标实例。 - 发起真实请求:Feign 将请求 URL 替换为所选实例的 IP 和端口,通过 HTTP 客户端(如 OkHttp、Apache HttpClient)发起调用。
底层组件替换
- 早期版本默认集成 Ribbon(需引入
spring-cloud-starter-netflix-ribbon)。 - 新版本官方推荐使用 Spring Cloud LoadBalancer,它是与 Spring Cloud Commons 集成的反应式负载均衡器,无需额外依赖即可与 Feign 配合使用。
配置方式
# 为指定服务配置负载均衡策略(Ribbon 示例)
service-name:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule【中等】为什么 Feign 第一次调用耗时很长?
Feign 首次调用慢是懒加载设计的初始化开销,通过饥饿加载或预热可解决。
核心原因:
- 懒加载机制:服务发现、负载均衡器、HTTP 客户端(连接池)均在首次调用时初始化,而非启动时。
- 额外组件初始化:若集成 Hystrix,首次调用需创建线程池或信号量。
- 网络开销:首次调用可能触发 DNS 解析或从注册中心拉取服务列表。
解决方案:
- 启用饥饿加载:配置
ribbon.eager-load.enabled=true,让负载均衡器启动时预初始化。 - 预热调用:应用启动后主动发起一次健康检查或空请求,触发初始化完成。
【中等】Feign 和 OpenFeign 有什么区别?
OpenFeign 是 Feign 的 Spring 增强版,是当前 Spring Cloud 项目的事实标准。
- 归属:Feign 是 Netflix 组件;OpenFeign 是 Spring Cloud 官方封装版。
- 注解:Feign 仅支持自身注解;OpenFeign 额外支持 Spring MVC 注解(如
@RequestMapping),开发更便捷。 - 集成:OpenFeign 深度集成 Spring 生态(自动配置、消息转换器、负载均衡器)。
- 依赖:OpenFeign 对应
spring-cloud-starter-openfeign(新版),Feign 对应旧版 starter。
【简单】Feign 和 Dubbo 有什么区别?
Feign 是 HTTP 风格的客户端,注重 Spring 生态集成;Dubbo 是高性能 RPC 框架,注重服务治理和性能。
- 通信协议:Feign 基于 HTTP 协议,通常用于 RESTful API 调用;Dubbo 基于自定义 TCP 协议(如 Netty),性能更高,适合内部服务间高频调用。
- 负载均衡:Feign 本身不具备负载均衡能力,需集成 Ribbon 或 Spring Cloud LoadBalancer;Dubbo 内置多种负载均衡策略(随机、轮询、一致性哈希等)。
- 服务治理:Dubbo 提供丰富的服务治理功能(服务路由、容错、降级、限流等),Feign 依赖 Spring Cloud 生态(如 Hystrix、Sentinel)组合实现。
- 生态集成:Feign 与 Spring Cloud 生态无缝融合,特别适合 Spring Boot 项目;Dubbo 是独立 RPC 框架,可通过 Spring Cloud Alibaba 整合到 Spring Cloud 体系。
【简单】HTTP 与 RPC 有什么区别?
HTTP是通用通信协议,侧重标准化与互操作性;RPC是高性能调用方式,侧重效率与内部服务治理。
| 维度 | HTTP | RPC |
|---|---|---|
| 协议定位 | 应用层通信标准 | 远程调用方式 |
| 数据格式 | 文本为主(JSON/XML) | 二进制为主(Protobuf等) |
| 性能 | 相对低(文本解析、短连接) | 高(长连接、二进制传输) |
| 服务治理 | 需额外组件(注册中心、网关) | 框架内置(负载均衡、熔断) |
| 适用场景 | 对外API、跨语言异构 | 内部服务间高性能调用 |