【☁Spring Cloud】Spring Cloud Alibaba面试题
Spring Cloud Alibaba 是什么
Spring Cloud Alibaba 是一套开源的分布式系统解决方案,为开发者提供了在云计算环境下构建应用程序所需的全部开发工具和服务支持。它在 Spring Cloud 基础上进行了扩展,为开发者提供了更多选择和灵活性。
Spring Cloud Alibaba 的核心组件包括 Nacos、Sentinel、Dubbo 和 RocketMQ。
有了Spring Cloud,为什么又出现了Spring Cloud Alibaba?
Spring Cloud netflix进入维护模式,大多数模块都不再维护和更新,意味着 Spring Cloud 团队将不会再向模块添加新功能。
Spring Cloud Alibaba 架构设计和流程
Spring Cloud Alibaba 的架构设计和流程与 Spring Cloud 类似,其核心原则是基于微服务架构的服务注册、发现、配置、监控和治理。
Spring Cloud Alibaba 提供了其他一些实用的组件,例如:
- Spring Cloud Alibaba Sentinel:用于实现流量控制、熔断降级、系统保护等功能的开源框架。
- Spring Cloud Alibaba Nacos Config:用于实现配置管理和服务发现的开源框架。
- Spring Cloud Alibaba Seata:用于实现分布式事务的开源框架。
- Spring Cloud Alibaba RocketMQ:用于实现消息队列的开源框架。
- Spring Cloud Alibaba Dubbo:用于实现微服务框架的开源框架。
你了解Nacos吗?
Nacos 是一个基于 REST 的动态服务发现、配置和服务管理平台,它可以帮助开发者快速地构建一套微服务生态系统。Nacos 提供了一个简单的 Web 界面来管理服务、配置和命名空间,可以通过 REST API 和服务 SDK 实现动态配置和服务发现。
Nacos 的架构设计基于三个核心模块:命名服务(Naming)、配置服务(Configuration)和服务治理(Governance)。其中,命名服务负责服务的注册和发现,配置服务负责配置的管理和发布,服务治理负责服务的负载均衡和流量控制。
Nacos就是注册中心+配置中心的组合
Nacos = Eureka + Config + Bus
Nacos有什么作用?
- 替代Eureka做服务注册
- 替代Config做配置中心
服务发现与服务健康检查
Nacos使服务更容易注册,并通过DNS或HTTP接口发现其他服务,Nacos还提供服务的实时健康检查,以防止向不健康的主机或服务实例发送请求。
动态配置管理
动态配置服务允许您在所有环境中以集中和动态的方式管理所有服务的配置。Nacos消除了在更新配置时重新部署应用程序,这使配置的更改更加高效和灵活。
动态DNS服务
Nacos提供基于DNS 协议的服务发现能力,旨在支持异构语言的服务发现,支持将注册在Nacos上的服务以域名的方式暴露端点,让三方应用方便的查阅及发现。
服务和元数据管理
Nacos 能让您从微服务平台建设的视角管理数据中心的所有服务及元数据,包括管理服务的描述、生命周期、服务的静态依赖分析、服务的健康状态、服务的流量管理、路由及安全策略。
Nacos支持Ap和Cp的切换,该如何选择呢?
一般来说,如果不需要存储服务级别的信息且服务实例是通过nacos-client注册,并能够保持心跳上报,那么就可以选择AP模式。当前主流的服务如 Spring cloud 和 Dubbo 服务,都适用于AP模式,AP模式为了服务的可用性而减弱了一致性,因此AP模式下只支持注册临时实例。
如果需要在服务级别编辑或者存储配置信息,那么 CP 是必须,K8S服务和DNS服务则适用于CP模式。
CP模式下则支持注册持久化实例,此时则是以 Raft 协议为集群运行模式,该模式下注册实例之前必须先注册服务,如果服务不存在,则会返回错误。
模式切换代码:
curl -X PUT '$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP'
Nacos读取配置文件的有哪几种方案?
- Data ID方案:指定spring.profile.active和配置文件的DataID来使不同环境下读取不同的配置
- Group方案:通过Group实现环境区分
- Namespace方案:通过建立不同NameSpace来区分
Nacos的服务注册和发现流程
整个注册中心的注册和发现流程主要有三个方面来完成:服务的提供方(以下简称server)、服务的消费者(以下简称client)、注册中心(nacos)。首先我们来探讨server与nacos的交互过程。
server需要通过nacos官方的OpenApi提供的接口来发起服务注册请求,随后server会定时向nacos发送心跳信息来进行心跳检测,对于使用者来说这一步可以采用ScheduledExecutorService创建定时任务来完成。nacos会异步的处理注册请求任务和心跳任务。
nacos心跳机制
nacos和client之间采取推拉结合的交互方式,一方面client可以通过定时任务每隔10s向nacos发起查询请求,如果服务列表改变nacos就会返回新列表,另一方面当本地服务实例发生变化时(即server实例注册成功或者心跳停止断开链接),nacos会主动通过UDP协议推送到client,udp协议非常快,不需要保持长连接。在注册中心的场景中client数量往往多于server,如果每一次服务更新,nacos要和成千上万的服务消费者去建立Tcp的话性能肯定是不行的。而如果UDP通知失败,客户端每10秒还会主动去拉一次,客户端拉取和服务器推送是互补的,这样既能保证server实例更新的时效性,又能提高效率。
Nacos的服务注册和发现的代码分析
Nacos Client
首先从客户端开始,通常我们的服务需要导入spring-cloud-starter-alibaba-nacos-discovery包来帮助我们将当前服务注册到nacos服务端。那么nacos client是何时将我们的服务注册到nacos服务端的呢?
(1)在org.springframework.cloud.client.serviceregistry包下的接口ServiceRegistry定义了sprngcloud中服务注册的规范,我们常用的例如eureka、nacos都是实现了这个接口,基于该标准去实现服务注册的。
(2)nacos的实现类是NacosServiceRegistry,这个类实现了register注册方法。在register中会封装一个Instance实例对象后调用namingService的registerInstance进行注册。
(3)在registerInstance方法中,nacos还会创建一个BeatInfo实例发送给服务端,用于检测服务的心跳。BeatReactor内部会维护一个线程每隔一段时间就会发送心跳包,并且还会维护一个线程去监听服务端的回应。如果超过指定时间服务端还是没有回应那就代表服务端可能已经宕机了。
(4)创建完心跳包后就开始向服务端进行实例注册了,具体的请求方法就封装在serverProxy.registerService中,registerService方法会将当前服务的po、端口号、服务名等信息作为参数通过服务端的open Api:/nacos/v1/ns/service创建服务。
注册方法何时被调用?
在spring-cloud-commons包的spring.factories文件中装配了AutoServiceRegistrationAutoConfiguration类。springboot的自动装配机制会自动的将这个类导入spring容器。
在这个类中注入了一个接口变量AutoServiceRegistration,nacos客户端就实现了这个接口,所以默认就是注入nacos的NacosAutoServiceRegistration,这个类继承了org.springframework.cloud.client.serviceregistry包下的AbstractAutoServiceRegistration类(这个类实现了AutoServiceRegistration和ApplicationListener),而且刚才我们介绍的实现注册操作的NacosServiceRegistry也作为变量被注入在这个类中。这个类监听了事件WebServerInitializedEvent,springboot在初始化完成的时候会发布WebServerInitializedEvent事件,这个类监听到事件就会调用onApplicationEvent方法。而方法中的bind方法会调用start()方法,而start()方法最终也会调用NacosServiceRegistry的registry方法完成服务注册。
Sentinel是什么?
Sentinel 是一款轻量级的流量控制和熔断降级框架,能够帮助用户解决高并发场景下的稳定性问题。它提供了实时的监控和告警功能,能够对服务的 QPS、RT、异常率等指标进行实时监控和统计,同时也支持基于规则的熔断降级、流量控制和系统保护。
Sentinel 的架构设计基于两个核心模块:流量控制和熔断降级。其中,流量控制负责限制服务的流量,避免系统被过载;熔断降级负责在服务异常或不可用时进行自动熔断,避免系统崩溃。
Sentinel 基本概念有哪些?
资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。
只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。规则围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。
Sentinel有哪些优点?
- 丰富的适用场景:哨兵在阿里巴巴得到了广泛的应用,几乎覆盖了近10年双11(11.11)购物节的所有核心场景,比如需要限制突发流量的“秒杀”满足系统能力、消息削峰填谷、不依靠业务断路、流量控制等。
- 实时监控:Sentinel 还提供实时监控能力。可以实时查看单台机器的运行时信息。
- 广泛的开源生态:Sentinel 提供与 Spring、Dubbo 和 gRPC 等常用框架和库的开箱即用集成。
- 多语言支持:Sentinel 为 Java、Go和C++提供了本机支持。
- 丰富的 SPI 扩展:Sentinel 提供简单易用的 SPI 扩展接口,可以让你快速自定义逻辑,例如自定义规则管理、适配数据源等。
Sentinel有哪几种流控模式?
- 直接(默认):api达到限流条件,直接限流
- 关联:当关联的资料达到阈值时,就限流自己。当与A关联的资源B达到阈值后,就限流A
- 链路:链路流控模式指的是,当从某个接口过来的资源达到限流条件时,开启限流;它的功能有点类似于针对 来源配置项,区别在于:针对来源是针对上级微服务,而链路流控是针对上级接口,也就是说它的粒度 更细;
Sentinel有哪几种流控效果呢?
- 直接(默认的流控处理):该方式是默认的流量控制方式,当QPS超过任意规则的阈值后,新的请求就会被立即拒绝,拒绝方式为抛出FlowException
- 预热(Warm Up):阈值除以coldFactor(默认为3),经过预热时长后才达到阈值,案例,阀值为10+预热时长设置5秒。系统初始化的阀值为10 / 3 约等于3,即阀值刚开始为3;然后过了5秒后阀值才慢慢升高恢复到10
- 排队等待:匀速器(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER)方式。这种方式严格控制了请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法
Sentinel 有哪些降级规则(熔断策略)?
- 慢调用比例 (SLOW_REQUEST_RATIO):选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。
- 异常比例 (ERROR_RATIO):当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。
- 异常数 (ERROR_COUNT):当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。
Dubbo是什么?
Dubbo 是一款高性能的 RPC 框架,能够帮助用户快速构建分布式应用程序。它支持多种协议和序列化方式,并提供了负载均衡、服务降级、集群容错等多种功能。
Dubbo 的架构设计基于三个核心模块:注册中心、提供者和消费者。其中,注册中心负责服务的注册和发现,提供者负责提供服务的实现,消费者负责调用服务的接口。
RocketMQ是什么?
RocketMQ 是一款开源的分布式消息中间件,能够帮助用户快速构建可靠的消息传递系统。它支持多种消息模式和协议,包括点对点模式和发布订阅模式,并提供了高可用、高性能和可扩展的特性。
Alibaba Cloud Config是什么?
Alibaba Cloud Config 是一款分布式配置中心,可以管理和推送应用程序的配置信息。它支持多种数据源,包括配置文件、环境变量、数据中心、GitHub 和 SVN 等,可以动态地更新应用程序的配置信息。
分布式事务的处理过程是怎样的?
分布式事务处理过程的唯一ID+三组件模型:
- Transaction ID XID(全局唯一的事务ID)
- TC (Transaction Coordinator) - 事务协调者:维护全局和分支事务的状态,驱动全局事务提交或回滚。
- TM (Transaction Manager) - 事务管理器:定义全局事务的范围:开始全局事务、提交或回滚全局事务。
- RM (Resource Manager) - 资源管理器:管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
处理过程:
- TM 向 TC 申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的 XID;
- XID 在微服务调用链路的上下文中传播;
- RM 向 TC 注册分支事务,将其纳入 XID 对应全局事务的管辖;
- TM 向 TC 发起针对 XID 的全局提交或回滚决议;
- TC 调度 XID 下管辖的全部分支事务完成提交或回滚请求。
Seata是什么?
Seata 是一个开源的分布式事务解决方案,它提供了高可用的事务管理功能和高性能的本地事务处理能力。Seata 可以与多种框架和平台进行集成,包括 Spring Cloud Alibaba、Dubbo。
Seata分布式事务框架实现原理?
Seata有三个组成部分:
- 事务协调器TC:协调者
- 事务管理器TM:发起方
- 资源管理器RM:参与方
(1)发起方会向协调者申请一个全局事务id,并保存到ThreadLocal中(为什么要保存到ThreadLocal中?弱引用,线程之间不会发生数据冲突)
(2)Seata数据源代理发起方和参与方的数据源,将前置镜像和后置镜像写入到undo_log表中,方便后期回滚使用
(3)发起方获取全局事务id,通过改写Feign客户端请求头传入全局事务id。
(4)参与方从请求头中获取全局事务id保存到ThreadLocal中,并把该分支注册到SeataServer中。
(5)如果没有出现异常,发起方会通知协调者,协调者通知所有分支,通过全局事务id和本地事务id删除undo_log数据,如果出现异常,通过undo_log逆向生成sql语句并执行,然后删除undo_log语句。如果处理业务逻辑代码超时,也会回滚。