SpringCloud 篇
1、什么是
Spring cloud 流应用程序启动器是基于 Spring Boot 的 Spring 集成应用程序,提供与外部系统的集成。Spring cloud Task,一个生命周期短暂的微服务框架,用于快速构建执行有限数据处理的应用程序。
2、什么是微服务
微服务架构是一种架构模式或者说是一种架构风格,它提倡将单一应用程序划分为一组小的服务,每个服务运行在其独立的自己的进程中,服务之间相互协调、互相配合,为用户提供最终价值。服务之间采用轻量级的通信机制互相沟通(通常是基于 HTTP 的 RESTful API),每个服务都围绕着具体的业务进行构建,并且能够被独立的构建在生产环境、类生产环境等。另外,应避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具对其进行构建,可以有一个非常轻量级的集中式管理来协调这些服务,可以使用不同的语言来编写服务,也可以使用不同的数据存储。
3、SpringCloud 有什么优势
使用 Spring Boot 开发分布式微服务时,我们面临以下问题
(1)与分布式系统相关的复杂性-这种开销包括网络问题,延迟开销,带宽问题,安全问题。
(2)服务发现-服务发现工具管理群集中的流程和服务如何查找和互相交谈。它涉及一个服务目录,在该目录中注册服务,然后能够查找并连接到该目录中的服务。
(3)冗余-分布式系统中的冗余问题。
(4)负载平衡 –负载平衡改善跨多个计算资源的工作负荷,诸如计算机,计算机集群,网络链路,中央处理单元,或磁盘驱动器的分布。
(5)性能-问题 由于各种运营开销导致的性能问题。
(6)部署复杂性-Devops 技能的要求。
4、 什么是服务熔断?什么是服务降级?
熔断机制是应对雪崩效应的一种微服务链路保护机制。当某个微服务不可用或者响应时间太长时,会进行服务降级,进而熔断该节点微服务的调用,快速返回“错误”的响应信息。当检测到该节点微服务调用响应正常后恢复调用链路。在 SpringCloud 框架里熔断机制通过Hystrix 实现,Hystrix 会监控微服务间调用的状况,当失败的调用到一定阈值,缺省是 5 秒内调用 20 次,如果失败,就会启动熔断机制。服务降级,一般是从整体负荷考虑。就是当某个服务熔断之后,服务器将不再被调用,此时客户端可以自己准备一个本地的 fallback回调,返回一个缺省值。这样做,虽然水平下降,但好歹可用,比直接挂掉强。
Hystrix 相关注解 @EnableHystrix:开启熔断 @HystrixCommand(fallbackMethod=”XXX”):声明一个失败回滚处理函数 XXX,当被注解的方法执行超时(默认是 1000 毫秒),就会执行 fallback 函数,返回错误提示。
5、Eureka 和 zookeeper 都可以提供服务注册与发现的功能,请说说两个的区别?
Zookeeper 保证了CP(C:一致性,P:分区容错性),Eureka 保证了AP(A:高可用,P:分区容错性)
1.当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的信息,但不能容忍直接 down 掉不可用。也就是说,服务注册功能对高可用性要求比较高,但 zk 会出现这样一种情况,当 master 节点因为网络故障与其他节点失去联系时,剩余节点会重新选 leader。问题在于,选取 leader 时间过长,30 ~ 120 s,且选取期间 zk 集群都不可用,这样就会导致选取期间注册服务瘫痪。在云部署的环境下,因网络问题使得zk集群失去master节点是较大概率会发生的事,虽然服务能够恢复,但是漫长的选取时间导致的注册长期不可用是不能容忍的。
2.Eureka 保证了可用性,Eureka 各个节点是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点仍然可以提供注册和查询服务。而 Eureka 的客户端向某个 Eureka 注册或发现时发生连接失败,则会自动切换到其他节点,只要有一台 Eureka 还在,就能保证注册服务可用,只是查到的信息可能不是最新的。除此之外,Eureka 还有自我保护机制,如果在 15 分钟内超过 85% 的节点没有正常的心跳,那么 Eureka 就认为客户端与注册中心发生了网络故障,此时会出现以下几种情况:
①、Eureka 不在从注册列表中移除因为长时间没有收到心跳而应该过期的服务。
②、Eureka 仍然能够接受新服务的注册和查询请求,但是不会被同步到其他节点上(即保证当前节点仍然可用)
③、当网络稳定时,当前实例新的注册信息会被同步到其他节点。
因此,Eureka 可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像 Zookeeper 那样使整个微服务瘫痪
6、SpringBoot 和 SpringCloud 的区别?
SpringBoot 专注于快速方便的开发单个个体微服务。
SpringCloud 是关注全局的微服务协调整理治理框架,它将 SpringBoot 开发的一个个单体微服务整合并管理起来,为各个微服务之间提供,配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等集成服务
SpringBoot 可以离开 SpringCloud 独立使用开发项目, 但是 SpringCloud 离不开 SpringBoot ,属于依赖的关系。SpringBoot 专注于快速、方便的开发单个微服务个体,SpringCloud 关注全局的服务治理框架。
7、负载平衡的意义什么?
在计算中,负载平衡可以改善跨计算机,计算机集群,网络链接,中央处理单元或磁盘驱动器等多种计算资源的工作负载分布。负载平衡旨在优化资源使用,最大化吞吐量,最小化响应时间并避免任何单一资源的过载。使用多个组件进行负载平衡而不是单个组件可能会通过冗余来提高可靠性和可用性。负载平衡通常涉及专用软件或硬件,例如多层交换机或域名系统服务器进程。
8、什么是 Hystrix ?它如何实现容错?
Hystrix 是一个延迟和容错库,旨在隔离远程系统,服务和第三方库的访问点,当出现不可避免的故障时,停止级联故障并在复杂的分布式系统中实现弹性。
通常对于使用微服务架构开发的系统,涉及到许多微服务。这些微服务彼此协作。思考以下微服务
假设如果上图中的微服务 9 失败了,那么使用传统方法我们将传播一个异常。但这仍然会导致整个系统崩溃。
随着微服务数量的增加,这个问题变得更加复杂。微服务的数量可以高达 1000。这是 hystrix 出现的地方,我们将使用 Hystrix 在这种情况下的 Fallback 方法功能。我们有两个服务 employee-consumer 使用由 employee-consumer 公开的服务。
简化图如下所示
现在假设由于某种原因,employee-producer 公开的服务会抛出异常。我们在这种情况下使用 Hystrix 定义了一个回退方法。这种后备方法应该具有与公开服务相同的返回类型。如果暴露服务中出现异常,则回退方法将返回一些值。
9、什么是 Hystrix 断路器?我们需要它吗?
由于某些原因,employee-consumer 公开服务会引发异常。在这种情况下使用 Hystrix 我们定义了一个回退方法。如果在公开服务中发生异常,则回退方法返回一些默认值
如果 firstPage method() 中的异常继续发生,则 Hystrix 电路将中断,并且员工使用者将一起跳过 firtsPage 方法,并直接调用回退方法。 断路器的目的是给第一页方法或第一页方法可能调用的其他方法留出时间,并导致异常恢复。可能发生的情况是,在负载较小的情况下,导致异常的问题有更好的恢复机会 。
10、说说 RPC 的实现原理
首先需要有处理网络连接通讯的模块,负责连接建立、管理和消息的传输。其次需要有编解码的模块,因为网络通讯都是传输的字节码,需要将我们使用的对象序列化和反序列化。剩下的就是客户端和服务器端的部分,服务器端暴露要开放的服务接口,客户调用服务接口的一个代理实现,这个代理实现负责收集数据、编码并传输给服务器然后等待结果返回。
11、Eureka 自我保护机制是什么?
当 Eureka Server 节点在短时间内丢失了过多实例的连接时(比如网络故障或频繁启动关闭客户端)节点会进入自我保护模式,保护注册信息,不再删除注册数据,故障恢复时,自动退出自我保护模式。
12、什么是 Ribbon ?
ribbon 是一个负载均衡客户端,可以很好的控制 http 和 tcp 的一些行为。feign 默认集成了 ribbon。
13、什么是 feigin ?它的优点是什么?
1.feign 采用的是基于接口的注解
2.feign 整合了 ribbon,具有负载均衡的能力
3.整合了 Hystrix,具有熔断的能力
使用: 1.添加 pom 依赖。 2.启动类添加 @EnableFeignClients 3.定义一个接口 @FeignClient(name=“xxx”) 指定调用哪个服务
14、Ribbon 和 Feign 的区别?
1.Ribbon 都是调用其他服务的,但方式不同。
2.启动类注解不同,Ribbon 是 @RibbonClient;feign 的是 @EnableFeignClients
3.服务指定的位置不同,Ribbon 是在 @RibbonClient 注解上声明,Feign则是在定义抽象方法的接口中使用 @FeignClient 声明。
4.调用方式不同,Ribbon 需要自己构建 http 请求,模拟 http 请求
15、如何设计一个注册中心?
- 服务注册
- 注册表结构设计服务发现
- 服务订阅
- 服务推送
- 健康检查
- 集群同步:设计到数据同步,数据同步我们有哪些协议 raft 、distro、ZAB
16、Nacos1.x 作为注册中心的原理?
1、使用 HTTP 发送注册
2、查询服务提供方列表
3、定时拉取(每 10 秒)
4、检测到服务提供者异常,基于 UDP 协议推送更新
5、定时心跳(5 秒),检测服务状态
6、定时心跳任务检查
7、集群数据同步任务使用 Distro
17、Nacos 服务领域模型有哪些?
模型名称 | 解释 |
---|---|
NameSpace | 实现环境隔离,默认值 public |
Group | 不同的 service 可以组成一个 Group,默认值 Default-Group |
Service | 服务名称 |
Cluster | 对指定的微服务虚拟划分,默认值Default |
Instance | 某个服务的具体实例 |
Nacos 服务注册中心于发现的领域模型的最佳实践。
18、Nacos中的Distro协议
- Nacos 每个节点自己负责部分的写请求。
- 每个节点会把自己负责的新增数据同步给其他节点。
- 每个节点定时发送自己负责数据的校验值到其他节点来保持数据一致性。
- 每个节点独立处理读请求,及时从本地发出响应。
- 新加入的 Distro 节点会进行全量数据拉取。(具体操作是轮询所有的 Distro节点,通过向其他的机器发送请求拉取全量数据。)
-
19、配置中心的技术选型
功能点 | Spring Cloud Config | Apollo | Nacos |
---|---|---|---|
版本管理 | 支持(Git) | 支持 | 支持 |
配置实时推送 | 支持(Spring Cloud Bus) | 支持(HTTP 长轮询 1 s 内) | 支持(HTTP 长轮询 1 s 内 或者 grpc) |
配置回滚 | 支持(Git) | 支持 | 支持 |
灰度发布 | 支持(调用机器接口) | 支持 | 不支持 |
权限管理 | 支持(依赖 Git) | 支持 | 支持 |
配置生效时间 | 重启 | 实时 | 实时 |
审计 | 支持(依赖 Git) | 支持 | 不支持 |
多集群 | 支持 | 支持 | 支持 |
多环境 | 支持 | 支持 | 支持 |
client 本地缓存 | 不支持 | 支持 | 支持 |
监听查询 | 支持 | 支持 | 支持 |
运维成本 | 高 | 中等 | 较低 |
多语言 | 仅 Java | 主流语言,提供了 Open API | 主流语言,提供了 Open API |
配置项维护 | 基于 Git | 统一界面 | 统一界面 |
20、Nacos1.x 配置中心长轮询机制?
客户端会轮询向服务端发出一个长连接请求,这个长连接最多 30 s 就会超时,服务端收到客户端的请求会先判断当前是否有配置更新,有则立即返回,如果没有服务端会将这个请求拿住“hold” 29.5 s 加入队列,最后 0.5 s 再检测配置文件无论有没有更新都进行正常返回,但等待的 29.5 s 期间有配置更新可以提前结束并返回。
21、Nacos 配置中心配置优先级?
1 | #作用:顺序 |
1 | spring.application.name=nacos-config |
22、Nacos 2.x 客户端探活机制?
Nacos 2.x 引入了客户端探活机制,该机制主要用于检测服务实例的健康状态。具体来说,Nacos 2.x 客户端探活机制包括以下几个步骤:
- 注册服务实例:服务提供者在启动时将自己的实例信息注册到 Nacos Server 中,包括 IP 地址、端口号和健康状态等。
- 心跳检测:Nacos Server 会周期性地向服务实例发送心跳请求,以检测实例是否存活。默认情况下,心跳检测间隔为 5 秒。
- 健康检测:服务实例在接收到 Nacos Server 的心跳请求后,会返回一个健康状态给 Nacos Server。如果服务实例长时间未返回健康状态或返回的状态为不健康,Nacos Server 会认为该实例不可用。
- 健康状态更新:服务实例的健康状态可能会因为各种原因发生变化,例如网络故障或服务异常。当服务实例的健康状态发生变化时,Nacos Server 会及时更新实例的健康状态。
通过客户端探活机制,Nacos 可以动态地监测和管理服务实例的健康状态,以确保服务的可用性和稳定性。
23、Ribbon 底层怎样实现不同服务的不同配置
Ribbon 是一个负载均衡客户端,它的底层实现主要依赖于以下几个组件:
- 服务发现:Ribbon 通过与服务注册中心(如 Eureka、Consul 或 Nacos)进行集成,获取可用的服务实例列表。通过服务发现,Ribbon 可以动态地获取不同服务的实例信息。
- 负载均衡策略:Ribbon 支持多种负载均衡策略,例如轮询、随机、加权随机、加权轮询等。根据不同的负载均衡策略,Ribbon 可以在不同的服务实例之间进行请求的分发。
- 配置管理:Ribbon 可以通过配置文件或配置中心(如 Spring Cloud Config 或 Nacos)获取服务的相关配置信息。这些配置信息可以包括连接超时时间、重试次数、连接池大小等。通过配置管理,Ribbon 可以根据不同的服务设置不同的配置。
通过以上组件的协作,Ribbon 可以根据服务的不同配置来进行请求的负载均衡。例如,可以针对不同的服务设置不同的负载均衡策略或超时时间,以满足不同服务的需求。
24、为什么 Feign 第一次调用耗时很长?
在使用 Feign 进行第一次调用时,可能会出现较长的耗时。这是由于以下原因:
- 服务发现和负载均衡:Feign 在第一次调用时需要进行服务发现和负载均衡操作,以确定要调用的服务实例。这涉及到与服务注册中心通信、获取可用实例列表并选择一个实例等步骤,这些操作可能会花费一些时间。
- 远程调用初始化:在进行第一次远程调用时,Feign 需要初始化相关的 HTTP 连接和连接池等资源。这包括建立 TCP 连接、进行 TLS 握手(如果使用 HTTPS)以及创建 HTTP 请求等。这些初始化过程可能会导致一定的延迟。
- 服务实例的冷启动:如果服务实例处于空闲状态,可能会因为冷启动而导致第一次调用的耗时较长。冷启动时,服务实例需要进行初始化和加载相关资源,这可能会花费更多的时间。
为了减少 Feign 第一次调用的耗时,可以采取以下措施:
- 启用连接池:可以通过配置 Feign 使用连接池来复用 TCP 连接,减少连接的建立和释放开销,提高性能。
- 预热服务实例:可以通过定时任务或定时健康检查等方式,定期发送心跳请求或调用服务实例,使其保持活跃状态,避免冷启动带来的延迟。
- 调整超时时间:根据实际情况,可以适当调整 Feign 的超时时间设置,以确保在网络状况较差或服务响应较慢时,不会因超时导致请求失败。
需要注意的是,Feign 的第一次调用耗时问题可能是正常现象,因为在微服务架构中,服务之间的通信和调用是不可避免的,而这些初始化和准备过程都需要一定的时间。
25、Ribbon 的属性配置和类配置优先级
在 Ribbon 中,属性配置和类配置有不同的优先级。具体来说,优先级从高到低如下:
- 属性配置优先级高于类配置:如果在属性配置和类配置中同时设置了相同的属性,属性配置会覆盖类配置。属性配置通常是通过配置文件(如
application.properties
或application.yml
)中的属性来进行设置。 - 类配置:类配置是通过编程方式进行设置,通常是通过创建
RibbonClientConfiguration
的子类并覆盖其中的方法来进行自定义配置。类配置中可以设置一些默认的属性值,这些属性值将被应用于所有的 Ribbon 客户端。 - 全局默认配置:Ribbon 还提供了一些全局默认配置,对所有的 Ribbon 客户端都生效。可以通过在配置文件中设置以”ribbon.”开头的属性来进行全局默认配置。
总的来说,属性配置具有最高的优先级,会覆盖类配置和全局默认配置。类配置的优先级次之,而全局默认配置的优先级最低。通过这种优先级的设置,可以在不同的层级上对 Ribbon 进行灵活的配置和定制。
26、Feign 的性能优化?
要优化 Feign 的性能,可以考虑以下几个方面:
- 启用连接池:通过配置 Feign 使用连接池来复用 TCP 连接,减少连接的建立和释放开销,提高性能。可以通过配置
httpclient
的相关属性,如maxTotalConnections
和maxConnectionsPerRoute
来控制连接池的大小。 - 调整超时时间:根据实际情况,可以适当调整Feign的超时时间设置,以确保在网络状况较差或服务响应较慢时,不会因超时导致请求失败。可以通过配置
connectTimeout
和readTimeout
来设置连接超时和读取超时时间。 - 批量请求:如果有多个独立的请求需要发送给同一个服务,可以考虑使用 Feign 的批量请求功能,将多个请求合并为一个批量请求发送,减少网络开销和连接建立的次数,提高性能。
- 启用 GZIP 压缩:可以通过配置 Feign 启用 GZIP 压缩来减少网络传输的数据量,提高性能。可以通过设置
Content-Encoding
为gzip
来启用 GZIP 压缩。 - 启用 HTTP / 2:如果服务端支持 HTTP / 2 协议,可以通过配置 Feign 使用 HTTP / 2 来提高性能。可以通过配置
httpclient
的相关属性,如sslContextBuilder
和alpnProtocols
来启用 HTTP / 2。 - 缓存:对于一些不经常变动的数据,可以考虑在客户端使用缓存,减少对服务端的请求,提高性能。可以使用 Spring Cache 等缓存框架来实现。
- 并发请求:如果有多个独立的请求需要发送给不同的服务,可以考虑使用并发请求的方式,同时发送多个请求,减少请求的等待时间,提高性能。可以使用异步方式发送请求,或使用并发工具类如 CompletableFuture 来实现。
注意,优化 Feign 的性能需要根据具体场景和需求进行调整和测试。不同的应用场景可能需要不同的优化策略,因此需要根据实际情况选择合适的优化方法。
Feign 底层默认是 JDK 自带的 HttpURLConnection,它是单线程发送 HTTP 请求的,不能配置线程池,我们使用 OKHttp 或者 HttpClient 来发送 HTTP 请求,并且它们两个都支持线程池。
常见HTTP客户端
HttpClient
HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协 议的客户端编程工具包,并且它支持 HTTP 协议最新版本和建议。HttpClient 相比传统 JDK 自带的 URLConnection,提升了易用性和灵活性,使客户端发送 HTTP 请求变得容易,提高了开发的效率。
Okhttp
一个处理网络请求的开源项目,是安卓端最火的轻量级框架,由 Square 公司贡献,用于替代 HttpUrlConnection 和 Apache HttpClient。OKHttp 拥有简洁的 API、高效的性能,并支持多种协议 (HTTP/2 和 SPDY)。
HttpURLConnection
HttpURLConnection 是 Java 的标准类,它继承自 URLConnection,可用于向指定网站发送 GET 请求、 POST 请求。HttpURLConnection 使用比较复杂,不像 HttpClient 那样容易使用。
RestTemplate
RestTemplate 是 Spring 提供的用于访问 Rest 服务的客户端,RestTemplate 提供了多种便捷访问远程 HTTP 服务的方法,能够大大提高客户端的编写效率。
27、Feign 怎样实现认证的传递?
在 Feign 中实现认证的传递,可以通过以下几种方式:
- 使用请求头传递认证信息:可以在 Feign 的请求方法上添加
@RequestHeader
注解,将认证信息作为请求头的一部分进行传递。例如:
1 |
|
在调用 getExampleData
方法时,可以将认证信息作为参数传入,Feign 会将其放入请求头中。
- 使用请求参数传递认证信息:可以在 Feign 的请求方法上添加
@RequestParam
注解,将认证信息作为请求参数进行传递。例如:
1 |
|
在调用 getExampleData
方法时,可以将认证信息作为参数传入,Feign 会将其作为请求参数进行传递。
- 使用请求体传递认证信息:可以在Feign的请求方法上添加
@RequestBody
注解,将认证信息作为请求体的一部分进行传递。例如:
1 |
|
在调用postExampleData
方法时,可以创建一个包含认证信息的请求体对象,并作为参数传入。
需要注意的是,以上方法仅适用于将认证信息传递给后端服务。在后端服务中,需要进行相应的认证验证和处理。另外,认证信息的传递方式应根据具体的认证机制和安全要求进行选择和配置。
28、谈谈 Sentienl 中使用的限流算法
Sentinel 是一个开源的分布式系统的流量防控组件,它提供了实时的流量控制、熔断降级、系统负载保护等功能。在 Sentienl 中使用的限流算法主要有以下几种:
- 固定窗口计数器(Fixed Window Counter):该算法是最简单的限流算法之一,它将请求按照时间窗口进行计数,当窗口内的请求数超过阈值时进行限流。例如,可以设置每秒钟最多处理 100 个请求,超过该阈值的请求将被限流。
- 滑动窗口计数器(Sliding Window Counter):该算法是固定窗口计数器的改进版,它不仅考虑了窗口内的请求数,还考虑了窗口内的时间分布。例如,可以将时间窗口划分为若干个小窗口,每个小窗口内都有一个请求数的阈值,当整个时间窗口内的请求数超过阈值时进行限流。
- 令牌桶算法(Token Bucket):该算法是一种基于令牌的限流算法,它维护一个固定容量的令牌桶,每个令牌代表一个请求的权限。当请求到达时,需要从令牌桶中获取一个令牌,如果令牌桶为空,则表示无法获取令牌,请求将被限流。令牌桶算法可以平滑处理请求的流量。
- 漏桶算法(Leaky Bucket):该算法是一种基于漏桶的限流算法,它将请求看作水滴,漏桶作为一个固定容量的桶,请求以恒定的速率流入桶中,如果桶满了,则表示请求无法处理,被限流。漏桶算法可以平滑处理突发的请求流量。
以上是 Sentienl 中使用的常见限流算法,根据具体的应用场景和需求,可以选择合适的算法进行限流。
29、谈谈 Sentienl 服务熔断过程
Sentinel 是一个流量控制组件,除了限流功能外,还提供了熔断降级的功能。在 Sentinel 中,服务熔断是一种保护机制,用于防止故障服务对整个系统的影响。下面是 Sentinel 服务熔断的一般过程:
- 监控服务调用:Sentinel 会监控服务的调用情况,包括请求的成功率、响应时间等指标。通过实时收集和统计这些指标,Sentinel 可以判断服务是否正常运行。
- 熔断条件判断:当服务的某些指标超过预设的阈值时,Sentinel 就会触发熔断条件判断。例如,可以设置当服务的请求错误率超过 50% 时触发熔断。
- 进入熔断状态:一旦触发熔断条件,Sentinel 会将服务切换到熔断状态。在熔断状态下,Sentinel 会拒绝对该服务的请求,并返回预设的错误信息或者空响应。这样可以避免故障服务对整个系统的影响。
- 熔断恢复:在熔断状态下,Sentinel 会定时尝试恢复服务。它会允许一部分请求通过,以测试服务的可用性。如果这些请求成功率达到一定的阈值,Sentinel 就会认为服务已经恢复正常,将服务切换回正常状态。
- 熔断保护:为了防止熔断状态频繁切换,Sentinel 还提供了熔断保护机制。当服务切换回正常状态后,Sentinel 会暂时禁止对该服务的请求,以避免服务被过多的请求压垮。
通过以上的熔断过程,Sentinel 可以有效地保护系统免受故障服务的影响,提高系统的可用性和稳定性。
30、在 Gateway 中怎样实现服务平滑迁移?
在 Gateway 中实现服务平滑迁移可以采用以下步骤:
- 配置多个后端服务:在 Gateway 的配置中,同时配置新旧两个版本的后端服务。可以使用不同的路由规则或者负载均衡策略来将请求分发到不同的后端服务。
- 分流策略设置:在 Gateway 中设置分流策略,逐渐将流量从旧版本的后端服务迁移到新版本的后端服务上。可以根据实际需求逐步提高新版本服务的流量占比,例如每天增加一定比例的流量。
- 监控和调整:监控新版本服务的性能和稳定性,确保新版本服务能够正常运行。如果发现问题,可以及时调整配置或者回滚迁移操作。
- 逐步迁移:在经过一段时间的监控和调整后,当新版本服务被充分验证并且稳定运行时,可以逐步将流量从旧版本服务全面切换到新版本服务上。
- 清理旧版本:在所有流量都已经迁移到新版本服务后,可以将旧版本服务从 Gateway 的配置中移除,并进行清理操作。
需要注意的是,在服务平滑迁移过程中,要确保新版本服务和旧版本服务的接口和功能兼容,以避免对客户端的影响。此外,还应该做好监控和回滚准备,以应对可能出现的问题。
31、Seata 支持那些事务模式?
概念:Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。
- AT(Atomikos)模式:AT 模式是 Seata 的默认事务模式,它通过在业务代码中嵌入事务上下文,实现分布式事务的一致性。在 AT 模式下,Seata 会对参与分布式事务的数据库进行事务协调和管理,保证所有数据库的数据一致性。提供无侵入自动补偿的事务模式 【这里是基于本地能支持事务的关系型数据库,然后 java 代码可以通过 JDBC 访问数据库, 这里的无侵入:我们只需要加上对应的注解就可以开启全局事务】
- TCC(Try-Confirm-Cancel)模式:TCC 模式是一种补偿性事务模式,它通过定义业务的 Try、Confirm 和 Cancel 三个阶段来实现分布式事务的一致性。在 TCC 模式下,Seata 会根据业务代码中定义的 Try、Confirm 和 Cancel 方法来执行事务操作,保证事务的一致性。
- SAGA(Saga)模式:SAGA 模式是一种长事务模式,它通过定义一系列的事务步骤来实现分布式事务的一致性。在 SAGA 模式下,Seata 会按照业务代码中定义的事务步骤顺序执行,每个步骤都有对应的补偿操作,以保证整个事务的一致性。
- XA(X/Open XA)模式:XA 模式是一种基于两阶段提交(2 PC)的事务模式,它通过协调参与分布式事务的资源管理器(如数据库)来实现事务的一致性。在 XA 模式下,Seata 会与各个资源管理器进行协调,确保所有资源的提交或回滚操作都能正确执行,以保证分布式事务的一致性。
32、请简述 2 PC 流程以及优缺点
2 PC(Two-Phase Commit)是一种经典的分布式事务协议,它通过两个阶段的协调来实现分布式事务的一致性。以下是 2 PC 的基本流程:
准备阶段(Prepare Phase):
- 协调者(Coordinator)向参与者(Participant)发送事务准备请求。
- 参与者执行事务操作,并将事务日志和准备完成的消息发送给协调者。
- 协调者收到所有参与者的准备完成消息后,进入下一阶段。如果有任何一个参与者发生错误或者超时,协调者将发送回滚请求给所有参与者。
提交阶段(Commit Phase):
- 协调者向所有参与者发送事务提交请求。
- 参与者执行事务的最终提交操作,并将提交完成的消息发送给协调者。
- 协调者收到所有参与者的提交完成消息后,向所有参与者发送事务完成的消息,事务完成。
2 PC 的优点:
- 数据一致性:2 PC 可以保证所有参与者的数据在事务提交时保持一致,即要么全部提交成功,要么全部回滚。
- 简单易用:2 PC 是一个相对简单的分布式事务协议,易于理解和实现。
2 PC 的缺点:
- 同步阻塞:在 2 PC 的过程中,所有参与者都需要等待协调者的指令,这会导致整个事务的执行过程存在阻塞,影响性能和吞吐量。
- 单点故障:2 PC 中的协调者是一个单点,如果协调者发生故障,整个事务的执行将受到影响。
- 阻塞风暴:如果在准备阶段中的任何一个参与者发生故障或者超时,协调者将发送回滚请求给所有参与者,导致参与者之间的通信产生大量的回滚请求,可能引发阻塞风暴。
综上所述,2 PC 是一种经典的分布式事务协议,能够保证数据一致性,但存在同步阻塞和单点故障等问题。因此,在实际应用中,可以根据具体的业务需求和性能要求选择合适的分布式事务协议。
33、Seata中xid怎样通过 Feign 进行全局传递
在 Seata 中,XID(全局事务 ID)是用来标识一个全局事务的唯一标识符。在使用 Feign 进行服务之间的远程调用时,可以通过以下方式将 XID 传递给下游服务:
- 通过请求头传递:在发起 Feign 请求时,可以将 XID 设置为请求头的一部分,并在下游服务中解析该请求头获取 XID。例如,可以使用
@RequestHeader
注解将 XID 传递给下游服务。
1 |
|
- 通过请求参数传递:将 XID 作为请求参数传递给下游服务。在定义 Feign 接口方法时,将 XID 作为方法的参数,并在请求中传递给下游服务。下游服务通过解析请求参数获取 XID。
1 |
|
通过以上方式,在 Feign 远程调用中传递 XID,可以确保全局事务上下文在服务之间的传递和一致性。同时,下游服务需要正确解析和使用 XID,以保证参与到全局事务中。
34、分布式事务应用的典型场景
1、多服务
随着互联网快速发展,微服务,SOA 等服务架构模式正在被大规模的使用,会出现很多分布式事务,问题如下:
2、多数据源
2.1 跨库
跨库事务指的是,一个应用某个功能需要操作多个库,如下图:
2.2 分库分表
通常一个库数据量比较大或者预期未来的数据量比较大,都会进行水平拆分,也就是分库分表。如下图,将订单数据库拆分成了 4 个库:
35、请说一下 CAP 和 BASE 理论
CAP 和 BASE 是分布式必备理论基础
1、CAP理论
这个定理的内容是指的是在一个分布式系统中、Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可得兼。
- 一致性(C)
一致性意思就是写操作之后进行读操作无论在哪个节点都需要返回写操作的值
- 可用性(A)
非故障的节点在合理的时间内返回合理的响应
- 分区容错性(P)
当出现网络分区后,系统能够继续工作。打个比方,这里个集群有多台机器,有台机器网络出现了问题,但是这个集群仍然可以正常工作。在分布式系统中,网络无法 100% 可靠,分区其实是一个必然现象,如果我们选择了 CA 而放弃了 P,那么当发生分区现象时,为了保证一致性,这个时候必须拒绝请求,但是 A 又不允许,所以分布式系统理论上不可能选择CA架构,只能选择 CP 或者 AP 架构。
对于CP来说,放弃可用性,追求一致性和分区容错性,我们的 zookeeper 其实就是追求的强一致。
对于 AP 来说,放弃一致性(这里说的一致性是强一致性),追求分区容错性和可用性,Nacos 就是 AP 模式,这是很多分布式系统设计时的选择,后面的 BASE 也是根据 AP 来扩展。
2、BASE理论
BASE 是 Basically Available(基本可用)、Soft state(软状态)和 Eventually consistent(最终一致性)三个短语的缩写。BASE 理论是对 CAP 中一致性和可用性权衡的结果,其来源于对大规模互联网系统分布式实践的总结, 是基于 CAP 定理逐步演化而来的。BASE 理论的核心思想是:即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性。
- 基本可用
基本可用是指分布式系统在出现不可预知故障的时候,允许损失部分可用性—-注意,这绝不等价于系统不可用。比如:
(1)响应时间上的损失。正常情况下,一个在线搜索引擎需要在0.5秒之内返回给用户相应的查询结果,但由于出现故障,查询结果的响应时间增加了 1~2 秒
(2)系统功能上的损失:正常情况下,在一个电子商务网站上进行购物的时候,消费者几乎能够顺利完成每一笔订单,但是在一些节日大促购物高峰的时候,由于消费者的购物行为激增,为了保护购物系统的稳定性,部分消费者可能会被引导到一个降级页面
- 软状态
软状态指允许系统中的数据存在中间状态,并认为该中间状态的存在不会影响系统的整体可用性,即允许系统在不同节点的数据副本之间进行数据同步的过程存在延时
- 最终一致性
最终一致性强调的是所有的数据副本,在经过一段时间的同步之后,最终都能够达到一个一致的状态。因此,最终一致性的本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性。
36、简述 Seata 的 AT 模式两阶段过程
Seata的AT(Atomikos)模式是一种基于应用程序代码的分布式事务处理模式。它通过两阶段提交(Two-Phase Commit,2PC)的方式来实现分布式事务的一致性。
下面是Seata AT模式的两阶段过程:
阶段一:准备阶段(Prepare Phase)
- 应用程序发起一个分布式事务,并向Seata事务协调器注册该事务。
- Seata 事务协调器将该事务注册到全局事务日志中,并生成一个全局事务ID(Global Transaction ID)。
- 应用程序在本地事务执行前,会先向Seata事务协调器发送分支事务的注册请求。
- Seata 事务协调器会将分支事务注册到全局事务中,并生成一个分支事务ID(Branch Transaction ID)。
- 应用程序执行本地事务,并将事务执行结果(成功或失败)发送给 Seata 事务协调器。
阶段二:提交/回滚阶段(Commit/Rollback Phase)
- 如果所有分支事务的本地事务都执行成功,Seata 事务协调器会发送一个全局提交请求给各个分支事务参与者。
- 分支事务参与者接收到全局提交请求后,会执行本地事务的提交操作,并将提交结果发送给 Seata 事务协调器。
- 如果任何一个分支事务的本地事务执行失败,Seata 事务协调器会发送一个全局回滚请求给各个分支事务参与者。
- 分支事务参与者接收到全局回滚请求后,会执行本地事务的回滚操作,并将回滚结果发送给 Seata 事务协调器。
通过这个两阶段的过程,Seata AT 模式可以确保分布式事务的一致性。如果所有分支事务的本地事务执行成功,那么全局提交请求将被发送,所有分支事务都会提交。如果任何一个分支事务的本地事务执行失败,那么全局回滚请求将被发送,所有分支事务都会回滚。
37、简述 Eureka 自我保护机制
Eureka 服务端会检查最近 15 分钟内所有 Eureka 实例正常心跳占比,如果低于 85% 就会触发自我保护机制。触发了保护机制,Eureka将暂时把这些失效的服务保护起来,不让其过期,但这些服务也并不是永远不会过期。Eureka 在启动完成后,每隔 60 秒会检查一次服务健康状态,如果这些被保护起来失效的服务过一段时间后(默认 90 秒)还是没有恢复,就会把这些服务剔除。如果在此期间服务恢复了并且实例心跳占比高于 85% 时,就会自动关闭自我保护机制。
阈值的计算方式:
每分钟 能接受最少的续租次数 = 微服务实例总数 * (60 s / 实例的续约时间间隔:30s ) * 有效的心跳比率 默认 85%
100 乘以(60 /30) 乘以 85% = 170
自我保护机制更改条件: 注册、服务下架、 服务初始化、15 分钟更新一次
自我保护机制的触发位置: 服务剔除
38、简述 Eureka 集群架构
参考官网:https://github.com/Netflix/eureka/wiki/Eureka-at-a-glance
- Register(服务注册):把自己的 IP 和端口注册给 Eureka。
- Renew(服务续约):发送心跳包,每 30 秒发送一次。告诉 Eureka 自己还活着。
- Cancel(服务下线):当 provider 关闭时会向 Eureka 发送消息,把自己从服务列表中删除。防止 consumer 调用到不存在的服务。
- Get Registry(获取服务注册列表):获取其他服务列表。
- Make Remote Call(远程调用):完成服务的远程调用。
- Replicate(集群中数据同步):eureka 集群中的数据复制与同步。
39、从 Eureka 迁移到 Nacos 的解决方案
版本依赖关系:
https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E
换依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<spring-cloud.alibaba.version>2.2.9.RELEASE</spring-cloud.alibaba.version>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>配置换一下
1
2
3
4
5
6spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
service: msb-order使用
@EnableDiscoveryClient
开启注册发现1
2
3@EnableDiscoveryClient // 这是官方提供的 ,我们以后可能切换其他的注册中心比如说 nacos,那我们就直接切换就行了
//@EnableEurekaClient // 是 netflix 提供的,如果用这个注解就只能服务于 eureka梳理项目关系
只提供调用的基础服务先进行更改,进行迁移
40、Apollo的整体架构
- Config Service 提供配置的读取、推送等功能,服务对象是 Apollo 客户端。
- Admin Service 提供配置的修改、发布等功能,服务对象是 Apollo Portal(管理界面)。
- Config Service 和 Admin Service 都是多实例、无状态部署,所以需要将自己注册到 Eureka 中并保持心跳。
- 在 Eureka 之上我们架了一层 Meta Serve r用于封装 Eureka 的服务发现接口。
- Client 通过域名访问 Meta Server 获取 Config Service 服务列表(IP+Port),而后直接通过 IP+Port 访问服务,同时在 Client 侧会做 load balance、错误重试。
- Portal 通过域名访问 Meta Server 获取 Admin Service 服务列表(IP+Port),而后直接通过 IP+Port 访问服务,同时在 Portal 侧会做 load balance、错误重试。
为了简化部署,我们实际上会把 Config Service、Eureka 和 Meta Server 三个逻辑角色部署在同一个 JVM 进程中。
41、Apollo的整体架构可靠性分析
场景 | 影响 | 降级 |
---|---|---|
某台 Config Service 下线 | 无影响 | |
所有 Config Service 下线 | 客户端无法读取最新配置,Portal 无影响 | 客户端重启时,可以读取本地缓存配置文件。如果是新扩容的机器,可以从其它机器上获取已缓存的配置文件,具体信息可以参考 Java 客户端使用指南 - 1.2.3 本地缓存路径 |
某台 Admin Service下线 | 无影响 | |
所有 Admin Service下线 | 客户端无影响,Portal无法更新配置 | |
某台 Portal 下线 | 无影响 | |
全部 Portal 下线 | 客户端无影响,Portal无法更新配置 | |
某个数据中心下线 | 无影响 | |
数据库宕机 | 客户端无影响,Portal无法更新配置 | Config Service 开启配置缓存后,对配置的读取不受数据库宕机影响 |
42、Apollo配置发布后的实时推送设计
在配置中心中,一个重要的功能就是配置发布后实时推送到客户端。下面我们简要看一下这块是怎么设计实现的。
上图简要描述了配置发布的大致过程:
用户在 Portal 操作配置发布
Portal 调用 Admin Service 的接口操作发布
Admin Service 发布配置后,发送
ReleaseMessage
给各个Config ServiceConfig Service收到
ReleaseMessage
后,通知对应的客户端
43、Apollo 客户端设计
上图简要描述了 Apollo 客户端的实现原理:
- 客户端和服务端保持了一个长连接,从而能第一时间获得配置更新的推送。(通过Http Long Polling实现)
- 客户端还会定时从Apollo配置中心服务端拉取应用的最新配置。
- 客户端从Apollo配置中心服务端获取到应用的最新配置后,会保存在内存中
- 客户端会把从服务端获取到的配置在本地文件系统缓存一份,在遇到服务不可用,或网络不通的时候,依然能从本地恢复配置
- 应用程序可以从 Apollo 客户端获取最新的配置、订阅配置更新通知
44、Zuul 有几种过滤器类型?分别是?
Zuul 有四种过滤器类型,分别是:
前置过滤器(Pre Filter):在请求被路由之前执行。可以用来做身份验证、请求参数校验、记录调试信息等操作。
路由过滤器(Route Filter):用于将请求转发到目标服务实例。可以修改请求的路由规则、请求头等信息。
这种过滤器用于构建发送给微服务的请求,并使用 Apache HttpClient 或 Netfilx feign 请求
后置过滤器(Post Filter):在目标服务实例处理完请求并返回响应之后执行。可用来为响应添加标准的HTTP Header、收
集统计信息和指标、将响应从微服务发送给客户端,可以对响应进行处理,如添加响应头、修改响应内容等。
错误过滤器(Error Filter):在整个请求生命周期中发生错误时执行。可以对错误进行处理,如记录错误日志、返回自定义错误信息等。
通过使用这四种过滤器类型,可以在Zuul网关中实现各种功能,如安全认证、请求转发、日志记录等。开发人员可以自定义各种过滤器,并将它们按照需要配置到Zuul网关中,以实现特定的功能和需求。