0%

微服务框架(二)——Spring Cloud

介绍

Spring Cloud provides tools for developers to quickly build some of the common patterns in distributed systems (e.g. configuration management, service discovery, circuit breakers, intelligent routing, micro-proxy, control bus, one-time tokens, global locks, leadership election, distributed sessions, cluster state). Coordination of distributed systems leads to boiler plate patterns, and using Spring Cloud developers can quickly stand up services and applications that implement those patterns. They will work well in any distributed environment, including the developer’s own laptop, bare metal data centres, and managed platforms such as Cloud Foundry.

Spring Cloud 是一系列框架的有序集合,它利用 SpringBoot 的开发便利性,巧妙地简化了分布式系统的基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以做到一键启动和部署。

选用 Spring Cloud 的好处包括

  • 基于 HTTP 协议,使用 RESTFUL 风格,接口简单方便,高效透明(Dubbo 是使用 RPC 协议,性能稍优于 HTTP 协议,但是耦合度更高)

核心成员

  • 服务注册中心:Spring Cloud Netflix Eureka
  • 服务监控:SpringBoot Admin
  • 断路器:Spring Cloud Netflix Hystrix
  • 服务网关:Spring Cloud Netflix Zuul
  • 分布式配置:Spring Cloud Config
  • 服务跟踪:Spring Cloud Sleuth
  • 消息总线:Spring Cloud Bus
  • 数据流:Spring Cloud Stream
  • 批量任务:Spring Cloud Task
  • 服务调用方式:RESTFUL API

Spring Cloud Eureka

Eureka 是 Netflix 开发的服务发现组件,本身是一个基于 REST 的服务,主要用于定位运行在 AWS 域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的。Spring Cloud 将其集成在其子项目 spring-cloud-netflix 上,以实现 Spring Cloud 的服务发现功能。

我们可以将自定义的 API 接口注册到 Spring Cloud Eureka 上,Eureka 负责服务的注册与发现,它的角色与 ZooKeeper 差不多,都是服务的注册与发现。所以,构成 Eureka 体系的包括:服务注册中心、服务提供者、服务消费者,主要包含两个组件:Eureka Server 和 Eureka Client。

High Level ArchitectureHigh Level Architecture

The architecture above depicts how Eureka is deployed at Netflix and this is how you would typically run it. There is one eureka cluster per region which knows only about instances in its region. There is at the least one eureka server per zone to handle zone failures.

Services register with Eureka and then send heartbeats to renew their leases every 30 seconds. If the client cannot renew the lease for a few times, it is taken out of the server registry in about 90 seconds. The registration information and the renewals are replicated to all the eureka nodes in the cluster. The clients from any zone can look up the registry information (happens every 30 seconds) to locate their services (which could be in any zone) and make remote calls.

Eureka Server 提供服务注册功能,提供者节点启动后,会在 Eureka Server 中进行注册,所以 Eureka Server 的服务注册表中将会存储所有可用服务节点的信息。各个提供者会向 Euraka Server 发送心跳,以告知 Eureka Server 自己的健康状况,默认周期为 30 秒。如果在多个心跳周期内都没有接收到某个提供者节点的心跳,那么 Eureka Server 就会认为其已经无法提供服务,就会将该节点从服务注册表中移除。Eureka Server 之间是通过复制的方式完成数据的同步。

Eureka Client 是一个 Java 客户端,是用于简化消费者与 Eureka Server 的交互。同时,Eureka Client 内置有负载均衡器,为消费者从 Eureka Server 的服务注册表中选择合适的提供者。

Eureka 提供了客户端缓存机制,即使所有的 Eureka Server 都宕机,客户端仍然能够利用缓存的信息为消费者提供服务发现功能。但此时就不再接受服务注册。

综上,Eureka 通过心跳检查、客户端缓存等机制,确保了系统的高可用性、灵活性和可伸缩性。

Spring Cloud Hystrix

Hystrix 的意思是豪猪,所以,它表明了框架的主要功能:自我保护功能。Hystrix 是一个用于处理分布式系统的延迟和容错的开源库。Hystrix 具有服务降级,熔断,线程池隔离,信号量隔离,缓存等功能。它能够保证在一个依赖出现问题的情况下,不会倒置整体服务失败,避免级联故障,提高分布式系统的弹性。

「断路器」本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似保险熔断),向调用方法返回一个符合预期的,可处理的被选相应(FallBack 降级操作),而不是长时间的等待或者抛出无法处理的异常。这样保证了服务调用方法的线程不会长时间,不必要地占用,从而避免了故障在分布式系统中的蔓延,从而导致雪崩效应。

如下图所示,断路器有对应的三个阶段:

  • 第一阶段:正常
  • 第二阶段:发现超时或者失败后,标识失败
  • 第三阶段:达到阈值之后,触发了熔断器策略,标识服务不可用,熔断器就自动断开。如果此时 B 对 C 有访问,熔断器会给 B 立刻返回失败,不再调用 C。同时进行间断性尝试,判断服务是否恢复

Hystrix 的三种情况Hystrix 的三种情况

Hystrix 存在三种模式:

  • 断路器模式:设置超时或者失败等熔断策略
  • 后备策略模式:在第二阶段或者第三阶段失败时,如果存在后备策略,都会去执行后备策略
  • 舱壁模式:保证一个服务独享一个线程池

所以,Hystrix 的功能执行如下:

  • 熔断触发前,超时或者失败发生时:
    • 如果存在后备策略,执行后备策略
    • 如果不存在后备策略,抛出异常处理
  • 在熔断触发之前后,立即返回失败,保护下游失败
    • 存在后备策略,则执行
    • 不存在,则抛出异常
  • 在熔断器触发了之后,还可以定期检查服务是否正常,将服务恢复正常

Spring Cloud Zuul

Spring Cloud Zuul 是 Spring Cloud Netflix 子项目的核心组件之一,可以作为微服务架构中的 API 网关使用,支持动态请求路由、负载均衡、效验过滤、服务容错、服务聚合等功能。API 网关为微服务架构中的服务提供了统一的访问入口,客户端通过 API 网关访问相关服务。

Zuul 的核心是一系列的 Filters,其作用类比于 Servlet 框架的 Filter,或者 AOP。其大部分功能都是通过过滤器来实现的,它们能够执行非常大范围的操作,并且可以在请求-响应生命周期的不同阶段运行,如下图所示:

ZuulZuul

其定义了四种标准过滤器类型:

  • PRE:这种过滤器在请求被路由之前调用。可以用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等
  • ROUTING:这种过滤器是用于构建发送给微服务的请求,并使用 Apache HttpClient 或者 Netflix Ribbon 请求微服务
  • POST:这种过滤器在路由到微服务以后执行,可用来为响应添加标准的 HTTP Header、收集统计信息和指标、将相应从微服务发回给客户端等
  • ERROR:在其它阶段发生错误时执行该过滤器

Zuul 四种标准过滤器模型Zuul 四种标准过滤器模型

Spring Cloud Config

在分布式系统中,因为服务数量很多,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件。在 Spring Cloud 中,有分布式配置中心组件 Spring Cloud Config,它支持配置服务放在配置服务的内存中(本地),也支持放在远程 Git 中。

在 Spring Cloud Config 组件中,分两个角色:

  • Config Server:一个可横向扩展、集中式的配置服务器,它用于集中管理应用程序各个环境下的配置,为客户端提供获取配置信息、加密、解密信息等访问接口
  • Config Client:是 Config Server 的客户端,是微服务架构中的各个微服务应用或基础设施,通过指定的配置中心来管理应用资源与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息。

基于消息总线的配置中心架构需要依赖外部的MQ组件,例如 RabbitMQ 或者 Kafka 等实现远程环境变更通知,客户端实时配置变更可以基于 Git Hook 功能实现。

Spring Cloud Sleuth

随着微服务部署的节点增多,以及对各个微服务的拆分后,对服务本身的日志和调用链路的监控变得更加困难。Spring Cloud Sleuth 就是为了解决分布式链路追踪这个问题而生的。

Spring Cloud Sleuth 的实体概念主要来源于谷歌在 2010 年发表的一篇论文:《Dapper, a Large-Scale Distributed Systems Tracing Infrastructure》:

  • Span:基本工作单元。发送RPC就是一个新的 span,就像 RPC 发送响应那样。Span 携带了 span 的唯一 64 位标识、另外一个 Trace 的 64 位的标识。Span 还有其余的数据,例如描述、带时间戳的事件、键值 annotations(标签)等。
  • Trace:一组 span 造成的树状结构;
  • Annotation:用于及时记录事件的存在

微服务日志追踪主要包括:

  • 日志输出
  • 日志收集
  • 分布式链路追踪:以集成 Zipkin 服务为基础,准备 4 个微服务工程:
    • eureka server:复杂服务注册
    • zipkin server:负责链路数据收集以及查询
    • zuul-gateway:服务网关,负责调用
    • personal-service:作为后台 server,负责调用

Spring Cloud Bus

Spring Cloud Config 的作用的帮助更新配置文件,即配置文件可以通过 Config Server 存储到 Git 地方,通过 Config Client 进行读取。但是配置发生变化时,又是如何进行更新的呢?

一种简单的方式是关闭服务,重新让 Config Client 进行获取。但是这样需要关闭服务,Spring Cloud 肯定不允许这样做。那么,它需要通过「消息总线」的方式来进行通知。

这套机制是:我们使用消息代理来构建一个 Topic,然后把微服务架构中的所有服务都连接到这个主题上,当我们向该主题发送消息时,所有订阅了该主题的服务都会收到消息并进行消费。目前 Spring Cloud Bus 支持两种主流的消息代理:RabbitMQ 和 Kafka。

Spring Cloud Bus 的执行步骤Spring Cloud Bus 的执行步骤

从上图可以看出 Spring Cloud Bus 的执行步骤:

  • 提交代码给客户端 A
  • 客户端 A 收到了请求,从 Server 端更新配置,发送给 Spring Cloud Bus
  • Spring Cloud Bus 接收到消息,通知其它的客户端
  • 其它客户端接收到通知,请求 Server 端,获取最新的配置
  • 这样,全部的客户端都能获取到更新的配置

Spring Cloud Stream

Spring Cloud Stream 在 Spring Cloud 体系内用于构建高度可扩展的基于事件驱动的微服务。而 SCS(Spring Cloud Stream) 是在 Spring Message 和 Spring Integration 两个项目的基础上完成构建的。

Spring Message 模块是 Spring Framework 的一个模块,其作用就是统一消息的编程模型。

生产者 Producer 发送消息到消息通道 Message Channel中,消费者 Consumer 调用receive()方法从消息通道中获取到消息。

Spring Integration 提供了 Spring 编程模型的扩展,用来支持企业集成模式(Enterprise Integration Patterns)。

Spring Integration 是对 Spring Messaging 的扩展。它提出了不少新的概念,包括消息的路由 MessageRoute、消息的分发 MessageDispatcher、消息过滤 Filter、消息转换 Transfoer、消息聚合 Aggregator、消息分隔 Splitter等等。


SCS 则是 Spring Integration 的加强,同时与 SpringBoot 体系融合,也是 Spring Cloud Bus 的基础。它屏蔽了底层消息中间件的实现细节,希望以统一的一套 API 来进行消息的发送/消费,底层消息中间件的实现细节由各消息中间件的 Binder 来完成

Binder 细节Binder 细节

Binder 是提供与外部消息中间件集成的组件,会构造 Binding,内部构造实现生产者和消费者。它是连接应用程序跟消息中间件的桥梁,用于消息的消费和生产

SCS 解决了开发人员无感知的使用消息中间件的问题,因为 SCS 对消息中间件的进一步封装,可以做到代码层面对中间件的无感知,甚至还可以动态切换中间件。这使得微服务开发的高度解耦,服务可以主要关注自己的流程。

Spring Cloud Task

Spring Cloud Task 允许用户使用 Spring Cloud 开发和运行短期微服务,并在云和本地运行,甚至还可以在 Spring Cloud Data Flow 上运行。

Spring Cloud Task 主要是来解决short lived microservices的问题的。因为一般的应用服务都是长时间运转的不停止的,但是有些服务却具有以下特点:

  • 定时的服务
  • 临时的服务
  • 占用资源过多的服务

这些服务因为重要性偏低,所以可以交个 Spring Cloud Task 来执行。除此之外,有些任务是串联的。一个业务会牵扯到多个业务,任务之间是通过事件触发的,这就是 Spring Cloud Stream 来解决的。