深入理解 Spring Cloud 核心组件 底层原理

PHP是最好的 2020-11-10 13:10:44 ⋅ 806 阅读

搜云库技术团队:https://mp.weixin.qq.com/s/_KCBWTPvFQ2QsM4P8-gqTQ

之前一直在看 Spring Cloud 及微服务架构 对 Spring Cloud 的主要组件的原理有了更深入一点的理解,特地做一下总结。

一、Spring Cloud核心组件:Eureka

Netflix Eureka

1、Eureka服务端:也称服务注册中心,同其他服务注册中心一样,支持高可用配置。如果Eureka以集群模式部署,当集群中有分片出现故障时,那么Eureka就转入自我保护模式。它允许在分片故障期间继续提供服务的发现和注册,当故障分片恢复运行时,集群中其他分片会把它们的状态再次同步回来

2、Eureka客户端:主要处理服务的注册与发现。客户端服务通过注解和参数配置的方式,嵌入在客户端应用程序的代码中,在应用程序运行时,Eureka客户端想注册中心注册自身提供的服务并周期性地发送心跳来更新它的服务租约。同时,它也能从服务端查询当前注册的服务信息并把它们缓存到本地并周期性地刷新服务状态

3、Eureka Server 的高可用实际上就是将自己作为服务向其他注册中心注册自己,这样就可以形成一组互相注册的服务注册中心,以实现服务清单的互相同步,达到高可用效果

Eureka详解

1、服务提供者

A.服务注册

服务提供者在启动的时候会通过发送REST请求的方式将自己注册到Eureka Server上,同时带上了自己服务的一些元数据信息。Eureka Server接收到这个REST请求之后,将元数据信息存储在一个双层结构Map中,其中第一层的key是服务名,第二层的key是具体服务的实例名

B.服务同步

两个服务提供者分别注册到了两个不同的服务注册中心上,也就是说,它们的信息分别被两个服务注册中心所维护。此时,由于服务注册中心之间因互相注册为服务,当服务提供者发送注册请求到一个服务注册中心时,它会将该请求转发给集群中相连的其他注册中心,从而实现注册中心之间的服务同步。通过服务同步,两个服务提供者的服务信息就可以通过这两台服务注册中心中的任意一台获取到

C.服务续约

在注册完服务之后,服务提供者会维护一个心跳用来持续告诉Eureka Server:“我还活着”,以防止Eureka Server的剔除任务将该服务实例从服务列表中排除出去,我们称该操作为服务续约

  1. # 定义服务续约任务的调用间隔时间,默认30秒

  2. eureka.instance.lease-renewal-interval-in-seconds=30

  3. # 定义服务失效的时间,默认90秒

  4. eureka.instance.lease-expiration-duration-in-seconds=90

2、服务消费者

A.获取服务

当我们启动服务消费者的时候,它会发送一个REST请求给服务注册中心,来获取上面注册的服务清单。为了性能考虑,Eureka Server会维护一份只读的服务清单来返回给客户端,同时该缓存清单会每隔30秒更新一次

  1. # 缓存清单的更新时间,默认30秒

  2. eureka.client.registry-fetch-interval-seconds=30

B.服务调用

服务消费者在获取服务清单后,通过服务名可以获得具体提供服务的实例名和该实例的元数据信息。在Ribbon中会默认采用轮询的方式进行调用,从而实现客户端的负载均衡

对于访问实例的选择,Eureka中有Region和Zone的概念,一个Region中可以包含多个Zone,每个服务客户端需要被注册到一个Zone中,所以每个客户端对应一个Region和一个Zone。在进行服务调用的时候,优先访问同处一个一个Zone中的服务提供方,若访问不到,就访问其他的Zone

C.服务下线

当服务实例进行正常的关闭操作时,它会触发一个服务下线的REST请求给Eureka Server,告诉服务注册中心:“我要下线了”。服务端在接收到请求之后,将该服务状态置为下线(DOWN),并把该下线事件传播出去

3、服务注册中心

A.失效剔除

Eureka Server在启动的时候会创建一个定时任务,默认每隔一段时间(默认为60秒)将当前清单中超时(默认为90秒)没有续约的服务剔除出去

B.自我保护

在服务注册中心的信息面板中出现红色警告信息:

该警告就是触发了Eureka Server的自我保护机制。Eureka Server在运行期间,会统计心跳失败的比例在15分钟之内是否低于85%,如果出现低于的情况,Eureka Server会将当前的实例注册信息保护起来,让这些实例不会过期,尽可能保护这些注册信息。但是,在这段保护期间内实例若出现问题,那么客户端很容易拿到实际已经不存在的服务实例,会出现调用失败的情况,所以客户端必须要有容错机制,比如可以使用请求重试、断路器等机制

  1. # 关闭保护机制,以确保注册中心可以将不用的实例正确剔除(本地调试可以使用,线上不推荐)

  2. eureka.server.enable-self-preservation=false

二、Spring Cloud核心组件:Ribbon

Ribbon是一个基于HTTP和TCP的客户端负载均衡器,它可以在通过客户端中配置的ribbonServerList服务端列表去轮询访问以达到服务均衡的作用。当Ribbon和Eureka联合使用时,Ribbon的服务实例清单RibbonServerList会被DiscoveryEnabledNIWSServerList重写,扩展成从Eureka注册中心中获取服务端列表。同时它也会用NIWSDiscoveryPing来取代IPing,它将职责委托给Eureka来去定服务端是否已经启动

在客户端负载均衡中,所有客户端节点都维护着自己要访问的服务端清单,而这些服务端的清单来自于服务注册中心(比如Eureka)。在客户端负载均衡中也需要心跳去维护服务端清单的健康性,只是这个步骤需要与服务注册中心配合完成。整编:微信公众号,搜云库技术团队,ID:souyunku

通过Spring Cloud Ribbon的封装,我们在微服务架构中使用客户端负载均衡调用只需要如下两步:

1、服务提供者只需要启动多个服务实例并且注册到一个注册中心或是多个相关联的服务注册中心

2、服务消费者直接通过调用被@LoadBalanced注解修饰过的RestTemplate来实现面向服务的接口调用

三、Spring Cloud核心组件:Feign

Feign的关键机制是使用了动态代理

1、首先,对某个接口定义了@FeignClient注解,Feign就会针对这个接口创建一个动态代理

2、接着调用接口的时候,本质就是调用Feign创建的动态代理

3、Feign的动态代理会根据在接口上的@RequestMapping等注解,来动态构造要请求的服务的地址

4、针对这个地址,发起请求、解析响应

Feign是和Ribbon以及Eureka紧密协作的

1、首先Ribbon会从Eureka Client里获取到对应的服务注册表,也就知道了所有的服务都部署在了哪些机器上,在监听哪些端口

2、然后Ribbon就可以使用默认的Round Robin算法,从中选择一台机器

3、Feign就会针对这台机器,构造并发起请求

四、Spring Cloud核心组件:Hystrix

在微服务架构中,存在着那么多的服务单元,若一个单元出现故障,就很容易因依赖关系而引发故障的蔓延,最终导致整个系统的瘫痪,这样的架构相较传统架构更加不稳定。为了解决这样的问题,产生了断路器等一系列的服务保护机制

在分布式架构中,当某个服务单元发生故障之后,通过断路器的故障监控,向调用方返回一个错误响应,而不是长时间的等待。这样就不会使得线程因调用故障服务被长时间占用不释放,避免了故障在分布式系统中的蔓延

Hystrix具备服务降级、服务熔断、线程和信号隔离、请求缓存、请求合并以及服务监控等强大功能

Hystrix使用舱壁模式实现线程池的隔离,它会为每一个依赖服务创建一个独立的线程池,这样就算某个依赖服务出现延迟过高的情况,也只是对该依赖服务的调用产生影响,而不会拖慢其他的依赖服务

五、Spring Cloud核心组件:Zuul

Spring Cloud Zuul通过与Spring Cloud Eureka进行整合,将自身注册为Eureka服务治理下的应用,同时从Eureka中获得了所有其他微服务的实例信息

对于路由规则的维护,Zuul默认会将通过以服务名作为ContextPath的方式来创建路由映射

Zuul提供了一套过滤器机制,可以支持在API网关无附上进行统一调用来对微服务接口做前置过滤,已实现对微服务接口的拦截和校验。整编:微信公众号,搜云库技术团队,ID:souyunku

六、总结

Eureka:各个服务启动时,Eureka Client都会将服务注册到Eureka Server,并且Eureka Client还可以反过来从Eureka Server拉取注册表,从而知道其他服务在哪里

Ribbon:服务间发起请求的时候,基于Ribbon做负载均衡,从一个服务的多台机器中选择一台

Feign:基于Feign的动态代理机制,根据注解和选择的机器,拼接请求URL地址,发起请求

Hystrix:发起请求是通过Hystrix的线程池来走的,不同的服务走不同的线程池,实现了不同服务调用的隔离,避免了服务雪崩的问题

Zuul:如果前端、移动端要调用后端系统,统一从Zuul网关进入,由Zuul网关转发请求给对应的服务

全部评论: 0

    我有话说:

    构建数据集成和实时数据处理流水线工具Spring Cloud Data Flow

    Spring Cloud Data Flow 是基于原生云对 Spring XD 的重新设计

    Spring Cloud(Greenwich版)-06-Spring Cloud集成Feign

    Spring Cloud系列教程第6节-Spring Cloud集成Feign

    Spring Cloud快速搭建开放平台解决方案

    基于Spring Cloud开放平台解决方案 SOP

    Spring Cloud Alibaba 发布毕业后的首个版本

    方剑,花名洛夜,GitHub ID @fangjian0423,开源爱好者,阿里巴巴高级开发工程师,阿里云产品 EDAS 开发,Spring Cloud Alibaba 开源项目负责人。

    Spring Cloud(Greenwich版)-03-编写高可用Eureka Server(集群)

    前言 上一章Spring Cloud(Greenwich版)-02-服务注册与服务发现-Eureka入门,我们实现了将User和Goods微服务都注册到了Eureka上,那么在生产环境中为了达到高

    码云推荐:一个优秀的分布式spring boot/Spring Cloud API限流框架,特别适合微服务架构

    一个优秀的分布式spring boot/Spring Cloud API限流框架,特别适合微服务架构.

    10分钟看懂,Java NIO 底层原理

    目录 写在前面 1.1. Java IO读写原理 1.1.1. 内核缓冲与进程缓冲区 1.1.2. java IO读写的底层流程 1.2. 四种主要的IO模型 1.3

    【轻阅读】基于 Java Spring cloud的开源在线教育系统调试实战

    转载自:https://www.toutiao.com/i6759167063090004483开篇之前分享

    MateCloud 3.2.8 版本发布,基于 Spring Cloud Alibaba 的微服务平台

    软件简介 MateCloud 是一款基于Spring Cloud Alibaba的微服务架构。目前已经整合 Spring Cloud Gateway、Spring Security

    Spring Cloud Data Flow 2.7.1 发布

    Spring Cloud Data Flow 2.7.1 发布了。Spring Cloud Data Flow 是构建数据集成和实时数据处理流水线的工具包。 主要更新内容 UI 错误修复

    微服务架构学习笔记:gRPC Spring Boot Starter 2.2.0 发布,及使用步骤

    gRPC Spring Boot Starter 项目是一个 gRPC 的 Spring Boot 模块。内嵌一个 gRPC Server 对外提供服务,并支持 Spring Cloud 的服务发现

    Spring Cloud 2020.0.1 BUG 修复版本发布

    2021 首发, Spring Cloud 2020.0.1 (代号"Ilford",伊尔福德)版本发布,此版本 BUG 修复版本,可从 2020.0.0 版本平滑升级。目前已可以从 maven

    【SpringCloud实战】一次开发中使用Feign添加动态Header问题思考

    踩了一个Spring Cloud Feign添加自定义Header的坑,分享给大家

    Fluid 0.3 正式发布:实现云原生场景通用化数据加速

    简介 为了解决大数据、AI 等数据密集型应用在云原生计算存储分离场景下,存在的数据访问延时高、联合分析难、多维管理杂等痛点问题,南京大学 PASALab、阿里巴巴、Alluxio 在 2020 年

    Spring Boot 开发利器

    工欲善其事,必先利其器每次创建新项目都要找各种依赖的包是不是很烦?今天给大家介绍下 Spring 官方提供的 Online 项目脚手架