SpringCloud 常见面试题
概念
什么是微服务?你是怎么理解微服务的?
微服务架构是一种架构模式或者说是一种架构风格,它提倡将单一应用程序划分为一组小的服务,每个服务运行在其独立的自己的进程中,服务之间相互协调、互相配合,为用户提供最终价值。服务之间采用轻量级的通信机制互相沟通(通常是基于HTTP的RESTful API),每个服务都围绕着具体的业务进行构建,并且能够被独立的构建在生产环境、类生产环境等。另外,应避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具对其进行构建,可以有一个非常轻量级的集中式管理来协调这些服务,可以使用不同的语言来编写服务,也可以使用不同的数据存储。
通俗地来讲:
微服务就是一个独立的职责单一的服务应用程序。在 intellij idea 工具里面就是用maven开发的一个个独立的module,具体就是使用springboot 开发的一个小的模块,处理单一专业的业务逻辑,一个模块只做一个事情。
微服务强调的是服务大小,关注的是某一个点,具体解决某一个问题/落地对应的一个服务应用,可以看做是idea 里面一个 module。
微服务有什么好处?
微服务优点很多,但是我们通常说一个东西好肯定会跟另一个东西比较, 通常说微服务好会和单体项目进行比较。以下是微服务相对于单体项目的一些显著好处:
单体项目的缺点:
- 可扩展性受限: 单体应用通常在可扩展性方面受到限制,因为整个应用程序必须一起扩展。这意味着即使只有一个组件需要更多资源,也必须扩展整个应用程序,这可能会导致资源浪费。
- 难以维护和更新: 随着时间的推移,单体应用程序往往变得越来越庞大和复杂,难以理解、维护和更新。每次修改都可能引发意想不到的影响。
- 高风险: 单体应用程序中的一个小错误或故障可能会导致整个应用程序崩溃,因此存在较高的风险。此外,长时间不更新的单体应用可能会受到安全威胁。
- 技术栈限制: 单体应用程序通常使用相同的技术栈,这可能会限制您在项目中使用最新的技术和工具的能力。
- 团队协作复杂: 单体应用程序的所有组件都在一个代码库中,这可能导致开发团队之间的冲突和协作问题,尤其在大型团队中更为突出。
微服务项目的优点:
- 可扩展性: 微服务架构允许您根据需要独立地扩展单个服务,而不必扩展整个应用程序,这提供了更高的可扩展性。
- 灵活性和快速开发: 微服务允许开发团队独立设计、开发和部署服务,这提高了灵活性,允许团队更快地推出新功能和更新。
- 故障隔离和容错性: 单个微服务的故障通常不会影响其他服务,提高了应用程序的容错性,同时更容易识别和解决故障。
- 技术多样性: 微服务允许您选择适合每个服务的最佳技术栈,这有助于充分利用各种技术和工具的优势。
- 独立部署和维护: 微服务可以独立部署和维护,这减少了风险,使团队能够更快速地进行修复和更新。
- 团队协作: 不同团队可以独立工作在不同服务上,这提高了团队的自治和协作能力,减少了冲突。
总的来说,微服务项目通过提供更高的可扩展性、灵活性和容错性,以及更容易管理的部署和维护过程,有助于克服单体应用程序的一些限制和缺点。但请注意,微服务架构也会引入一些新的复杂性,需要更多的管理和监控。
单体应用、SOA 和微服务架构有什么区别
单体应用、SOA和微服务架构都是不同的架构风格,适用于不同的情况。
单体应用像一个整体,所有的功能都打包在一个应用中。这种架构风格容易部署和测试,但随着系统规模的扩大,它的灵活性和可维护性会降低。
SOA是一种面向服务的架构风格,将系统划分为多个独立的服务。这些服务可以通过网络调用,并且可以跨平台、跨语言进行交互。SOA的优点是提供了跨系统的服务复用和松散耦合的交互方式,但实现SOA需要投入大量的工作,包括服务的定义、接口的选择、协议的制定等。
微服务架构进一步将系统划分为多个小型、独立的服务,每个服务都是一个单独的应用程序,可以独立部署、运行和扩展。微服务架构具有更高的灵活性和可维护性,适用于复杂的大型系统,强调服务的自治和独立性。但是,实施微服务架构也需要投入大量的工作,包括服务的定义、通信机制的选择、服务的管理等。
分布式和微服务有什么区别?
分布式系统和微服务架构是两个相关但不同的概念,它们的注重点其实不太一样。
分布式系统:它是由多台计算机或多节点组成的系统,各节点之间通过网络进行通信和协作,共同完成一个或多个共享的任务也就是说分布式的各个节点其实目标是一致的,之所以要分布式只是为了有更好的能力,能更快、更高效地承接任务。比如常见的分布式文件系统、分布式数据库。
微服务:其实是一种服务的架构风格,它主要是为了把一个大而全的服务,拆分成多个可以独立、松耦合的服务单元,为了让这些服务单元可以独立部署、运行、管理比如电商服务拆分成微服务,可以分为商品服务、用户服务、订单服务、库存服务等等
什么是Spring Cloud ?
Spring cloud 流应用程序启动器是基于 Spring Boot 的 Spring 集成应用程序,提供与外部系统的集成。Spring cloud Task,一个生命周期短暂的微服务框架,用于快速构建执行有限数据处理的应用程序。
Spring cloud 流应用程序启动器是基于 Spring Boot 的 Spring 集成应用程序,提供与外部系统的集成。Spring cloud Task,一个生命周期短暂的微服务框架,用于快速构建执行有限数据处理的应用程序。
现在有哪些流行的微服务解决方案?
目前最主流的微服务开源解决方案有三种:
Dubbo:
- Dubbo 是一个高性能、轻量级的 Java 微服务框架,最初由阿里巴巴(Alibaba)开发并于2011年开源。它提供了服务注册与发现、负载均衡、容错、分布式调用等功能,后来一度停止维护,在近两年,又重新开始迭代,并推出了Dubbo3。
- Dubbo 使用基于 RPC(Remote Procedure Call)的通信模型,具有较高的性能和可扩展性。它支持多种传输协议(如TCP、HTTP、Redis)和序列化方式(如JSON、Hessian、Protobuf),可根据需求进行配置。
- Dubbo更多地被认为是一个高性能的RPC(远程过程调用)框架,一些服务治理功能依赖于第三方组件实现,比如使用ZooKeeper、Apollo等等。
Spring Cloud Netflix:
- Spring Cloud Netflix 是 Spring Cloud 的一个子项目,结合了 Netflix 开源的多个组件,但是Netflix自2018年停止维护和更新Netflix OSS项目,包括Eureka、Hystrix等组件,所以Spring Cloud Netflix也逐渐进入了维护模式。
- 该项目包含了许多流行的 Netflix 组件,如Eureka(服务注册与发现)、Ribbon(客户端负载均衡)、Hystrix(断路器)、Zuul(API 网关)等。它们都是高度可扩展的、经过大规模实践验证的微服务组件。
Spring Cloud Alibaba:
- Spring Cloud Alibaba 是 Spring Cloud 的另一个子项目,与阿里巴巴的分布式应用开发框架相关。它提供了一整套与 Alibaba 生态系统集成的解决方案。
- 该项目包括 Nacos(服务注册与发现、配置管理)、Sentinel(流量控制、熔断降级)、RocketMQ(消息队列)等组件,以及与 Alibaba Cloud(阿里云)的集成。它为构建基于 Spring Cloud 的微服务架构提供了丰富的选项。
这三种方案有什么区别:
| 特点 | Dubbo | Spring Cloud Netflix | Spring Cloud Alibaba |
|---|---|---|---|
| 开发语言 | Java | Java | Java |
| 服务治理 | 提供完整的服务治理功能 | 提供部分服务治理功能 | 提供完整的服务治理功能 |
| 服务注册与发现 | ZooKeeper/Nacos | Eureka/Consul | Nacos |
| 负载均衡 | 自带负载均衡策略 | Ribbon | Ribbon\Dubbo负载均衡策略 |
| 服务调用 | RPC方式 | RestTemplate/Feign | Feign/RestTemplate/Dubbo |
| 熔断器 | Sentinel | Hystrix | Sentinel/Resilience4j |
| 配置中心 | Apollo | Spring Cloud Config | Nacos Config |
| API网关 | Higress/APISIX | Zuul/Gateway | Spring Cloud Gateway |
| 分布式事务 | Seata | 不支持分布式事务 | Seata |
| 限流和降级 | Sentinel | Hystrix | Sentinel |
| 分布式追踪和监控 | Skywalking | Spring Cloud Sleuth + Zipkin | SkyWalking或Sentinel Dashboard |
| 微服务网格 | Dubbo Mesh | 不支持微服务网格 | Service Mesh(Nacos+Dubbo Mesh) |
| 社区活跃度 | 相对较高 | 目前较低 | 相对较高 |
| 孵化和成熟度 | 孵化较早,成熟度较高 | 成熟度较高 | 孵化较新,但迅速发展 |
-在面试中,微服务一般主要讨论的是Spring Cloud Netflix,其次是Spring Cloud Alibaba,Dubbo更多的是作为一个RPC框架来问。
Spring Cloud有什么优势
使用 Spring Boot 开发分布式微服务时,我们面临以下问题
- 与分布式系统相关的复杂性-这种开销包括网络问题,延迟开销,带宽问题,安全问题。
- 服务发现-服务发现工具管理群集中的流程和服务如何查找和互相交谈。它涉及一个服务目录,在该目录中注册服务,然后能够查找并连接到该目录中的服务。
- 冗余-分布式系统中的冗余问题。
- 负载平衡 --负载平衡改善跨多个计算资源的工作负荷,诸如计算机,计算机集群,网络链路,中央处理单元,或磁盘驱动器的分布。
- 性能-问题 由于各种运营开销导致的性能问题。
- 部署复杂性-Devops 技能的要求。
说下微服务有哪些组件?
微服务给系统开发带来了一些问题和挑战,如服务调用的复杂性、分布式事务的处理、服务的动态管理等。为了更好地解决这些问题和挑战,各种微服务治理的组件应运而生,充当微服务架构的基石和支撑。
微服务的各个组件和常见实现:
- 注册中心:用于服务的注册与发现,管理微服务的地址信息。常见的实现包括:
- Spring Cloud Netflix:Eureka、Consul
- Spring Cloud Alibaba:Nacos
- 配置中心:用于集中管理微服务的配置信息,可以动态修改配置而不需要重启服务。常见的实现包括:
- Spring Cloud Netflix:Spring Cloud Config
- Spring Cloud Alibaba:Nacos Config
- 远程调用:用于在不同的微服务之间进行通信和协作。常见的实现保包括:
- RESTful API:如RestTemplate、Feign
- RPC(远程过程调用):如Dubbo、gRPC
- API网关:作为微服务架构的入口,统一暴露服务,并提供路由、负载均衡、安全认证等功能。常见的实现包括:
- Spring Cloud Netflix:Zuul、Gateway
- Spring Cloud Alibaba:Gateway、Apisix等
- 分布式事务:保证跨多个微服务的一致性和原子性操作。常见的实现包括:
- Spring Cloud Alibaba:Seata
- 熔断器:用于防止微服务之间的故障扩散,提高系统的容错能力。常见的实现包括:
- Spring Cloud Netflix:Hystrix
- Spring Cloud Alibaba:Sentinel、Resilience4j
- 限流和降级:用于防止微服务过载,对请求进行限制和降级处理。常见的实现包括:
- Spring Cloud Netflix:Hystrix
- Spring Cloud Alibaba:Sentinel
- 分布式追踪和监控:用于跟踪和监控微服务的请求流程和性能指标。常见的实现包括:
- Spring Cloud Netflix:Spring Cloud Sleuth + Zipkin
- Spring Cloud Alibaba:SkyWalking、Sentinel Dashboard
Spring、SpringMVC、Springboot、 Springcloud 的区别是什么?
Spring
Spring是一个生态体系(也可以说是技术体系),是集大成者,它包含了Spring Framework、Spring Boot、Spring Cloud等。它是一个轻量级控制反转(IOC)和面向切面(AOP)的容器框架,为开发者提供了一个简易的开发方式。
Spring的核心特性思想之一IOC,它实现了容器对Bean对象的管理、降低组件耦合,使各层服务解耦。
Spring的另一个核心特性就是AOP,面向切面编程。面向切面编程需要将程序逻辑分解为称为所谓关注点的不同部分。跨越应用程序多个点的功能称为跨领域问题,这些跨领域问题在概念上与应用程序的业务逻辑分离。有许多常见的例子,如日志记录,声明式事务,安全性,缓存等。
如果说IOC依赖注入可以帮助我们将应用程序对象相互分离,那么AOP可以帮助我们将交叉问题与它们所影响的对象分离。二者目的都是使服务解耦,使开发简易。
当然,除了Spring 的两大核心功能,还有如下这些,如:
- Spring JDBC
- Spring MVC
- Spring ORM
- Spring Test
SpringMVC
Spring与MVC可以更好地解释什么是SpringMVC,MVC为现代web项目开发的一种很常见的模式,简言之C(控制器)将V(视图、用户客户端)与M(模块,业务)分开构成了MVC ,业内常见的MVC模式的开发框架有Struts。
Spring MVC是Spring的一部分,主要用于开发WEB应用和网络接口,它是Spring的一个模块,通过DispatcherServlet, ModelAndView 和View Resolver,让应用开发变得很容易。
SpringBoot
SpringBoot是一套整合了框架的框架。
它的初衷:解决Spring框架配置文件的繁琐、搭建服务的复杂性。
它的设计理念:约定优于配置(convention over configuration)。
基于此理念实现了自动配置,且降低项目搭建的复杂度。
搭建一个接口服务,通过SpringBoot几行代码即可实现。基于Spring Boot,不是说原来的配置没有了,而是Spring Boot有一套默认配置,我们可以把它看做比较通用的约定,而Spring Boot遵循的是约定优于配置原则,同时,如果你需要使用到Spring以往提供的各种复杂但功能强大的配置功能,Spring Boot一样支持。
在Spring Boot中,你会发现引入的所有包都是starter形式,如:
- spring-boot-starter-web-services,针对SOAP Web Services
- spring-boot-starter-web,针对Web应用与网络接口
- spring-boot-starter-jdbc,针对JDBC
- spring-boot-starter-cache,针对缓存支持
Spring Boot是基于 Spring 框架开发的用于开发 Web 应用程序的框架,它帮助开发人员快速搭建和配置一个独立的、可执行的、基于 Spring 的应用程序,从而减少了繁琐和重复的配置工作。
Spring Cloud
Spring Cloud事实上是一整套基于Spring Boot的微服务解决方案。它为开发者提供了很多工具,用于快速构建分布式系统的一些通用模式,例如:配置管理、注册中心、服务发现、限流、网关、链路追踪等。Spring Boot是build anything,而Spring Cloud是coordinate anything,Spring Cloud的每一个微服务解决方案都是基于Spring Boot构建的。
SpringBoot和SpringCloud的区别?
SpringBoot专注于快速方便得开发单个个体微服务。
SpringCloud是关注全局的微服务协调整理治理框架,它将SpringBoot开发的一个个单体微服务整合并管理起来,为各个微服务之间提供,配置管理、服务发现、。断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等集成服务
SpringBoot可以离开SpringCloud独立使用开发项目, 但是SpringCloud离不开SpringBoot ,属于依赖的关系.
SpringBoot专注于快速、方便得开发单个微服务个体,SpringCloud关注全局的服务治理框架。
Spring Cloud各个微服务之间为什么要用http交互?难道不慢吗?
Spring Cloud是一个为分布式微服务架构构建应用程序的开发工具箱,是Spring Boot的扩展,通过各种微服务组件的集成,极大地简化了微服务应用程序的构建和开发。在分布式系统中,各个微服务之间的通信是非常重要的,而HTTP作为通信协议具有普遍性和可扩展性,是Spring Cloud微服务架构中主流的通信方式。
尽管使用HTTP作为微服务之间的通信协议存在一定的网络开销,但是这种不可避免的网络开销远低于我们所能得到的好处。使用HTTP通信可以实现松耦合和异步通信,微服务之间可以彼此独立地进行开发和测试,单个微服务的故障不会影响整个系统的运行,也可以支持各种不同的技术栈之间的互操作性。
另外,使用HTTP作为通信协议还具有优秀的可扩展性。HTTP协议定义了不同的请求方法(例如 GET、POST、DELETE 等),不同请求方法的扩展格式也很灵活,可以用来传递各种类型的数据和格式,同时HTTP协议支持缓存,减少重复性的数据传输和带宽开销。
当然,为了提高微服务之间的通信效率,我们也可以通过一些优化手段来减少HTTP协议的网络开销。例如,使用数据压缩和缓存技术来压缩和缓存请求和响应,减少网络数据传输量和响应时间;使用负载均衡技术来合理地分配请求和响应,避免单个微服务出现性能瓶颈;使用高速缓存技术来缓存请求和响应,避免重复的请求和响应等等。
因此,Spring Cloud各个微服务之间使用HTTP交互是一个比较成熟的选择。虽然它可能存在一些网络开销,但是在实际应用中,这种开销是可以优化和控制的,甚至可以提高系统的可扩展性和可靠性。
注册中心
注册中心是用来干什么的?
注册中心是用来管理和维护分布式系统中各个服务的地址和元数据的组件。它主要用于实现服务发现和服务注册功能。
总结一下注册中心的作用:
- 服务注册:各个服务在启动时向注册中心注册自己的网络地址、服务实例信息和其他相关元数据。这样,其他服务就可以通过注册中心获取到当前可用的服务列表。
- 服务发现:客户端通过向注册中心查询特定服务的注册信息,获得可用的服务实例列表。这样客户端就可以根据需要选择合适的服务进行调用,实现了服务间的解耦。
- 负载均衡:注册中心可以对同一服务的多个实例进行负载均衡,将请求分发到不同的实例上,提高整体的系统性能和可用性。
- 故障恢复:注册中心能够监测和检测服务的状态,当服务实例发生故障或下线时,可以及时更新注册信息,从而保证服务能够正常工作。
- 服务治理:通过注册中心可以进行服务的配置管理、动态扩缩容、服务路由、灰度发布等操作,实现对服务的动态管理和控制。
为什么需要服务注册发现?
在分布式系统中,服务的数量通常会有很多,而且规模还不是一般地大,与此同时,服务的部署和变化也会很频繁,因此,如果要依赖人工去维护这些服务的关系,实现服务的管理以及调用就会变得非常困难。
服务注册与发现的作用就是为了解决这个问题,它通过注册中心来维护服务生产者以及服务消费者之间的关系。当服务启动之后,其就会向注册中心注册自己的信息,比如服务名称、服务端口、服务的P地址等,当服务消费者需要调用某个服务的时候,它会向注册中心发起查询请求,获取对应服务的信息,然后向生产者服务发送请求。如果一些服务上线或者下线,注册中心都可以主动通知消费者,这就动态地实现了服务的上下线,在高峰期加机器,低峰期减机器,减少了管理的成本,十分方便。也可以方便实现服务的监控、管理等等。
SpringCloud可以选择哪些注册中心?
SpringCloud可以与多种注册中心进行集成,常见的注册中心包括:
- Eureka:Eureka 是 Netflix 开源的服务发现框架,具有高可用、弹性、可扩展等特点,并与 Spring Cloud 集成良好,已闭源。ap
- Consul:Consul 是一种分布式服务发现和配置管理系统,由 HashiCorp 开发。它提供了服务注册、服务发现、健康检查、键值存储等功能,并支持多数据中心部署。c/ap
- ZooKeeper:ZooKeeper 是 Apache 基金会开源的分布式协调服务,可以用作服务注册中心。它具有高可用、一致性、可靠性等特点。 cp
- Nacos:Nacos 是阿里巴巴开源的一个动态服务发现、配置管理和服务管理平台。它提供了服务注册和发现、配置管理、动态 DNS 服务等功能。 ap
- etcd:etcd 是 CoreOS 开源的一种分布式键值存储系统,可以被用作服务注册中心。它具有高可用、强一致性、分布式复制等特性。 cp
什么是 Eureka?
Eureka 是一个 Spring Cloud Netflix 的一款老牌注册中心,设计用于实现云端部署微服务架构中的服务注册与发现功能。
在技术领域,特别是分布式系统中,Eureka作为一个基于 RESTFul 的服务,主要职责包括:
- 服务注册:允许服务实例向 EurekaServer 注册自己的信息。这样,每个服务实例都能让 Eureka Server 获取到自身服务以及地址等信息。
- 服务发现:Eureka客户端可以从 Eureka server 查询到注册的服务实例信息,进而实现客户端的软负载均像和故障转移。服务消费者可以查询 Eureka Sener 获取到提供某一服务的所有服务实例列表,然后根据策略选择一个实例进行通信。
- 健康检查:Eureka 通过心跳机制监控服务实例的状态,确保服务列表的时效性和)准确性,如果某个服务实例宕机或天法响应,Eureka Senver将从注册表中移除该实例,避免了将流量导向不可用的服务(默认 90s)。
- 高可用性:Eureka 通过部署多个 Eureka Server 实例并相互复制注册信息,可以构建高可用的服务注册中心集群,提高系统的整体稳定性。
在 Spring Cloud 中,Eureka 被集成作为服务注册与服务发现的核心组件,通过 @EnableEurekaServer 和 @EnableEurekaClient 注解可以轻松实现服务注册中心或服务客户端
Eureka 在2020年后 Netflix 宣布不再积极维护,但它仍然是许多现有系统中服务注册中心的实现方案,并目有社区进行维护,
Spring Cloud如何实现服务的注册?
服务发布时,指定对应的服务名,将服务注册到 注册中心(Eureka 、Zookeeper)。
注册中心加@EnableEurekaServer,服务用@EnableDiscoveryClient,然后用ribbon或feign进行服务直接的调用发现。
说下Eureka、ZooKeeper、Nacos的区别?
| 特性 | Eureka | ZooKeeper | Nacos |
|---|---|---|---|
| 开发公司 | Netflix | Apache 基金会 | 阿里巴巴 |
| CAP | AP(可用性和分区容忍性) | CP(一致性和分区容忍性) | 既支持AP,也支持CP |
| 功能 | 服务注册与发现 | 分布式协调、配置管理、分布式锁 | 服务注册与发现、配置管理、服务管理 |
| 定位 | 适用于构建基于 HTTP 的微服务架构 | 通用的分布式协调服务框架 | 适用于微服务和云原生应用 |
| 访问协议 | HTTP | TCP | HTTP/DNS |
| 自我保护 | 支持 | - | 支持 |
| 数据存储 | 内嵌数据库、多个实例形成集群 | ACID 特性的分布式文件系统 ZAB 协议 | 内嵌数据库、MySQL 等 |
| 健康检查 | Client Beat | Keep Alive | TCP/HTTP/MYSQL/Client Beat |
| 特点 | 简单易用、自我保护机制 | 高性能、强一致性 | 动态配置管理、流量管理、灰度发布等 |
可以看到Eureka和ZooKeeper的最大区别是一个支持AP,一个支持CP,Nacos既支持既支持AP,也支持CP。
关于CAP相关理论和概念可以看这篇文章:CAPl理论
- Nacos除了作为注册中心外,还提供了配置管理、服务发现和事件通知等功能。Nacos默认情况下采用AP架构保证服务可用性,CP架构底层采用Raft协议保证数据的一致性。Nacos适合作为微服务注册中心和配置管理中心,支持快速发现、配置管理和服务治理等功能。
- Eureka是只提供注册中心功能的工具,它的设计理念是AP,即保证服务的可用性,不保证一致性。Eureka的各个节点之间相互注册,只要有一台Eureka节点存在,整个微服务就可以通讯。
- 而Zookeeper相比前两者,除了注册中心的功能,还提供了分布式协调服务,比如通知、公告、配置管理等。Zookeeper采用CP设计,可以保证数据的一致性,但是牺牲了一部分服务的可用性。Zookeeper适用于需要分布式协调服务的场景,如配置管理、命名服务等。
请说说Eureka和zookeeper 的区别?
Zookeeper保证了CP,Eureka保证了AP。
CAP理论详情请看CAP理论
A:高可用
C:一致性
P:分区容错性
- 当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的信息,但不能容忍直接down掉不可用。也就是说,服务注册功能对高可用性要求比较高,但zk会出现这样一种情况,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新选leader。问题在于,选取leader时间过长,30 ~ 120s,且选取期间zk集群都不可用,这样就会导致选取期间注册服务瘫痪。在云部署的环境下,因网络问题使得zk集群失去master节点是较大概率会发生的事,虽然服务能够恢复,但是漫长的选取时间导致的注册长期不可用是不能容忍的。
- Eureka保证了可用性,Eureka各个节点是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点仍然可以提供注册和查询服务。而Eureka的客户端向某个Eureka注册或发现时发生连接失败,则会自动切换到其他节点,只要有一台Eureka还在,就能保证注册服务可用,只是查到的信息可能不是最新的。除此之外,Eureka还有自我保护机制,如果在15分钟内超过85%的节点没有正常的心跳,那么Eureka就认为客户端与注册中心发生了网络故障,此时会出现以下几种情况:
- Eureka不在从注册列表中移除因为长时间没有收到心跳而应该过期的服务。
- Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其他节点上(即保证当前节点仍然可用)
- 当网络稳定时,当前实例新的注册信息会被同步到其他节点。
因此,Eureka可以很好地应对因网络故障导致部分节点失去联系的情况,而不会像Zookeeper那样使整个微服务瘫痪
Nacos和Eureka的区别
Nacos和Eureka整体结构类似,服务注册、服务拉取、心跳等待,但是也存在一些差异:

Nacos与eureka的共同点
- 都支持服务注册和服务拉取
- 都支持服务提供者心跳方式做健康检测
Nacos与Eureka的区别
- Nacos支持服务端主动检测提供者状态:临时实例采用心跳模式,非临时实例采用主动检测模式
- 临时实例心跳不正常会被剔除,非临时实例则不会被剔除
- Nacos支持服务列表变更的消息推送模式,服务列表更新更及时
- Nacos集群默认采用AP方式,当集群中存在非临时实例时,采用CP模式;Eureka采用AP方式
Eureka实现原理了解吗?

Eureka的实现原理,大概可以从这几个方面来看:
- 服务注册与发现: 当一个服务实例启动时,它会向Eureka Server发送注册请求,将自己的信息注册到注册中心。Eureka Server会将这些信息保存在内存中,并提供REST接口供其他服务查询。服务消费者可以通过查询服务实例列表来获取可用的服务提供者实例,从而实现服务的发现。
- 服务健康检查: Eureka通过心跳机制来检测服务实例的健康状态。服务实例会定期向Eureka Server发送心跳,也就是续约,以表明自己的存活状态。如果Eureka Server在一定时间内没有收到某个服务实例的心跳,则会将其标记为不可用,并从服务列表中移除,下线实例。
- 服务负载均衡: Eureka客户端在调用其他服务时,会从本地缓存中获取服务的注册信息。如果缓存中没有对应的信息,则会向Eureka Server发送查询请求。Eureka Server会返回一个可用的服务实例列表给客户端,客户端可以使用负载均衡算法选择其中一个进行调用。
其它的注册中心,如Nacos、Consul等等,在服务注册和发现上,实现原理都是大同小异。
Eureka Server怎么保证高可用?
Eureka Server保证高可用,主要通过这三个方面来实现:

- 多实例部署: 通过将多个Eureka Server实例部署在不同的节点上,可以实现高可用性。当其中一个实例发生故障时,其他实例仍然可以提供服务,并保持注册信息的一致性。
- 服务注册信息的复制: 当一个服务实例向Eureka Server注册时,每个Eureka Server实例都会复制其他实例的注册信息,以保持数据的一致性。当某个Eureka Server实例发生故障时,其他实例可以接管其工作,保证整个系统的正常运行。
- 自我保护机制: Eureka还具有自我保护机制。当Eureka Server节点在一定时间内没有接收到心跳时,它会进入自我保护模式。在自我保护模式下,Eureka Server不再剔除注册表中的服务实例,以保护现有的注册信息。这样可以防止由于网络抖动或其他原因导致的误剔除,进一步提高系统的稳定性。
eureka自我保护机制是什么?
什么是自我保护模式?
- 自我保护的条件:一般情况下,微服务在 Eureka 上注册后,会每 30 秒发送心跳包,Eureka 通过心跳来判断服务是否健康,同时会定期删除超过 90 秒没有发送心跳服务。
- 有两种情况会导致 Eureka Server 收不到微服务的心跳
- 是微服务自身的原因
- 是微服务与 Eureka 之间的网络故障
通常(微服务的自身的故障关闭)只会导致个别服务出现故障,一般不会出现大面积故障,而(网络故障)通常会导致 Eureka Server 在短时间内无法收到大批心跳。考虑到这个区别,Eureka 设置了一个阀值,当判断挂掉的服务的数量超过阀值时,Eureka Server 认为很大程度上出现了网络故障,将不再删除心跳过期的服务。
- 那么这个阀值是多少呢?
15 分钟之内是否低于 85%;Eureka Server 在运行期间,会统计心跳失败的比例在 15 分钟内是否低于 85%,这种算法叫做 Eureka Server 的自我保护模式。
为什么要自我保护?
- 因为同时保留"好数据"与"坏数据"总比丢掉任何数据要更好,当网络故障恢复后,这个 Eureka 节点会退出"自我保护模式"。
- Eureka 还有客户端缓存功能(也就是微服务的缓存功能)。即便 Eureka 集群中所有节点都宕机失效,微服务的 Provider 和 Consumer都能正常通信。
- 微服务的负载均衡策略会自动剔除死亡的微服务节点。
Consul是什么?
Consul 是 HasiCorp 公司用 Golang 开发的一款开源的服务注册中心以及配置中心,提供了服务注册与发现、健康检查、KV 存储、多数据中心支持、DNS 和 HTTP API 接口等功能,而且提供了可视化控制台用于操作。
Consul 的优点有很多
- 基于 Raft 协议,比较简洁
- 支持简单检查,同时支持 HTTP 和 DNS 协议
- 支持跨数据中心的 WAN 集群
- 提供了跨平台的图形化界面,支持 Windows、Linux、Mac 等系统
单体服务拆成多个微服务,这些服务之间如何自动发现彼此?具体原理是什么?
这些微服务之间一般需要借助注册中心,然后通过服务发现机制定位彼此。
核心原理是:服务启动时将自己的地址和元数据注册到注册中心(Nacos、Consul),调用方通过注册中心动态获取可用服务实例列表,然后基于负载均衡策略(如轮询、随机)发起请求。

整个过程还得依赖心跳检测确保实例状态实时更新,例如老服务的下线,新服务的上线。
每个微服务启动后,会向注册中心(如Nacos、Consul)发送自己的信息(IP、端口、服务名等),告诉注册中心“我上线了”
注册中心会存储所有已注册服务的信息,并通过心跳检测(如每隔5秒发一次“我还活着”)监控服务状态,若某服务超过一定时间没心跳,注册中心会标记它为“下线”
当服务 A需要调用服务B时,会向注册中心查询服务 B的所有可用实例(IP+端口),然后从这些实例中选一个(如轮询、随机)发起请求。
配置中心
什么是配置中心?有哪些常见的配置中心?
配置中心是一个用于配置集中化管理目支持动态更新、分发配置文件的工具(服务)。
它实现了配置的统一管理和动态同新,当配置信息发生变化时,配置中心可以自动通知服务实例进行配置更新,这样就可以实例无需重启即可应用最新的配置,从一定程度上减少了系统访问的空窗期,非常灵活方便
常见的配置中心:
- Spring Cloud Config:Spring 提供的分布式配置管理工具,支持从 Git、SVN 等版本控制系统加载配置
- Apollo:由携程开源的配置管理中心,支持配置的实时推送和权限管理。
- Nacos:阿里巴巴的配置管理和服务发现工具,既支持配置中心功能,又能作为注册中心使用。
- Consul:HashiCorp 提供的分布式系统管理工具,既可以用作服务发现,也可以用于存储和分发配置
- Etcd:分布式键值存储工具,常用于 Kubernetes 集群中的配置管理。
- Zookeeper:Zookeeper 是一个开源的分布式协调服务,和 Nacos 一样,其既可以作为注册中心,又可以作为配置中心。
为什么微服务需要配置中心?
微服务架构中的每个服务通常都需要一些配置信息,例如数据库连接地址、服务端口、日志级别等。这些配置可能因为不同环境、不同部署实例或者动态运行时需要进行调整和管理。
微服务的实例一般非常多,如果每个实例都需要一个个地去做这些配置,那么运维成本将会非常大,这时候就需要一个集中化的配置中心,去管理这些配置。
SpringCloud可以选择哪些配置中心?
和注册中心一样,SpringCloud也支持对多种配置中心的集成。常见的配置中心选型包括:
- Spring Cloud Config:官方推荐的配置中心,支持将配置文件存储在Git、SVN等版本控制系统中,并提供RESTful API进行访问和管理。
- ZooKeeper:一个开源的分布式协调服务,可以用作配置中心。它具有高可用性、一致性和通知机制等特性。
- Consul:另一个开源的分布式服务发现和配置管理工具,也可用作配置中心。支持多种配置文件格式,提供健康检查、故障转移和动态变更等功能。
- Etcd:一个分布式键值存储系统,可用作配置中心。它使用基于Raft算法的一致性机制,提供分布式数据一致性保证。
- Apollo:携程开源的配置中心,支持多种语言和框架。提供细粒度的配置权限管理、配置变更通知和灰度发布等高级特性,还有可视化的配置管理界面。
- Nacos:阿里巴巴开源的服务发现、配置管理和服务管理平台,也可以作为配置中心使用。支持服务注册与发现、动态配置管理、服务健康监测和动态DNS服务等功能。
Nacos配置中心的原理了解吗?
配置中心,说白了就是一句话:配置信息的CRUD。

具体的实现大概可以分成这么几个部分:
- 配置信息存储:Nacos默认使用内嵌数据库Derby来存储配置信息,还可以采用MySQL等关系型数据库。
- 注册配置信息:服务启动时,Nacos Client会向Nacos Server注册自己的配置信息,这个注册过程就是把配置信息写入存储,并生成版本号。
- 获取配置信息:服务运行期间,Nacos Client通过API从Nacos Server获取配置信息。Server根据键查找对应的配置信息,并返回给Client。
- 监听配置变化:Nacos Client可以通过注册监听器的方式,实现对配置信息的监听。当配置信息发生变化时,Nacos Server会通知已注册的监听器,并触发相应的回调方法。
Nacos配置中心长轮询机制?
一般来说客户端和服务端的交互分为两种:推(Push)和拉(Pull),Nacos在Pull的基础上,采用了长轮询来进行配置的动态刷新。 详情可以看这篇文章Nacos交互模型
在长轮询模式下,客户端定时向服务端发起请求,检查配置信息是否发生变更。如果没有变更,服务端会"hold"住这个请求,即暂时不返回结果,直到配置发生变化或达到一定的超时时间。
具体的实现过程如下:


如果客户端发起 Pull 请求,服务端收到请求之后,先检查配置是否发生了变更:
- 变更:返回变更配置;
- 无变更:设置一个定时任务,延期 29.5s 执行,把当前的客户端长轮询连接加入 allSubs 队列;
在这 29.5s 内的配置变化:
- 配置无变化:等待 29.5s 后触发自动检查机制,返回配置;
- 配置变化:在 29.5s 内任意一个时刻配置变化,会触发一个事件机制,监听到该事件的任务会遍历 allSubs 队列,找到发生变更的配置项对应的 ClientLongPolling 任务,将变更的数据通过该任务中的连接进行返回。相当于完成了一次 PUSH 操作;
长轮询机制结合了 Pull 机制和 Push 机制的优点; 通过长轮询的方式,Nacos客户端能够实时感知配置的变化,并及时获取最新的配置信息。同时,这种方式也降低了服务端的压力,避免了大量的长连接占用内存资源。
Nacos的服务注册表结构是怎样的?
Nacos采用了数据的分级存储模型,最外层是Namespace,用来隔离环境。然后是Group,用来对服务分组。接下来就是服务(Service)了,一个服务包含多个实例,但是可能处于不同机房,因此Service下有多个集群(Cluster),Cluster下是不同的实例(Instance)。
对应到Java代码中,Nacos采用了一个多层的Map来表示。结构为Map<String, Map<String, Service>>,其中最外层Map的key就是namespaceId,值是一个Map。内层Map的key是group拼接serviceName,值是Service对象。Service对象内部又是一个Map,key是集群名称,值是Cluster对象。而Cluster对象内部维护了Instance的集合。
Nacos中的Namespace是什么?如何使用它来组织和管理微服务
Nacos中的Namespace是用于隔离不同环境或应用之间的配置和服务信息的概念。通过使用Namespace,可以将不同的环境(例如开发、测试和生产)或不同的应用程序(例如Web应用和移动应用)的配置和服务信息分离开来,以避免冲突和错误。
在Nacos中,每个Namespace都有自己独立的配置和服务注册表。这意味着,如果有多个应用程序需要使用Nacos,可以将它们分别放置在不同的Namespace中。每个Namespace都有自己的命名空间ID,用于标识该Namespace。要使用Namespace,在Nacos客户端初始化时,需要指定要使用的Namespace ID。
通过使用Namespace,可以对不同Namespace下的服务进行分组和管理,例如可以使用Nacos提供的Group功能对同一Namespace下的服务进行分组,方便管理和查找。同时,使用Namespace还可以对不同环境下的配置进行隔离,避免不同环境之间的配置冲突。
SpringCloud Config 是什么?
SpringCloud Config 为分布式系统外部化配置提供了服务端以及客户端的支持,简单来说就是一个配置中心,其主要包括以下两个部分的内容:Config Sever和 Config Cient 。
- ConfigServer是一个可横向扩展,并且集中式配置的服务器,主要用于集中管理服务各种环境下的配置,然后默认使用 Git进行存储配置的内容,因此可以很方便地实现配置的版本控制
- Config Client 是 Config Server 的客户端,主要用于操作存储在 Config Server 中的配置信息。
远程调用
说说微服务之间是如何独立通讯的?
远程过程调用(Remote Procedure Invocation)
也就是我们常说的服务的注册与发现,直接通过远程过程调用来访问别的service。
优点:简单,常见,因为没有中间件代理,系统更简单
缺点:只支持请求/响应的模式,不支持别的,比如通知、请求/异步响应、发布/订阅、发布/异步响应,降低了可用性,因为客户端和服务端在请求过程中必须都是可用的。
消息
使用异步消息来做服务间通信。服务间通过消息管道来交换消息,从而通信。
优点:把客户端和服务端解耦,更松耦合,提高可用性,因为消息中间件缓存了消息,直到消费者可以消费, 支持很多通信机制比如通知、请求/异步响应、发布/订阅、发布/异步响应。
缺点:消息中间件有额外的复杂。
说说 RPC 的实现原理
首先需要有处理网络连接通讯的模块,负责连接建立、管理和消息的传输。其次需要有编 解码的模块,因为网络通讯都是传输的字节码,需要将我们使用的对象序列化和反序列化。剩下的就是客户端和服务器端的部分,服务器端暴露要开放的服务接口,客户调用服 务接口的一个代理实现,这个代理实现负责收集数据、编码并传输给服务器然后等待结果返回。
能说下HTTP和RPC的区别吗?
严格来讲,HTTP和RPC不是一个层面的东西:
- HTTP(Hypertext Transfer Protocol)是一种应用层协议,主要强调的是网络通信;
- RPC(Remote Procedure Call,远程过程调用)是一种用于分布式系统之间通信的协议,强调的是服务之间的远程调用。
一些RPC框架比如gRPC,底层传输协议其实也是用的HTTP2,包括Dubbo3,也兼容了gRPC,使用了HTTP2作为传输层的一层协议。
如果硬要说区别的话,如下:
| HTTP | RPC | |
|---|---|---|
| 定义 | HTTP(超文本传输协议)是一种用于传输超文本的协议。 | RPC(远程过程调用)是一种用于实现分布式系统中不同节点之间通信的协议。 |
| 通信方式 | 基于请求-响应模型,客户端发送请求,服务器返回响应。 | 基于方法调用模型,客户端调用远程方法并等待结果。 |
| 传输协议 | 基于TCP协议,可使用其他传输层协议如TLS/SSL进行安全加密。 | 可以使用多种传输协议,如TCP、UDP等。 |
| 数据格式 | 基于文本,常用的数据格式有JSON、XML等。 | 可以使用各种数据格式,如二进制、JSON、Protocol Buffers等。 |
| 接口定义 | 使用RESTful风格的接口进行定义,常用的方法有GET、POST、PUT、DELETE等。 | 使用IDL(接口定义语言)进行接口定义,如Protocol Buffers、Thrift等。 |
| 跨语言性 | 支持跨语言通信,可以使用HTTP作为通信协议实现不同语言之间的通信。 | 支持跨语言通信,可以使用IDL生成不同语言的客户端和服务端代码。 |
| 灵活性 | 更加灵活,适用于不同类型的应用场景,如Web开发、API调用等。 | 更加高效,适用于需要高性能和低延迟的分布式系统。 |
在微服务体系里,基于HTTP风格的远程调用通常使用框架如Feign来实现,基于RPC的远程调用通常使用框架如Dubbo来实现。
那Feign和Dubbo的区别呢?
这两个才是适合拿来比较的东西:
| Feign | Dubbo | |
|---|---|---|
| 定义 | Feign是一个声明式的Web服务客户端,用于简化HTTP API的调用。 | Dubbo是一个分布式服务框架,用于构建面向服务的微服务架构。 |
| 通信方式 | 基于HTTP协议,使用RESTful风格的接口进行定义和调用。 | 基于RPC协议,支持多种序列化协议如gRPC、Hessian等。 |
| 服务发现 | 通常结合服务注册中心(如Eureka、Consul)进行服务发现和负载均衡。 | 通过ZooKeeper、Nacos等进行服务注册和发现,并提供负载均衡功能。 |
| 服务治理 | 不直接提供服务治理功能,需要结合其他组件或框架进行服务治理。 | 提供服务注册与发现、负载均衡、容错机制、服务降级等服务治理功能。 |
| 跨语言性 | 支持跨语言通信,可以使用HTTP作为通信协议实现不同语言之间的通信。 | 支持跨语言通信,通过Dubbo的IDL生成不同语言的客户端和服务端代码。 |
| 生态系统 | 集成了Spring Cloud生态系统,与Spring Boot无缝集成。 | 拥有完整的生态系统,包括注册中心、配置中心、监控中心等组件。 |
| 适用场景 | 适用于构建RESTful风格的微服务架构,特别适合基于HTTP的微服务调用。 | 适用于构建面向服务的微服务架构,提供更全面的服务治理和容错机制。 |
需要注意的是,Feign和Dubbo并不是互斥的关系。实际上,Dubbo可以使用HTTP协议作为通信方式,而Feign也可以集成RPC协议进行远程调用。选择使用哪种远程调用方式取决于具体的业务需求和技术栈的选择。
负载均衡的意义什么?
在计算中,负载均衡可以改善跨计算机,计算机集群,网络链接,中央处理单元或磁盘驱动器等多种计算资源的工作负载分布。
负载均衡旨在优化资源使用,最大化吞吐量,最小化响应时间并避免任何单一资源 的过载。使用多个组件进行负载均衡可而不是单个组件可能会通过冗余来提高可靠性和可用性。负载均衡可通常涉及专用软件或硬件,例如多层交换机或域名系统服务器进程。
集中式与进程内负载均衡的区别
目前业界主流的负载均衡方案可分成两类:
- 集中式负载均衡, 即在 consumer 和 provider 之间使用独立的负载均衡设施(可以是硬件,如F5, 也可以是软件,如 Nginx), 由该设施负责把 访问请求 通过某种策略转发至 provider;
- 进程内负载均衡,将负载均衡逻辑集成到 consumer,consumer 从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的 provider。Ribbon 就属于后者,它只是一个类库,集成于 consumer 进程,consumer 通过它来获取到 provider 的地址。

说说有哪些负载均衡算法?
常见的负载均衡算法包含以下几种:
| 内置负载均衡规则类 | 规则描述 |
|---|---|
| RoundRobinRule | 简单轮询服务列表来选择服务器。它是Ribbon默认的负载均衡规则。 |
| AvailabilityFilteringRule | 对以下两种服务器进行忽略: (1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级地增加。 (2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上限,可以由客户端的 <clientName>.<clientConfigNameSpace>.ActiveConnectionsLimit属性进行配置。 |
| WeightedResponseTimeRule | 为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。 |
| ZoneAvoidanceRule | 以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。而后再对Zone内的多个服务做轮询。 |
| BestAvailableRule | 忽略那些短路的服务器,并选择并发数较低的服务器。 |
| RandomRule | 随机选择一个可用的服务器。 |
| RetryRule | 重试机制的选择逻辑 |
- 轮询算法(Round Robin):轮询算法是最简单的负载均衡算法之一。它按照顺序将请求依次分配给每个后端服务器,循环往复。当请求到达时,负载均衡器按照事先定义的顺序选择下一个服务器。轮询算法适用于后端服务器具有相同的处理能力和性能的场景。
- 加权轮询算法(Weighted Round Robin):加权轮询算法在轮询算法的基础上增加了权重的概念。每个后端服务器都被赋予一个权重值,权重值越高,被选中的概率就越大。这样可以根据服务器的处理能力和性能调整请求的分配比例,使得性能较高的服务器能够处理更多的请求。
- 随机算法(Random):随机算法将请求随机分配给后端服务器。每个后端服务器有相等的被选中概率,没有考虑服务器的实际负载情况。这种算法简单快速,适用于后端服务器性能相近且无需考虑请求处理能力的场景。
- 加权随机算法(Weighted Random):加权随机算法在随机算法的基础上引入了权重的概念。每个后端服务器被赋予一个权重值,权重值越高,被选中的概率就越大。这样可以根据服务器的处理能力和性能调整请求的分配比例。
- 最少连接算法(Least Connection):最少连接算法会根据后端服务器当前的连接数来决定请求的分配。负载均衡器会选择当前连接数最少的服务器进行请求分配,以保证后端服务器的负载均衡。这种算法适用于后端服务器的处理能力不同或者请求的处理时间不同的场景。
- 哈希算法(Hash):哈希算法会根据请求的某个特定属性(如客户端IP地址、请求URL等)计算哈希值,然后根据哈希值选择相应的后端服务器。
常见的负载均衡器,比如Ribbion、Gateway等等,基本都支持这些负载均衡算法。
可以用几行代码实现一个负载均衡器吗?
不要题目吓到,这类题目不会让你实现一个完整的可以运行的系统,仅用几行代码突出其核心思想即可
可以,例如可以用常见的轮询(Round Robin)的方式来分发请求。核心就是维护一个服务器列表和当前下标,每次请求返回一个不同的服务器
List<String> servers = List.of("A", "B", "C");
AtomicInteger index = new AtomicInteger(0);
public String getServer() {
return servers.get(index.getAndIncrement() % servers.size());
}Atomiclnteger 用来保证在多线程环境下也能安全地自增,不会出现重复或跳号的情况。
轮询的优点是实现简单、平均分配,缺点是不考虑服务器实际负载,所有机器一视同仁。
什么是Ribbon?
ribbon是一个负载均衡客户端,可以很好地控制htt和tcp的一些行为。feign默认集成了ribbon。
什么是 Feign?它的优点是什么?
Feign 是一个声明式的Web服务客户端。
所谓的声明式就是指不需要编写复杂的关于 Http 请求的东西。只需要声明一个一个接口,然后在这个接口上添加一些注解,这些注解包括了请求的方法(如GET和POST)、请求的URL等信息
Feign 在运行时通过注解和接口上定义的内容来动态构造和发送 Http 请求。所以使用 Feign,开发者只需要定义服务接口并通过注解指明服务名和参数等信息,Feign 就能自动完成 Http 请求的构建、发送和结果处理
Feign 也是 Spring Cloud Netflix 组件之一,结合Spring Cloud 的服务注册和发现、负载均衡等功能,能够让服务间的调用变得更加方便
Feign 的主要特点有:
- 声明式的服务客户端,通过 Java 接口和注解构建服务客户端,简化了 Http 调用的使用过程,无需手动构建 HTTP 请求
- 很好地融入了 SpringCloud 生态,可以使用 SpringCloud负载均衡、服务熔断等能力
使用方式
- 添加pom依赖。
- 启动类添加
@EnableFeignClients - 定义一个接口
@FeignClient(name=“xxx”)指定调用哪个服务
Ribbon和Feign的区别?
- 启动类注解不同,Ribbon是@RibbonClient feign的是@EnableFeignClients;
- 服务指定的位置不同,Ribbon是在@RibbonClient注解上声明,Feign则是在定义抽象方法的接口中使用@FeignClient声明;
- 调用方式不同,Ribbon需要自己构建http请求,模拟http请求。
Ribbon是一个客户端负载均衡器,作用在于多个微服务实例间分发请求,提升可用性和性能。它可与各种HTTP客户端如RestTemplate配合使用来发送HTTP请求并进行负载均衡。
Feign则是一个声明式的HTTP客户端,通过编写接口来定义对远程微服务的需求。Feign使用注解和模板方法简化了远程调用的编写,使得调用远程服务的代码更加清晰和简洁。它更注重简洁的声明式编程模型,你只需编写接口并使用注解描述HTTP请求,Feign会在运行时生成实现类来执行实际的HTTP请求。
Ribbon更注重负载均衡,需要配合其他库如RestTemplate来发送http请求,而Feign则采用声明式编程模型,只需编写接口和注解即可。此外,Ribbon提供了自定义负载均衡策略的能力,而Feign通常与Ribbon一起使用以实现负载均衡。
为什么Feign第一次调用耗时很长?
主要原因是由于Ribbon的懒加载机制,当第一次调用发生时,Feign会触发Ribbon的加载过程,包括从服务注册中心获取服务列表、建立连接池等操作,这个加载过程会增加首次调用的耗时。
ribbon:
eager-load:
enabled: true
clients: service-1那怎么解决这个问题呢?
可以在应用启动时预热Feign客户端,自动触发一次无关紧要的调用,来提前加载Ribbon和其他相关组件。这样,就相当于提前进行了第一次调用。
Feign怎么实现认证传递?
比较常见的一个做法是,使用拦截器传递认证信息。可以通过实现RequestInterceptor接口来定义拦截器,在拦截器里,把认证信息添加到请求头中,然后将其注册到Feign的配置中。
@Configuration
public class FeignClientConfig {
@Bean
public RequestInterceptor requestInterceptor() {
return new RequestInterceptor() {
@Override
public void apply(RequestTemplate template) {
// 添加认证信息到请求头中
template.header("Authorization", "Bearer " + getToken());
}
};
}
private String getToken() {
// 获取认证信息的逻辑,可以从SecurityContext或其他地方获取
// 返回认证信息的字符串形式
return "your_token";
}
}Fegin怎么做负载均衡?Ribbon?
在Feign中,负载均衡是通过集成Ribbon来实现的。
Ribbon是Netflix开源的一个客户端负载均衡器,可以与Feign无缝集成,为Feign提供负载均衡的能力。
Ribbon在发起请求前,会从“服务中心”获取服务列表(清单),然后按照一定的负载均衡策略去发起请求,从而实现客户端的负载均衡。Ribbon本身也维护着“服务提供者”清单的有效性。如果它发现“服务提供者”不可用,则会重新从“服务中心”获取有效的“服务提供者”清单来及时更新。

Feign 和 OpenFeign 的区别?
Feign 和 OpenFeign 都是用于简化服务之间的 HTTP 调用的工具,让我们可以更加方便地实现服务间的通信
Feign 最初是由 Netfix 开发的一个声明式, REST 客户端框架,它的目标是让微服务之间的调用像调用本地方法一样容易。如果我们想调用其它服务的接口,可以创建一个接口,然后通过注解声明所需要调用服务的方法和路径,Feign 可以自动发送 Http 请求和接收响应,转换为方法返回值
而 OpenFeign 是 Spring Cloud在 Feign 的基础上进一步封装的,它整合了 Spring Cloud 的特性,使得我们可以更加简单地使用 Feign,包括如下几个方面:
- 自动配置:Openfeign利用Spring Boot的自动配置机制,通过@FeignClien和@EnableFeignClients 注解就可以创建一个 Feign 客户端,极大简化了Feign客户端的创建和配置过程。
- 负载均衡:与Spring Cloud等服务发现组件集成,可以轻松实现客户端负载均衡
- Hystrix集成:只需要简单的配置就可以快速集成Hystrix,提高系统的容错性
服务容灾
什么是熔断器?为什么需要熔断器?
在微服务架构中,服务之间的调用关系会形成调用链路,链路中的任何一个服务都可能出现超时或者宕机的情况,而在微服务系统中,如果调用失败的话可能会引起大面积的服务瘫痪,即形成“服务雪崩”的情况,这样的话对于服务的影响是巨大的。
熔断器就是为了来解决这个问题,避免服务雪崩情况的发生。
熔断器的基本原理如下:
- 正常情况下,熔断器处于关闭状态,服务消费者正常请求微服务中的服务提供者。
- 当发生了服务调用清求失败的时候,并且达到了一定比例,比如70% 的清求发生了失败,或者失败的清求次数达到了10等等,这个时候熔断器打开,此时将服务调用者不再发起服务调用请求,这种方法是一种快速失败的方法,也称为熔断方法。
- 熔断器启用一段时间时候,自动进入“半关闭状态”,这个时候熔断器允许服务调用者发起一个请求给服务提供者,如果请求调用成功了,关闭熔断器,反之继续打开熔断器,循环往复。
这种方式在服务发生意外的时候,可以实现服务错误的隔离,避免了服务错误导致了系统的整体不可用,这样保证了系统即使出现了局部问题也不会发生服务雪崩的情况。
什么是服务雪崩?
在微服务中,假如一个或者多个服务出现故障,如果这时候,依赖的服务还在不断发起请求,或者重试,那么这些请求的压力会不断在下游堆积,导致下游服务的负载急剧增加。不断累计之下,可能会导致故障的进一步加剧,可能会导致级联式的失败,甚至导致整个系统崩溃,这就叫服务雪崩。
一般,为了防止服务雪崩,可以采用这些措施:
- 服务高可用部署:确保各个服务都具备高可用性,通过冗余部署、故障转移等方式来减少单点故障的影响。
- 限流和熔断:对服务之间的请求进行限流和熔断,以防止过多的请求涌入导致后端服务不可用。
- 缓存和降级:合理使用缓存来减轻后端服务的负载压力,并在必要时进行服务降级,保证核心功能的可用性。
什么是服务熔断?
熔断机制是应对雪崩效应的一种微服务链路保护机制。当某个微服务不可用或者响应时间太长时,会进行服务降级,进而熔断该节点微服务的调用,快速返回“错误”的响应信息。当检测到该节点微服务调用响应正常后恢复调用链路。在Spring Cloud框架里熔断机制通过Hystrix实现,Hystrix会监控微服务间调用的状况,当失败的调用到一定阈值,缺省是5秒内调用20次,如果失败,就会启动熔断机制。
什么是服务降级?
服务降级,一般是从整体负荷考虑。当系统出现异常情况时,服务降级会主动屏蔽一些非核心或可选的功能,而只提供最基本的功能,以确保系统的稳定运行。通过减少对资源的依赖,服务降级可以保证系统的可用性和性能。 它可以根据业务需求和系统状况来制定策略,例如替换耗时操作、返回默认响应、返回静态错误页面等。
Hystrix相关注解@EnableHystrix:开启熔断 @HystrixCommand(fallbackMethod=”XXX”),声明一个失败回滚处理函数XXX,当被注解的方法执行超时(默认是1000毫秒),就会执行fallback函数,返回错误提示。
什么是服务限流?
服务限流是一种流量控制策略,它通过限制每秒请求的数量(QPS)、请求频率、并发数等,来保护服务的处理能力,防止系统因为流量过大而出现性能问题或资源耗尽服务限流可以认为是服务降级的一种,限流就是通过限制系统清求的输入和输出,从而实现对于系统的保护,这个和降级的概念很像,都是为了保证核心功能的正常运行。限流是因为服务的吞吐量以及负载这些都是可以预估的,我们为了保证系统的正常运行,可以设置限制的國值,即涌过限制输入或者输出的方式来减少流量的流通,然后实现对于系统的保护限流有很多种实现方案,比如我们说的限流算法、延迟解决、拒绝解决等等,保证请求的范围在系统可以接受的阈值以内,实现对系统的保护。
有哪些熔断降级方案实现?
目前常见的服务熔断降级实现方案有这么几种:
| 框架 | 实现方案 | 特点 |
|---|---|---|
| Spring Cloud | Netflix Hystrix | 提供线程隔离、服务降级、请求缓存、请求合并等功能; 可与Spring Cloud其他组件无缝集成 官方已宣布停止维护,推荐使用Resilience4j代替 |
| Spring Cloud | Resilience4j | 轻量级服务熔断库 提供类似于Hystrix的功能 - 具有更好的性能和更简洁的API 可与Spring Cloud其他组件无缝集成 |
| Spring Cloud Alibaba | Sentinel | 阿里巴巴开源的流量控制和熔断降级组件 提供实时监控、流量控制、熔断降级等功能 与Spring Cloud Alibaba生态系统紧密集成 |
| Dubbo | Dubbo自带熔断降级机制 | Dubbo框架本身提供的熔断降级机制 可通过配置实现服务熔断和降级 与Dubbo的RPC框架紧密集成 |
什么是Hystrix?
Hystrix是一个延迟和容错库,旨在隔离远程系统,服务和第三方库的访问点,当出现故障是不可避免的故障时,停止级联故障并在复杂的分布式系统中实现弹性。
通常对于使用微服务架构开发的系统,涉及到许多微服务。这些微服务彼此协作。
思考一下微服务:

假设如果上图中的微服务9失败了,那么使用传统方法我们将传播一个异常。但这仍然会导致整个系统崩溃。
随着微服务数量的增加,这个问题变得更加复杂。微服务的数量可以高达1000.这是hystrix出现的地方 我们将使用Hystrix在这种情况下的Fallback方法功能。我们有两个服务employee-consumer使用由employee-consumer公开的服务。
简化图如下所示

现在假设由于某种原因,employee-producer公开的服务会抛出异常。我们在这种情况下使用Hystrix定义了一个回退方法。这种后备方法应该具有与公开服务相同的返回类型。如果暴露服务中出现异常,则回退方法将返回一些值。
Hystrix如何实现容错?
尽管已经不再更新,但是Hystrix是非常经典的服务容错开源库,它提供了多种机制来保护系统,Hystrix服务容错六大机制:
- 服务熔断(Circuit Breaker):Hystrix通过设置阈值来监控服务的错误率或响应时间。当错误率或响应时间超过预设的阈值时,熔断器将会打开,后续的请求将不再发送到实际的服务提供方,而是返回预设的默认值或错误信息。这样可以快速隔离故障服务,防止故障扩散,提高系统的稳定性和可用性。
- 服务降级(Fallback):当服务熔断打开时,Hystrix可以提供一个备用的降级方法或返回默认值,以保证系统继续正常运行。开发者可以定义降级逻辑,例如返回缓存数据、执行简化的逻辑或调用其他可靠的服务,以提供有限但可用的功能。
- 请求缓存(Request Caching):Hystrix可以缓存对同一请求的响应结果,当下次请求相同的数据时,直接从缓存中获取,避免重复的网络请求,提高系统的性能和响应速度。
- 请求合并(Request Collapsing):Hystrix可 以将多个并发的请求合并为一个批量请求,减少网络开销和资源占用。这对于一些高并发的场景可以有效地减少请求次数,提高系统的性能。
- 实时监控和度量(Real-time Monitoring and Metrics):Hystrix提供了实时监控和度量功能,可以对服务的执行情况进行监控和统计,包括错误率、响应时间、并发量等指标。通过监控数据,可以及时发现和解决服务故障或性能问题。
- 线程池隔离(Thread Pool Isolation):Hystrix将每个依赖服务的请求都放在独立的线程池中执行,避免因某个服务的故障导致整个系统的线程资源耗尽。通过线程池隔离,可以提高系统的稳定性和可用性。
说下Hystrix与Sentinel的区别
Hystrix和Sentinel都是服务熔断器,用于提高分布式系统的弹性。它们的主要区别在于实现方式、适用场景和资源模型设计。
Hystrix基于命令模式设计,将外部资源的调用封装在命令对象中,通过线程池或信号量来实现隔离。它提供了丰富的配置选项,如线程池大小、超时时间等,以实现对系统资源的有力控制。Hystrix更适用于需要高并发、快速响应的场景,因为它可以快速隔离和恢复故障。
Sentinel则基于流量控制和熔断降级的思想,可以与Spring Cloud、gRPC、Dubbo等框架集成。它通过定义资源规则和应用策略来实现对系统资源的控制。Sentinel更适用于需要流量控制和熔断降级的场景,它可以根据系统负载和响应时间来实现自动熔断和降级操作。
总之,Hystrix和Sentinel都是服务熔断器,用于提高系统的弹性。它们在实现方式、适用场景和资源模型设计等方面存在一些不同。具体选择哪个工具取决于系统的具体需求和场景。
Sentinel采用的什么限流算法?
Sentinel使用滑动窗口限流算法来实现限流。
滑动窗口限流算法是一种基于时间窗口的限流算法。它将一段时间划分为多个时间窗口,并在每个时间窗口内统计请求的数量。通过动态地调整时间窗口的大小和滑动步长,可以更精确地控制请求的通过速率。
Sentinel是怎么实现限流的?
首先需要定义具体需要限流的资源,然后指定一定的规则(基于QPS(每秒查询数)、线程数等维度),限制资源的访问频次。然后根据一定的限流算法(固定窗口、滑动窗口、令牌桶和漏桶),对指定的资源进行访问的流量控制。具体流程如下:
- 当一个请求进入系统时,Sentinel 会首先对请求进行统计(如当前的 QPS、并发数)
- 接着 Sentine| 检查配置的限流规则,如果当前请求的速率超过了设定的限流阈值,Sentinel 将触发限流措施
- 对于被限流的请求,可以选择直接拒绝、排队等待、或返回降级响应等方式来处理,保证系统核心功能的稳定
Sentinel怎么实现集群限流?
Sentinel利用了Token Server和Token Client的机制来实现集群限流。
开启集群限流后,Client向Token Server发送请求,Token Server根据配置的规则决定是否限流。

服务网关
在微服务架构中,网关的作用是什么
在微服务架构中,网关(Gateway)具有以下作用:
- 统一入口:网关为所有的微服务提供一个唯一的入口点,从而简化了客户端与服务的交互,同时保障了后台服务的安全性。
- 鉴权校验:网关能够识别每个进来的请求,并根据其权限进行校验,阻止不符合要求的请求通过。
- 动态路由:根据需要,网关可以动态地将请求路由到不同的后端集群中,实现服务的灵活调度。
- 降低耦合度:通过在网关层做映射,可以将客户端与服务解耦,使服务可以独立发展,减少两者之间的依赖。
- 提供附加功能:网关不仅可以保护微服务,还可以为服务提供和沉淀更多附加功能,如熔断、限流等。
什么是API网关?
API网关(API Gateway)是一种中间层服务器,用于集中管理、保护和路由对后端服务的访问。它充当了客户端与后端服务之间的入口点,提供了一组统一的接口来管理和控制API的访问。
API网关的主要功能包括:
- 路由转发:API网关根据请求的URL路径或其他标识,将请求路由到相应的后端服务。通过配置路由规则,可以灵活地将请求分发给不同的后端服务。
- 负载均衡:API网关可以在后端服务之间实现负载均衡,将请求平均分发到多个实例上,提高系统的吞吐量和可扩展性。
- 安全认证与授权:API网关可以集中处理身份验证和授权,确保只有经过身份验证的客户端才能访问后端服务。它可以与身份提供者(如OAuth、OpenID Connect)集成,进行用户认证和授权操作。
- 缓存:API网关可以缓存后端服务的响应,减少对后端服务的请求次数,提高系统性能和响应速度。
- 监控与日志:API网关可以收集和记录请求的指标和日志,提供实时监控和分析,帮助开发人员和运维人员进行故障排查和性能优化。
- 数据转换与协议转换:API网关可以在客户端和后端服务之间进行数据格式转换和协议转换,如将请求从HTTP转换为WebSocket,或将请求的参数进行格式转换,以满足后端服务的需求。
- API版本管理:API网关可以管理不同版本的API,允许同时存在多个API版本,并通过路由规则将请求正确地路由到相应的API版本上。
……
通过使用API网关,可以简化前端与后端服务的交互,提供统一的接口和安全性保障,同时也方便了服务治理和监控。它是构建微服务架构和实现API管理的重要组件之一。
SpringCloud可以选择哪些API网关?
使用SpringCloud开发,可以采用以下的API网关选型:
- Netflix Zuul(已停止更新):Netflix Zuul是Spring Cloud早期版本中提供的默认API网关。它基于Servlet技术栈,可以进行路由、过滤、负载均衡等功能。然而,自2020年12月起,Netflix宣布停止对Zuul 1的维护,转而支持新的API网关项目。
- Spring Cloud Gateway:Spring Cloud Gateway是Spring Cloud官方推荐的API网关,取代了Netflix Zuul。它基于非阻塞的WebFlux框架,充分利用了响应式编程的优势,并提供了路由、过滤、断路器、限流等特性。Spring Cloud Gateway还支持与Spring Cloud的其他组件集成,如服务发现、负载均衡等。
- Kong:Kong是一个独立的、云原生的API网关和服务管理平台,可以与Spring Cloud集成。Kong基于Nginx,提供了强大的路由、认证、授权、监控和扩展能力。它支持多种插件和扩展,可满足不同的API管理需求。
- APISIX:APISIX基于Nginx和Lua开发,它具有强大的路由、流量控制、插件扩展等功能。APISIX支持灵活的配置方式,可以根据需求进行动态路由、负载均衡和限流等操作。
说说你对Spring Cloud Gateway的理解
Spring Cloud Gateway是Spring Cloud官方推出的第二代网关框架,取代Zuul 1.0网关。网关作为流量的,在微服务系统中有着非常作用,网关常见的功能有路由转发、权限校验、限流控制等作用。
使用了一个RouteLocatorBuilder的bean去创建路由,除了创建路由RouteLocatorBuilder可以让你添加各种predicates和filters,predicates断言的意思,顾名思义就是根据具体的请求的规则,由具体的route去处理,filters是各种过滤器,用来对请求做各种判断和修改。
Spring Cloud Gateway核心概念?

在Spring Cloud Gateway里,有三个关键组件:
- Route(路由):路由是Spring Cloud Gateway的基本构建块,它定义了请求的匹配规则和转发目标。通过配置路由,可以将请求映射到后端的服务实例或URL上。路由规则可以根据请求的路径、方法、请求头等条件进行匹配,并指定转发的目标URI。
- Predicate(断言):断言用于匹配请求的条件,如果请求满足断言的条件,则会应用所配置的过滤器。Spring Cloud Gateway提供了多种内置的断言,如Path(路径匹配)、Method(请求方法匹配)、Header(请求头匹配)等,同时也支持自定义断言。
- Filter(过滤器):过滤器用于对请求进行处理和转换,可以修改请求、响应以及执行其他自定义逻辑。Spring Cloud Gateway提供了多个内置的过滤器,如请求转发、请求重试、请求限流等。同时也支持自定义过滤器,可以根据需求编写自己的过滤器逻辑。
我们再来看下Spring Cloud Gateway的具体工作流程:

两个比较重要的概念:
- Gateway Handler(网关处理器):网关处理器是Spring Cloud Gateway的核心组件,负责将请求转发到匹配的路由上。它根据路由配置和断言条件进行路由匹配,选择合适的路由进行请求转发。网关处理器还会依次应用配置的过滤器链,对请求进行处理和转换。
- Gateway Filter Chain(网关过滤器链):网关过滤器链由一系列过滤器组成,按照配置的顺序依次执行。每个过滤器可以在请求前、请求后或请求发生错误时进行处理。过滤器链的执行过程可以修改请求、响应以及执行其他自定义逻辑。
什么是限流算法,网关如何实现限流
限流算法是指用于限制单位时间内服务的请求数量的算法,目的是防止服务被过高的请求压力所击垮。常见的限流算法包括计数器算法、滑动窗口算法、漏桶算法、令牌桶算法。
网关如何实现限流:
- 利用限流算法插件/模块:网关可以集成限流算法插件/模块,通过配置相关参数(如令牌桶大小、令牌生成速率等)来实现限流。例如,Spring Cloud Gateway可以使用Redis的RateLimiter限流算法插件来实现限流。
- 自定义限流逻辑:网关可以通过编程方式自定义实现限流逻辑。例如,在微服务架构中,可以在每个服务的网关层(如Nacos、Eureka等)实现限流逻辑,或者使用限流SDK(如Sentinel)对请求进行限流。
- 利用云平台提供的限流功能:一些云平台提供了自动化的限流功能,例如AWS CloudWatch、Azure Application Insights等,网关可以利用这些云平台的功能来实现限流。
你项目里为什么选择 Gateway 作为网关?
选择 Spring Cloud Gateway 的原因主要有两个:
- 以前用得比较多的是 Spring Cloud 官方开源的Zuul,其用得比较多的还是1.0 的版本,不过1.0版本 Netflix很早就宣布进入维护状态了,虽然Zuul已经出了2.0版本,但是 Spring Cloud 官方团队好像没有整合的计划,并且 Netflix 很多相关的组件,如 Eureka、Hystrix 都已经进入维护期了,所以不知道前景如间,然后 Sping doud 官方自己研发了Spring Cloud Gateway,并且大力支持和推荐,所以相比与Zuul, Gateway是一个更好的选择。
- Spring Cloud Gateway 有很多的特性:
- 基于 Spring5和 Spring Boot 2 进行构建,与 Spring 生态兼容较好
- 动态路由:可以根据配置条件,如 URL、请求方法等实现动态配置
- 可以对路由指定断言(Predicate)和过滤器(Filter)
- 集成 Hystrix 断路器功能,可以实现服务熔断
- 集成 Spring Cloud 相关组件,如 Eureka、Nacos、Consule 等实现服务的注册与发现
- 内置了限流模块,可以根据配置实现服务限流
Dubbo和 Spring Cloud Gateway 有什么区别?
Dubbo 是一个RPC(远程过程调用)框架,主要用于服务之间的通信。它提供高性能的 RPC 调用、负载均衡、服务发现、服务注册、服务治理等功能。适用于需要高性能 RPC 调用的分布式系统,常用于内部服务通信。
Spring Cloud Gateway是一个API 网关,用于处理外部客户端请求并将其路由到后端服务。它提供请求路由、负载均衡、协议转换、安全管理、流量控制、日志和监控等功能。适用于微服务架构中的统一入口管理,常用于外部请求的入口层。
所以说它们不是一个层级的东西。
链路追踪
为什么要用微服务链路追踪?
在微服务中,有的上下游可能有十几个服务,如果某一环出了问题,排查起来非常困难,所以,就需要进行链路追踪,来帮助排查问题。
通过链路追踪,可以可视化地追踪请求从一个微服务到另一个微服务的调用情况。除了排查问题,链路追踪黑还可以帮助优化性能,可视化依赖关系、服务监控和告警。
SpringCloud可以选择哪些微服务链路追踪方案?
Spring Cloud提供了多种选择的微服务链路追踪方案。以下是一些常用的方案:
- Zipkin:Zipkin 是一个开源的分布式实时追踪系统,由 Twitter 开发并贡献给开源社区。Spring Cloud Sleuth 提供了与 Zipkin 的集成,可以通过在微服务中添加相应的依赖和配置,将追踪信息发送到 Zipkin 服务器,并通过 Zipkin UI 进行可视化展示和查询。
- Jaeger:Jaeger 是 Uber 开源的分布式追踪系统,也被纳入了 CNCF(云原生计算基金会)的维护。通过使用 Spring Cloud Sleuth 和 Jaeger 客户端库,可以将追踪信息发送到 Jaeger 并进行可视化展示和查询。
- SkyWalking:Apache SkyWalking 是一款开源的应用性能监控与分析系统,提供了对 Java、.NET 和 Node.js 等语言的支持。它可以与 Spring Cloud Sleuth 集成,将追踪数据发送到 SkyWalking 服务器进行可视化展示和分析。
- Pinpoint:Pinpoint 是 Naver 开源的分布式应用性能监控系统,支持 Java 和 .NET。它提供了与 Spring Cloud Sleuth 的集成,可以将追踪数据发送到 Pinpoint 服务器,并通过其 UI 进行分析和监控。
这些方案都可以与 Spring Cloud Sleuth 进行集成,Spring Cloud Sleuth 是 Spring Cloud 中的一个组件,提供了在微服务调用时生成追踪信息的能力。
分布式事务
什么情况下需要用到分布式事务?有哪些方案?
分布式事务是指在多个网络节点或服务之间进行数据一致性处理的情况。以下是一些可能需要使用分布式事务的场景:
- 微服务之间通过远程调用完成事务操作:当不同的微服务之间需要进行数据一致性保证时,就需要使用分布式事务。例如,一个电商微服务中的订单服务和库存服务需要通过远程调用进行事务操作,保证库存数量和订单信息的同步更新,避免出现超卖或缺货的情况。
- 单体系统访问多个数据库实例:当一个系统需要访问多个数据库实例时,例如用户信息和订单信息分别存储在两个不同的数据库实例中,需要通过分布式事务保证数据一致性,避免出现数据不一致的情况。
- 多服务访问同一个数据库实例:当多个服务访问同一个数据库实例时,例如订单微服务和库存微服务都需要访问同一个数据库,也可能需要使用分布式事务。因为跨JVM进程的多个服务同时持有不同的数据库连接进行数据库操作,可能会出现数据不一致的情况。
在这些场景下,我们需要使用分布式事务来保证数据的一致性。常用的分布式事务方案包括两阶段提交(2PC)、三阶段提交(3PC)、TCC、Saga、本地消息表等。其中,两阶段提交和三阶段提交都是基于锁机制实现的,而TCC、Saga和本地消息表则是基于业务逻辑实现的。选择哪种方案取决于业务需求、系统复杂性和性能等多个因素。
详情可以看这篇文章:深度解析分布式事务的七大核心方案
什么是分布式事务的防悬挂,空回滚?
防悬挂是指在分布式事务的第一阶段,防止在没有对应的 Try 操作的情况下出现 Confirm 或 Cancel 操作。这是为了保证事务的正确性和一致性。
分布式事务中最常见的模型是 TCC(Try-Confirm-Cancel)模型。在 TCC 模型中,事务分为三个步骤:
- Try:资源的预留操作。
- Confirm:确认操作,完成业务逻辑
- Cancel:取消操作,回滚预留资源。
防悬挂机制的作用是确保在分布式事务中,Confirm 和 Cancel 操作只会在 Try 操作成功执行后才会触发。
防悬挂的场景通常是以下情况:
- Confirm 操作悬挂:如果 Confirm 操作在没有执行过 Try 操作的情况下被调用,可能会导致数据不一致。
- Cancel 操作悬挂:类似地,如果 Cancel 操作在没有 Try 操作的情况下被调用,也会破坏数据的一致性。
为了防止这种情况,需要通过某些机制来检测和防止悬挂。例如:
- 幂等性检查:Confirm 和 Cancel 操作应该具备幂等性,避免多次调用引发问题。
- 状态校验:在执行 Confirm 或 Cancel之前,可以先检査是否有对应的 Try 操作成功过,如果没有,则拒绝执行 Confirm 或 Cancel 操作
空回滚是指在没有执行成功的Try操作时,Cancel 操作仍然被调用了。Cancel 操作实际上就是 Try操作的回滚操作,如果 Try 操作根本没有成功,则Cancel 操作实际不会对任问资源产生影响,这就是空回滚
空回滚一般发生在分布式系统中的异常情况下,比如:
- 网络超时:Try 操作还没执行成功,网络就超时了,分布式事务协调器可能误认为 Try 操作失败,因此会调用 Cancel。
- 网络分区或中断:Try 操作请求未到达相应的服务端,客户端误认为 Try 操作已经失败并发起 Cancel。
在这些情况下,Cancel 操作会被执行,但因为 Try 操作并没有成功,所以 Cancel 实际上什么都不需要做。这就是空回流,。为了支持空回滚,Cancel操作必须具备以下能力:
- 幂等性:即使 Cancel 操作被多次调用,它的效果也只能是执行一次,不会对系统产生额外影响。
- 空回滚兼容性:Cancel 操作在发现没有Try 操作执行成功时,不做任何修改,直接返回成功状态
什么是Seata?谈谈你对Seata的理解
Seata是一款开源的分布式事务解决方案,它主要用于解决在分布式系统中全局事务的一致性问题。
在分布式系统中,由于一次业务操作需要跨多个数据源或进行远程调用,往往会产生分布式事务问题。例如,在一个电商微服务系统中,订单服务和库存服务需要协同工作,如果订单服务已经创建成功,但库存服务因为某些原因失败了,就会导致数据不一致的问题。Seata就是为解决这个问题而产生的。
Seata的主要特点是无侵入以及高性能。它对业务无侵入,可以减少技术架构上的微服务化所带来的分布式事务问题对业务的侵入,同时高性能则是减少分布式事务解决方案所带来的性能消耗。
在Seata的事务处理中主要有三个重要的角色:事务的协调者(TC)、事务的管理者(TM)和事务的作业管理器(RM)。
- 事务协调者(TC)主要负责管理全局的分支事务的状态,用于全局性事务的提交和回滚。它会对所有的分支事务进行注册,然后根据各个分支事务的状态来决定是否提交或者回滚全局事务。
- 事务管理者(TM)用于开启、提交或回滚事务。它会根据业务逻辑来决定何时开启一个新的事务,并在适当的时候提交或回滚该事务。
- 资源管理器(RM)用于分支事务上的资源管理,向TC注册分支事务,上报分支事务的状态,接收TC的命令来提交或者回滚分支事务。
Seata支持哪些模式的分布式事务?
Seata以下几种模式的分布式事务:
- AT(Atomikos)模式:AT模式是Seata默认支持的模式,也是最常用的模式之一。在AT模式下,Seata通过在业务代码中嵌入事务上下文,实现对分布式事务的管理。Seata会拦截并解析业务代码中的SQL语句,通过对数据库连接进行拦截和代理,实现事务的管理和协调。
- TCC(Try-Confirm-Cancel)模式:TCC模式是一种基于补偿机制的分布式事务模式。在TCC模式中,业务逻辑需要实现Try、Confirm和Cancel三个阶段的操作。Seata通过调用业务代码中的Try、Confirm和Cancel方法,并在每个阶段记录相关的操作日志,来实现分布式事务的一致性。
- SAGA模式:SAGA模式是一种基于事件驱动的分布式事务模式。在SAGA模式中,每个服务都可以发布和订阅事件,通过事件的传递和处理来实现分布式事务的一致性。Seata提供了与SAGA模式兼容的Saga框架,用于管理和协调分布式事务的各个阶段。
- XA模式:XA模式是一种基于两阶段提交(Two-Phase Commit)协议的分布式事务模式。在XA模式中,Seata通过与数据库的XA事务协议进行交互,实现对分布式事务的管理和协调。XA模式需要数据库本身支持XA事务,并且需要在应用程序中配置相应的XA数据源。
了解Seata的实现原理吗?
Seata的实现原理主要包括三个核心组件:事务协调器(Transaction Coordinator)、事务管理器(Transaction Manager)和资源管理器(Resource Manager)。
- 事务协调器(Transaction Coordinator):事务协调器负责协调和管理分布式事务的整个过程。它接收事务的开始和结束请求,并根据事务的状态进行协调和处理。事务协调器还负责记录和管理事务的全局事务 ID(Global Transaction ID)和分支事务 ID(Branch Transaction ID)。
- 事务管理器(Transaction Manager):事务管理器负责全局事务的管理和控制。它协调各个分支事务的提交或回滚,并保证分布式事务的一致性和隔离性。事务管理器还负责与事务协调器进行通信,并将事务的状态变更进行持久化。
- 资源管理器(Resource Manager):资源管理器负责管理和控制各个参与者(Participant)的事务操作。它与事务管理器进行通信,并根据事务管理器的指令执行相应的事务操作,包括提交和回滚。
Seata的实现原理基于两阶段提交(Two-Phase Commit)协议,具体的机制如下:
- 一阶段:在事务提交的过程中,首先进行预提交阶段。事务协调器向各个资源管理器发送预提交请求,资源管理器执行相应的事务操作并返回执行结果。在此阶段,业务数据和回滚日志记录在同一个本地事务中提交,并释放本地锁和连接资源。
- 二阶段:在预提交阶段成功后,进入真正的提交阶段。此阶段主要包括提交异步化和回滚反向补偿两个步骤:
- 提交异步化:事务协调器发出真正的提交请求,各个资源管理器执行最终的提交操作。这个阶段的操作是非常快速的,以确保事务的提交效率。
- 回滚反向补偿:如果在预提交阶段中有任何一个资源管理器返回失败结果,事务协调器发出回滚请求,各个资源管理器执行回滚操作,利用一阶段的回滚日志进行反向补偿。
Seata的事务执行流程是什么样的?
Seata事务的执行流程可以简要概括为以下几个步骤:
- 事务发起方(Transaction Starter)发起全局事务:事务发起方是指发起分布式事务的应用程序或服务。它向Seata的事务协调器发送全局事务的开始请求,生成全局事务ID(Global Transaction ID)。
- 事务协调器创建全局事务记录:事务协调器接收到全局事务的开始请求后,会为该事务创建相应的全局事务记录,并生成分支事务ID(Branch Transaction ID)。
- 分支事务注册:事务发起方将全局事务ID和分支事务ID发送给各个参与者(Participant),即资源管理器。参与者将分支事务ID注册到本地事务管理器,并将事务的执行结果反馈给事务协调器。
- 执行业务逻辑:在分布式事务的上下文中,各个参与者执行各自的本地事务,即执行业务逻辑和数据库操作。
- 预提交阶段:事务发起方向事务协调器发送预提交请求,事务协调器将预提交请求发送给各个参与者。
- 执行本地事务确认:参与者接收到预提交请求后,执行本地事务的确认操作,并将本地事务的执行结果反馈给事务协调器。
- 全局事务提交或回滚:事务协调器根据参与者反馈的结果进行判断,如果所有参与者的本地事务都执行成功,事务协调器发送真正的提交请求给参与者,参与者执行最终的提交操作;如果有任何一个参与者的本地事务执行失败,事务协调器发送回滚请求给参与者,参与者执行回滚操作。
- 完成全局事务:事务协调器接收到参与者的提交或回滚结果后,根据结果更新全局事务的状态,并通知事务发起方全局事务的最终结果。
全局事务ID和分支事务ID是怎么传递的?
全局事务ID和分支事务ID在分布式事务中通过上下文传递的方式进行传递。常见的传递方式包括参数传递、线程上下文传递和消息中间件传递。具体的传递方式可以根据业务场景和技术选型进行选择和调整。
Seata的事务回滚是怎么实现的?
Seata的事务回滚是通过回滚日志实现的。每个参与者在执行本地事务期间生成回滚日志,记录了对数据的修改操作。
当需要回滚事务时,事务协调器向参与者发送回滚请求,参与者根据回滚日志中的信息执行撤销操作,将数据恢复到事务开始前的状态。
回滚日志的管理和存储是Seata的核心机制,可以选择将日志存储在不同的介质中。通过回滚日志的持久化和恢复,Seata确保了事务的一致性和恢复性。
Sentinel 与Hystrix的区别是什么
Hystrix和Sentinel都是微服务架构中实现熔断和限流的工具,它们有以下区别和特点:
Hystrix是Netflix开源的熔断器实现,主要用于保护分布式系统中的服务调用。它的主要特点包括线程隔离、资源保护和降级处理。Hystrix通过将每个服务调用放入独立的线程池中来实现线程隔离,防止一个服务的延迟或故障影响其他服务。它通过监控服务调用的成功率、延迟等指标来保护后端资源,并在失败的请求或响应超时达到一定阈值时自动打开熔断器,避免连锁故障。此外,Hystrix还提供了降级处理功能,可以在服务不可用或响应过慢时返回预定义的降级响应,保证系统的可用性。
Sentinel是阿里巴巴开源的流量控制和系统保护工具,主要用于实现微服务架构中的流量控制、熔断、降级和系统负载保护等。它的主要特点包括实时监控和动态规则配置、丰富的流量控制策略、细粒度的服务保护以及支持多种编程语言。Sentinel可以实时监控服务的请求流量和各项指标,并提供实时的仪表盘和可视化的监控界面。它还支持通过API动态配置流量控制和熔断规则,可以根据实际情况进行动态调整。Sentinel提供了多种流量控制策略,包括基于QPS、线程数、并发连接数等多种指标进行的流量控制。此外,Sentinel还支持对每个具体的服务接口进行熔断、降级和限流等操作,以实现精确的服务保护策略。同时,Sentinel不仅支持Java,还支持Go、Python等多种编程语言,使其适用于跨语言的微服务架构。
总的来说,Hystrix注重线程隔离和资源保护,适用于保护单个服务调用。而Sentinel注重流量控制和动态规则配置,适用于对整个系统的流量进行监控和保护。根据实际需求和技术栈,可以选择适合的工具来实现微服务架构中的熔断和限流功能。
如果 Sentinel 的异常处理规则不满足需求,应该怎么办?
如果 Sentinel 的默认异常处理机制无法满足需求,可以选择自定义异常处理规则。
Sentinel 允许通过自定义实现 BlockedExceptionHandler 接口,然后将自定义的异常处理器对象交给 Spring 容器进行管理。 可以根据实际业务需求,定制化异常处理策略,例如全局兜底处理、日志打印、空指针检查等。 同时,还可以在处理器中加入自定义的业务逻辑,例如对异常进行分类、统计和反馈等。 这样,可以根据具体的应用场景和业务需求,灵活地扩展 Sentinel 的异常处理能力。
什么是分布式事务的防悬挂,空回滚
在分布式事务中,防悬挂和空回滚是两个重要的概念,它们通常在实现分布式事务时涉及的锁定机制、隔离性、错误处理等方面。下面对这两个概念进行详细解释
- 防悬挂
防悬挂是指在分布式事务的第一阶段,防止在没有对应的 Try 操作的情况下出现 Confirm 或 Cancel操作。这是为了保证事务的正确性和一致性。
分布式事务中最常见的模型是 TCC(Try-Confirm-Cancel)模型。在 TCC 模型中,事务通常分为三个步骤:
- Try:资源的预留操作。
- Confirm:确认操作,完成业务逻辑
- Cancel:取消操作,回滚预留资源。
防悬挂机制的作用是确保在分布式事务中,Confirm 和 Cancel 操作只会在 Try 操作成功执行后才会触发。防悬挂的场景通常是以下情况:
- Confirm 操作悬挂:如果 Confirm 操作在没有执行过 Try 操作的情况下被调用,可能会导致数据不一致
- Cancel 操作悬挂:类似地,如果 Cancel 操作在没有 Try 操作的情况下被调用,也会破坏数据的一致性。
为了防止这种情况,通常需要通过某些机制来检测和防止悬挂。例如:
- 幂等性检查:Confirm 和 Cancel 操作应该具备幂等性,避免多次调用引发问题。
- 状态校验:在执行 Confirm 或 Cancel 之前,可以先检查是否有对应的 Try 操作成功过,如果没有,则拒绝执行 Confirm 或 Cancel 操作
- 空回滚
空回滚是指在没有执行成功的Try操作时,Cancel操作仍然被调用了。Cancel操作实际上就是 Try操作的回滚操作,如果 Try 操作很本没有成功,则 Cancel 操作实际不会对任何资源产生影响,这种情况下称为空回滚
空回滚通常发生在分布式系统中的异常情况下,比如:
- 网络超时:Try 操作还没执行成功,网络就超时了,分布式事务协调器可能误认为 Try 操作失败,因此会调用 Cancel。
- 网络分区或中断:Try 操作请求未到达相应的服务端,客户端误认为 Try 操作已经失败并发起 Cancel。
在这些情况下,Cancel 操作会被执行,但因为 Try 操作并没有成功,所以 Cancel 实际上什么都不需要做。这就是空回滚。
为了支持空回滚,Cancel 操作必须具备以下能力:
- 幂等性:即使 Cancel 操作被多次调用,它的效果也只能是执行一次,不会对系统产生额外影响。
- 空回滚兼容性:Cancel操作在发现没有 Try 操作执行成功时,不做任何修改,直接返回成功状态
当前有个本地操作 A,远程操作 B,我需要保证 A和 B事务的一致性,你会如何实现?
这个题目经常有人会直接踩坑,然后就被面试官绕进去出不来了
要保证本地操作A和远程操作B的事务一致性,这是一个分布式事务问题。不能在本地事务中直接嵌入远程 RPC调用(这就是坑),而是通过异步解耦+补偿机制实现最终一致性。
常见方案是本地消息表:本地事务A执行时,先记录一条“待执行远程操作B”的日志(与A在同一事务中),本地事务提交后,通过异步线程或消息队列触发远程调用B、若B失败,通过定时任务重试(因为有日志,可以扫描日志重试),直到成功或人工介入。
为什么不能在本地事务中直接调用远程 RPC?
begin transaction
update A 本地数据库
调用远程服务B(RPC)
commit举个例子:本地操作A是“扣库存”(数据库事务),远程操作B是“调用支付接口扣款”。如果在本地事务中直接调用B,若 B超时 则本地事务回滚,但B实际执行了,导致库存与支付状态不一致。
除此之外,还有长事务问题,毕竟外部系统不可控(即使是公司其他部分的接口),若B执行时间过长,会导致 A 操作本地事务锁持有时间延长,引发数据库连接耗尽或死锁问题。
所以,不建议将 RPC调用嵌入本地事务中。同理,像发MQ、更新外部系统(如缓存)等操作,都不建议放在事务内。
现在需要你设计一个将已登录的用户踢下线的功能,如何实现?
可以通过标记用户 token 为失效或者直接移除其 session来实现踢下线功能
简单来说,就是让后续请求中带的登录凭证不再被系统接受。标记失效和直接删除都行,这样用户下次请求就会被拦截或要求重新登录
分布式系统
把单体项目进行了多机部署,多台服务器是如何共享用户登录信息的?
目前主流有两个方案:
- 将 Session 放置第三方共享存储中,例如 Redis、Memcached 等分布式缓存 或数据库中,所有的服务器统一访问第三方。
- JWT,即服务器不存储会话,用户登录后返回签名令牌(含用户信息),每次请求携带令牌验证即可。不过现在很多项目会把 JWT 存在 Redis 中
因为单机时候会话(Session)会存储在本地,比如 Tomcat 的 HttpSession 默认存在当前服务器内存中。多机部署后,同一个用户多次请求可能会被负载均衡到其他服务器,新服务器无法读取原会话数据,这时候登录态就丢了有些人会采用 粘性会话,比如利用 Nginx 根据用户 IP 或 Cookie 哈希固定转发到同一台服务器。这个方式有局限性,如果服务器宕机了会话就丢失(登录态就掉了),且扩容缩容时会导致负载不均,无法实现真正的弹性伸缩。所以普遍会采用第三方共享存储 Session,比如用 Redis 存放 Session,这样一来所有的服务都可以共享访问到同一个 Session。
举个例子
- 用户登录后,服务端生成 SessionID,并将用户数据(如用户ID、权限)写入Redis(Key=SessionID,Value=序列化数据)。
- 响应中设置 Cookie(如SESSION=abc123)或 Header 返回 Token。
- 用户下次请求携带 Session ID,任意服务器从 Redis 读取数据,还原用户上下文
服务监控
你们的服务怎么做监控和告警?
我们使用Prometheus和Grafana来实现整个微服务集群的监控和告警:
- Prometheus:Prometheus 是一个开源的监控系统,具有灵活的数据模型和强大的查询语言,能够收集和存储时间序列数据。它可以通过HTTP协议定期拉取微服务的指标数据,并提供可扩展的存储和查询功能。
- Grafana:Grafana 是一个开源的可视化仪表板工具,可以与 Prometheus 结合使用,创建实时和历史数据的仪表板。Grafana 提供了丰富的图表和可视化选项,可以帮助用户更好地理解和分析微服务的性能和状态。
你们的服务怎么做日志收集?
日志收集有很多种方案,我们用的是ELK:
- Elasticsearch:Elasticsearch是一个分布式搜索和分析引擎,用于存储和索引大量的日志数据。它提供了快速的搜索和聚合功能,可以高效地处理大规模的日志数据。
- Logstash:Logstash是一个用于收集、过滤和转发日志数据的工具。它可以从各种来源(如文件、网络、消息队列等)收集日志数据,并对数据进行处理和转换,然后将其发送到Elasticsearch进行存储和索引。
- Kibana:Kibana是一个用于日志数据可视化和分析的工具。它提供了丰富的图表、仪表盘和搜索功能,可以帮助用户实时监控和分析日志数据,发现潜在的问题和趋势。
简单说,这三者里Elasticsearch提供数据存储和检索能力,Logstash负责将日志收集到ES,Kibana负责日志数据的可视化分析。
使用ELK进行微服务日志收集的一般流程如下:
- 在每个微服务中配置日志输出:将微服务的日志输出到标准输出(stdout)或日志文件。
- 使用Logstash收集日志:配置Logstash收集器,通过配置输入插件(如文件输入、网络输入等)监听微服务的日志输出,并进行过滤和处理。
- 将日志数据发送到Elasticsearch:配置Logstash的输出插件,将经过处理的日志数据发送到Elasticsearch进行存储和索引。
- 使用Kibana进行可视化和分析:通过Kibana连接到Elasticsearch,创建仪表盘、图表和搜索查询,实时监控和分析微服务的日志数据。
除了应用最广泛的ELK,还有一些其它的方案比如Fluentd、Graylog、Loki、Filebeat,一些云厂商也提供了付费方案,比如阿里云的sls。
其它
说一下你对于 DDD 的了解?
DDD全名叫做 Domain-driven design,即领域驱动设计,它是一种软件开发方法,其主要目的就是让开发人员和领域专家可以更好地协作,从而开发出满足业务需求的系统
DDD 的关键概念包括领域模型和限界上下文。
- 领域模型描述了业务领域的规则和逻辑,让开发人员能够更好地理解业务需求。
- 限界上下文则定义了一个特定的业务领域内的模型和代码,使得其可以独立于其他上下文进行开发和维护。
除此之外,DDD还强调分层架构和事件溯源的重要性,分层架构将系统划分为不同层次的结构,每个层次的职责和角色各有不同,从而方便业务代码的开发和维护。事件溯源则是一种存储和处理业务事件的技术,支持审计、合规和业务分析等需求。
总得来说,DOD是一种设计和开发复杂软件系统的方法,一般情况下 MVC 已经能够完成许多软件业务的开发了,如果项目本身比较简单,引入 DDD的话不仅不能降低开发成本,还会增加开发的复杂程度,所以 DDD 在使用之前需要一定的思考。
什么是灰度发布、金丝雀部署以及蓝绿部署?
灰度发布、金丝雀部署和蓝绿部署是三种常见的软件发布策略,它们用于在系统升级时降低风险,确保在新版本上线过程中服务的稳定性和可控性
- 灰度发布
灰度发布是一种新进式的发布方式,它通过将新版本逐步推送给部分用户进行试用,逐步扩大使用范围,直到新版本完全替换旧版本,其目的是通过小范围的用户测试,验证新版本的稳定性,降低发布新版本的风验
实现方式:通常通过流量控制的方式,将一部分用户请求引导到新版本实例上。如果新版本表现正常,可以逐步增加新版本的用户群体,直到全量用户使用新版本。
适用场景:适合在业务逻辑变动较大的场景中使用,通过灰度发布可以发现新版本中的潜在问题,并在影响范围较小的情况下进行回滚。
- 金丝雀部署
金丝雀部署(Ccanary Deployment)是一种特殊的灰度发布策略,通常是指将新版本部署到少量的实例上,并仅将部分流量引导至这些实例,以验证新版本在实际生产环境中的表现。
和灰度发布的区别:金丝雀部署更强调在生产环境中逐步验证新版本的表现,类似于让“金丝雀”先进入矿井检测安全性,一旦检测到问题,可以快速回滚。
实现方式:可以通过负载均衡器或服务网格,将一定比例的流量引导到运行新版本的实例上。若新版本稳定,再逐步增加其流量占比。
适用场景:适用于需要在生产环境中验证新功能或配置变更的场景。通过金丝雀部署,可以提前发现新版本在生产环境中的潜在问题,降低对全量用户的影响,
- 蓝绿部署
蓝绿部署(Blue-Green Deployment)是一种无缝切换的部署策略,在这种模式下,生产环境中始终存在两个版本:蓝色版本(当前的生产版本)和绿色版本(新版本)。当绿色版本准备就绪时,通过负载均衡或路由切换,将所有流量从蓝色版本切换到绿色版本。
特点:在蓝绿部署中,旧版本(蓝色版本)始终保持可用,可以在新版本(绿色版本)出现问题时,快速切换回旧版本,实现快速回滚。
实现方式:通常通过负载均衡器、DNS 切换或 API网关,来切换蓝色版本和绿色版本之间的流量指向。
适用场景:适用于需要快速切换和回滚的场景,特别是在对系统稳定性要求较高的应用中,通过蓝绿部署,可以实现无停机升级。
