一、Spring官方文档
二、Spring Cloud 是什么?
https://github.com/spring-cloud
Spring Cloud 基于 Spring Boot,为微服务体系开发中的架构问题,提供了一整套的解决方案——服务注册与发现,服务消费,服务保护与熔断,网关,分布式调用追踪,分布式配置管理等。
Spring Boot 是 Spring 的一套快速配置脚手架,使用默认大于配置的理念,用于快速开发单个微服务。
重点:
-
基于 Spring Boot
-
云服务、分布式框架集合(众多)
核心功能:
-
分布式/版本化配置
-
服务注册和发现
-
路由
-
服务和服务之间的调用
-
负载均衡
-
断路器
-
分布式消息传递
三、Spring Cloud 完整技术
四、Spring Cloud 组件架构
流程:
-
请求统一通过 API 网关(Zuul)来访问内部服务。
-
网关接收到请求后,从注册中心(Eureka)获取可用服务。
-
由 Ribbon 进行均衡负载后,分发到后端具体实例。
-
微服务之间通过 Feign 进行通信处理业务。
-
Hystrix 负责处理服务超时熔断。
-
Turbine 监控服务间的调用和熔断相关指标。
五、Spring Cloud微服务组件
Spring Cloud为开发者提供了快速构建分布式系统的通用模型的工具(包括配置管理,服务发现,熔断器,智能路由,微代理,控制总线,一次性令牌,全局锁,领导选举,分布式会话,集群状态等)。 主要项目包括:
-
Spring Cloud Config :配置中心,由git存储库支持的集中式外部配置管理。配置资源直接映射到Spring Environment,但是如果需要可以被非Spring应用程序使用。
-
Spring Cloud Netflix :集成众多Netflix的开源软件。
-
Spring Cloud Netflix Eureka :服务中心(类似于管家的概念,需要什么直接从这里取,就可以了),一个基于 REST 的服务,用于定位服务,以实现云端中间层服务发现和故障转移。
-
Spring Cloud Netflix Hystrix :熔断器,容错管理工具,旨在通过熔断机制控制服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。
-
Spring Cloud Netflix Zuul :网关,是在云平台上提供动态路由,监控,弹性,安全等边缘服务的框架。Web 网站后端所有请求的前门。
-
Spring Cloud Netflix Archaius :配置管理 API,包含一系列配置管理API,提供动态类型化属性、线程安全配置操作、轮询框架、回调机制等功能。
-
Spring Cloud Netflix Ribbon :负载均衡。
-
Spring Cloud Netflix Fegin :REST客户端。
-
Spring Cloud Bus:消息总线,用于将服务和服务实例与分布式消息传递联系起来的事件总线。用于在集群中传播状态更改(例如配置更改事件)。
-
Spring Cloud for Cloud Foundry:将您的应用程序与Pivotal Cloudfoundry集成。提供服务发现实现,还可以轻松实现通过SSO和OAuth2保护资源,还可以创建Cloudfoundry服务代理。
-
Spring Cloud Cloud Foundry Service Broker:提供构建管理一个Cloud Foundry中服务的服务代理的起点。
-
Spring Cloud Cluster:集群工具,领导选举和通用状态模型(基于zookeeper,redis,hazelcast,Consul的抽象和实现)。
-
Spring Cloud Consul:基于Hashicorp Consul 实现的服务发现和配置管理。
-
Spring Cloud Security:安全控制,在Zuul代理中为负载平衡的OAuth2休眠客户端和认证头中继提供支持。
-
Spring Cloud Sleuth:分布式链路监控,适用于Spring Cloud应用程序的分布式跟踪,与Zipkin,HTrace和基于日志(例如ELK)跟踪兼容。
-
Spring Cloud Data Flow:针对现代运行时的可组合微服务应用程序的云本地编排服务。易于使用的DSL,拖放式GUI和REST-API一起简化了基于微服务的数据管道的整体编排。
-
Spring Cloud Stream:消息组件,轻量级事件驱动的微服务框架,可快速构建可连接到外部系统的应用程序。使用Apache Kafka或RabbitMQ在Spring Boot应用程序之间发送和接收消息的简单声明式模型。
-
Spring Cloud Stream App Starters:Spring Cloud任务应用程序启动器是Spring Boot应用程序,可能是任何进程,包括不会永远运行的Spring Batch作业,并且它们在有限时间的数据处理之后结束/停止。
-
Spring Cloud Zookeeper:Zookeeper的服务发现和配置管理。
-
Spring Cloud for Amazon Web Services:轻松集成托管的Amazon的Web Services服务。它通过使用spring的idioms和APIs便捷集成AWS服务,例如缓存或消息API。开发人员可以围绕托管服务,不必关心基础架构来构建应用。
-
Spring Cloud Connectors:使PaaS应用程序在各种平台上轻松连接到后端服务,如数据库和消息代理(以前称为“Spring Cloud”的项目)。
-
Spring Cloud Starters:作为基于spring boot的启动项目,降低依赖管理(在Angel.SR2后,不在作为独立项目)。
-
Spring Cloud CLI:命令行工具,插件支持基于Groovy预言快速创建spring cloud的组件应用。
六、Spring Cloud常用组件介绍
6.1、服务发现——Netflix Eureka
我们使用微服务,微服务的本质还是各种API接口的调用,那么我们怎么产生这些接口、产生了这些接口之后如何进行调用那?如何进行管理哪?
答案就是Spring Cloud Eureka,我们可以将自己定义的API 接口注册到Spring Cloud Eureka上,Eureka负责服务的注册于发现,如果学习过Zookeeper的话,就可以很好的理解,Eureka的角色和 Zookeeper的角色差不多,都是服务的注册和发现,构成Eureka体系的包括:服务注册中心、服务提供者、服务消费者。
Eureka和Consul、Zookeeper类似,是一个用于服务注册和发现的组件,最初开始用于亚马逊公司旗下的云计算服务平台(AWS)。Eureka采用了C-S的设计架构。分为EurekaServer和EurekaClient,EurekaServer即服务的注册中心;EurekaClient为Eureka客户端(javaclient)。EurekaServer作为服务注册功能的服务器,它是服务注册中心,维护注册上来的服务信息。EurekaClient作为作为客户服务的一个依赖,用来连接到EurekaServer注册自身服务实例信息并维持心跳连接。Eureka是Netflix公司完全开源产品,而且它经历了Netflix公司的生产环境考验,在功能和性能上都非常稳定,可以放心使用。
其次,Eureka是SpringCloud(早期版本)首选推荐的服务注册与发现组件,能够与SpringCloud其他组件无缝对接。比如负载均衡组件Ribbon、熔断器组件Hystrix、熔断器监控组件HystrixDashboard组件、熔断器聚合监控Turbine组件,以及网关Zuul组件相互配合,能够很容易实现服务注册、负载均衡、熔断和智能路由等功能。
Eureka Server 提供的三个主要功能:
服务注册 服务提供者启动时,会通过 Eureka Client 向 Eureka Server 注册信息,Eureka Server 会存储该服务的信息。
提供注册表 服务消费者在调用服务时,如果 Eureka Client 没有缓存注册表的话,会从 Eureka Server 获取最新的注册表。
同步状态 Eureka Client 通过注册、心跳机制和 Eureka Server 同步当前客户端的状态。
服务实例主要有 UP、DOWN、STARING、OUT_OF_SERVICE、UNKNOWN 几 种状态。其中 OUT_OF_SERVICE 标识停止服务,即停止接收请求,处于这个状态 的服务实例将不会被路由到,经常用于升级部署的场景。
上图中描述了:
1、两台Eureka服务注册中心构成的服务注册中心的主从复制集群;
2、然后服务提供者向注册中心进行注册、续约、下线服务等;
3、服务消费者向Eureka注册中心拉去服务列表并维护在本地(这也是客户端发现模式的机制体现!);
4、然后服务消费者根据从Eureka服务注册中心获取的服务列表选取一个服务提供者进行消费服务。
6.1.1、nacos
为什么使用nacos作为注册中心?nacos提供了基础的服务注册与发现以及服务健康检查功能。相比于其他服务治理工具: Eureka、Consul、Zookeeper、CoreDNS。Nacos 支持的功能相对来说更全面。 对比之前的服务治理组件Eureka来说:
1、Nacos支持CP、AP协议,默认服务注册是AP协议。Eureka只支持AP协议。
2、对于开发框架的支持,Nacos支持SpringCloud、Dubbo开发的应用注册,Eureka只支持基于SpringCloud框架开发的应 用。
3、Nacos支持多数据中心(Nacos、Zookeeper、Eureka、Consul)的注册数据同步,Eureka不支持同步。
4、Nacos支持K8s。
5、Nacos不仅提供服务注册的共能,还提供服务配置的功能。相当于:Nacos=Eureka+Config两部分的功能。
Nacos相关名词解释:
-
命名空间:用于进行租户粒度的配置隔离。不同的命名空间下,可以存在相同的 Group 或 Data ID 的配置。Namespace 的常 用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。
-
配置管理:系统配置的编辑、存储、分发、变更管理、历史版本管理、变更审计等所有与配置相关的活动。
-
配置集 ID:Nacos 中的某个配置集的 ID。配置集 ID 是组织划分配置的维度之一。Data ID 通常用于组织划分系统的配置 集。
-
服务名:服务提供的标识,通过该标识可以唯一确定其指代的服务。
-
服务分组:不同的服务可以归类到同一分组。
-
健康保护阈值:为了防止因过多实例 (Instance) 不健康导致流量全部流向健康实例 (Instance) ,继而造成流量压力把健康 健康实例 (Instance) 压垮并形成雪崩效应,应将健康保护阈值定义为一个 0 到 1 之间的浮点数。当域名健康实例 (Instance) 占总服务实例 (Instance) 的比例小于该值时,无论实例 (Instance) 是否健康,都会将这个实例 (Instance) 返回 给客户端。这样做虽然损失了一部分流量,但是保证了集群的剩余健康实例 (Instance) 能正常工作。
6.2、客服端负载均衡——Netflix Ribbon
Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。
在上Spring Cloud Eureka描述了服务如何进行注册,注册到哪里,服务消费者如何获取服务生产者的服务信息,但是Eureka只是维护了服务生产者、注册中心、服务消费者三者之间的关系,真正的服务消费者调用服务生产者提供的数据是通过Spring Cloud Ribbon来实现的。
在(1)中提到了服务消费者是将服务从注册中心获取服务生产者的服务列表并维护在本地的,这种客户端发现模式的方式是服务消费者选择合适的节点进行访问服务生产者提供的数据,这种选择合适节点的过程就是Spring Cloud Ribbon完成的。
Spring Cloud Ribbon客户端负载均衡器由此而来。
6.3、REST客户端——Spring Cloud Feign
上述(1)、(2)中我们已经使用最简单的方式实现了服务的注册发现和服务的调用操作,如果具体的使用Ribbon调用服务的话,你就可以感受到使用Ribbon的方式还是有一些复杂,因此Spring Cloud Feign应运而生。
Spring Cloud Feign 是一个声明web服务客户端,这使得编写Web服务客户端更容易,使用Feign 创建一个接口并对它进行注解,它具有可插拔的注解支持包括Feign注解与JAX-RS注解,Feign还支持可插拔的编码器与解码器,Spring Cloud 增加了对 Spring MVC的注解,Spring Web 默认使用了HttpMessageConverters, Spring Cloud 集成 Ribbon 和 Eureka 提供的负载均衡的HTTP客户端 Feign。
简单的可以理解为:Spring Cloud Feign 的出现使得Eureka和Ribbon的使用更为简单。
6.4、断路器——Netflix Hystrix
为了保证其高可用,单个服务通常会集群部署。由于网络原因或者自身的原因,服务并不能保证100%可用,如果单个服务出现问题,调用这个服务就会出现线程阻塞,此时若有大量的请求涌入,Servlet容器的线程资源会被消耗完毕,导致服务瘫痪。服务与服务之间的依赖性,故障会传播,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的“雪崩”效应。
Spring Cloud Hystrix 是一个延迟和容错库,旨在隔离远程系统、服务和 第三方库,阻止级联故障,能够在复杂的分布式系统中实现恢复能力。 Hystrix 是通过隔离服务的访问点阻止联动故障的,并提供了故障的解决方 案,从而提高了整个分布式系统的弹性。为了防止“雪崩效应”事件的发 生,Spring Cloud 构建的微服务系统采用了熔断器 Hystirx 的 Circuit Breaker 组件做了熔断处理。
Hystrix 设计的目标是:
-
对通过第三方客户端库访问的依赖项(通常是通过网络)的延迟和故 障进行保护和控制。
-
在复杂的分布式系统中阻止级联故障。
-
快速失败,快速恢复。
-
回退,尽可能优雅地降级。
-
启用近实时监控、警报和操作控制。
6.4.1、熔断场景
1)服务提供者不可用
➢硬件故障:硬件损坏造成的服务器主机宕机, 网络硬件故障造成的服务提供者的不可访问
➢程序 Bug
➢缓存击穿:缓存击穿一般发生在缓存应用重启,所有缓存被清空时,以及短时间内大量缓存失效时。大量 的缓存不命中,使请求直击后端,造成服务提供者超负荷运行,引起服务不可用
➢用户大量请求:在秒杀和大促开始前,如果准备不充分,用户发起大量请求也会造成服务提供者的不可用
2)重试加大流量
➢用户重试:在服务提供者不可用后,用户由于忍受不了界面上长时间的等待,而不断刷新页面甚至提交表 单
➢代码逻辑重试:服务调用端的会存在大量服务异常后的重试逻辑
3)服务调用者不可用同步等待造成的资源耗尽:当服务调用者使用同步调用时,会产生大量的等待线程占用系 统资源。 一旦线程资源被耗尽,服务调用者提供的服务也将处于不可用状态,于是服务雪崩效应产生了。
针对造成服务雪崩的不同原因,可以使用不同的应对策略。
流量控制
改进缓存模式
服务自动扩容
服务调用者降级服务
6.4.2、运行原理
-
开始时断路器处于关闭状态(Closed)。
-
如果调用服务持续出错、超时或失败率超过指定限制,断路器打开 进入熔断状态,后续一段时间内的所有请求都会被直接拒绝。
-
一段时间以后,保护器会尝试进入半熔断状态(Half-Open),允许少 量请求进来尝试;如果调用仍然失败,则回到熔断状态,如果调用 成功,则回到电路闭合状态;
我们在(1)、(2)、(3)中知道了使用Eureka进行服务的注册和发现,使用Ribbon实现服务的负载均衡调用,还知道了使用Feign可以简化我们的编码。但是,这些还不足以实现一个高可用的微服务架构。
例如:当有一个服务出现了故障,而服务的调用方不知道服务出现故障,若此时调用放的请求不断的增加,最后就会等待出现故障的依赖方 相应形成任务的积压,最终导致自身服务的瘫痪。
Spring Cloud Hystrix正是为了解决这种情况的,防止对某一故障服务持续进行访问。Hystrix的含义是:断路器,断路器本身是一种开关装置,用于我们家庭的电路保护,防止电流的过载,当线路中有电器发生短路的时候,断路器能够及时切换故障的电器,防止发生过载、发热甚至起火等严重后果。
6.5、分布式配置——Spring Cloud Config
SpringCloud Config提供服务器端和客户端。服务器存储后端的默认实现使用git,因此它轻松支持标签版本的配置环境,以及可以访问用于管理内容的各种工具。
对于微服务还不是很多的时候,各种服务的配置管理起来还相对简单,但是当成百上千的微服务节点起来的时候,服务配置的管理变得会复杂起来。
分布式系统中,由于服务数量巨多,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件。在Spring Cloud中,有分布式配置中心组件Spring Cloud Config ,它支持配置服务放在配置服务的内存中(即本地),也支持放在远程Git仓库中。在Cpring Cloud Config 组件中,分两个角色,一是Config Server,二是Config Client。
Config Server用于配置属性的存储,存储的位置可以为Git仓库、SVN仓库、本地文件等,Config Client用于服务属性的读取。
6.6、服务网关——Netflix Zuul
我们使用Spring Cloud Netflix中的Eureka实现了服务注册中心以及服务注册与发现;而服务间通过Ribbon或Feign实现服务的消费以及均衡负载;通过Spring Cloud Config实现了应用多环境的外部化配置以及版本管理。为了使得服务集群更为健壮,使用Hystrix的融断机制来避免在微服务架构中个别服务出现异常时引起的故障蔓延。
网关是一个服务器,是系统对外的唯一入口。网关封装了系统内部架构,为每个客户端提供一个路由。网关方式的核心要点是:所有的 客户端和消费端都通过统一的网关接入微服务,在网关层处理所有的非业务功能 微服务网关的作用和应用场景: 网关的具体的职责有:身份认证、监控、负载均衡、缓存、请求分片和管理、静态响应处理。当然,最主要的职责还是和外界联系 为什么需要网关: 不同的微服务一般会有不同的网络地址,客户端在访问这些微服务的时候需要记住几十甚至几百个地址,这对于客户端来说,是非常复杂 而且难以维护的 因此,我们需要一个微服务网关,介于客户端和服务器之间的中间层,所有的外部请求都会先经过微服务网关。客户端只需要和网关交 互,只需要知道一个网关地址即可,这样简化了开发,并且还有以下好处。
-
易于监控
-
易于认证
-
限流
-
扩展公共功能
-
减少了客户端和各个微服务之间的交互次数
先来说说这样架构需要做的一些事儿以及存在的不足:
1、首先,破坏了服务无状态特点。为了保证对外服务的安全性,我们需要实现对服务访问的权限控制,而开放服务的权限控制机制将会贯穿并污染整个开放服务的业务逻辑,这会带来的最直接问题是,破坏了服务集群中REST API无状态的特点。从具体开发和测试的角度来说,在工作中除了要考虑实际的业务逻辑之外,还需要额外可续对接口访问的控制处理。
2、其次,无法直接复用既有接口。当我们需要对一个即有的集群内访问接口,实现外部服务访问时,我们不得不通过在原有接口上增加校验逻辑,或增加一个代理调用来实现权限控制,无法直接复用原有的接口。
面对类似上面的问题,我们要如何解决呢?下面进入本文的正题:服务网关!
为了解决上面这些问题,我们需要将权限控制这样的东西从我们的服务单元中抽离出去,而最适合这些逻辑的地方就是处于对外访问最前端的地方,我们需要一个更强大一些的均衡负载器,它就是本文将来介绍的:服务网关。
服务网关是微服务架构中一个不可或缺的部分。通过服务网关统一向外系统提供REST API的过程中,除了具备服务路由、均衡负载功能之外,它还具备了权限控制等功能。Spring Cloud Netflix中的Zuul就担任了这样的一个角色,为微服务架构提供了前门保护的作用,同时将权限控制这些较重的非业务逻辑内容迁移到服务路由层面,使得服务集群主体能够具备更高的可复用性和可测试性。
6.7、消息总线——Spring Cloud Bus
在(5)Spring Cloud Config中,我们知道的配置文件可以通过Config Server存储到Git等地方,通过Config Client进行读取,但是我们的配置文件不可能是一直不变的,当我们的配置文件放生变化的时候如何进行更新哪?
一种最简单的方式重新一下Config Client进行重新获取,但Spring Cloud绝对不会让你这样做的,Spring Cloud Bus正是提供一种操作使得我们在不关闭服务的情况下更新我们的配置。
Spring Cloud Bus官方意义:消息总线。
当然动态更新服务配置只是消息总线的一个用处,还有很多其他用处。
6.8、调用链——Spring Cloud Bus
当我们开始微服务架构之后,我们的很多服务变成分布式的了,并且我 们对服务进行了拆分,拆分之后,用户的一个请求进来,会依次经过不同 的服务节点进行处理,处理完成后再返回结果给用户。那么在整个处理的 链条中,如果有任何一个节点出现了延迟或者问题,都有可能导致最终的 结果出现异常,有的时候不同的服务节点甚至是由不同的团队开发的、部 署在不同的服务器上,那么在这么错综复杂的环境下,我们想要排查出是 链条中的具体哪个服务节点出了问题,其实并不容易。
因此大家就想到了一个办法,将这个请求经过的每一个节点都记录下来, 形成一个完整的调用链监控系统,那么一旦发生请求调用异常的情况,只 需要去排查这个调用链日志就能很清楚看到出错的环节在哪儿。
在调用链监控系统中,有几个核心概念需要了解
-
Trace: 是指一次请求调用的链路过程,trace id 是指这次请求调用的ID。在一次请求中,会在网络的最开始生成一个全局 唯一的用于标识此次请求的trace id,这个trace id在这次请求调用过程中无论经过多少个节点都会保持不变,并且在随着 每一层的调用不停的传递。最终,可以通过trace id将这一次用户请求在系统中的路径全部串起来。
-
Span: 是指一个模块的调用过程,一般用span id来标识。在一次请求的过程中会调用不同的节点/模块/服务,每一次调用 都会生成一个新的span id来记录。这样,就可以通过span id来定位当前请求在整个系统调用链中所处的位置,以及它的 上下游节点分别是什么。
-
Annotation: 是指附属信息,可以用于附属在每一个Span上自定义的数据。
Spring Cloud Sleuth为Spring Cloud实现了分布式跟踪解决方案 Spring Cloud Sleuth 借鉴了Dapper的术语
Span:基本的工作单元。Span包括一个64位的唯一ID,一个64位trace码,描述信息,时间戳事件,key-value 注解(tags),span 处理者的ID(通常为IP)。
-
Trace:一组Span形成的树形结构。
-
Annotation:用于及时记录存在的事件。常用的Annotation如下:
-
cs:客户端发送(client send) 客户端发起一个请求,表示span开始。
-
sr:服务器接收(server received) 服务器接收到客户端的请求并开始处理,sr - cs 的时间为网络延迟。
-
ss:服务器发送(server send) 服务器处理完请求准备返回数据给客户端。ss - sr 的时间表示服务器端处理请求花费的时间。
-
cr:客户端接收(client received) 客户端接收到处理结果,表示span结束。cr - cs 的时间表示客户端接收服务端数据的时间。
Zipkin是 Twitter开源的分布式跟踪系统,基于 Dapper的论文设计而来。它的主要功能是收集系统的时序数据,从 而追踪微服务架构的系统延时等问题。 Zipkin还提供了一个非常友好的界面,来帮助分析追踪数据。
七、关于 RPC/gRPC/HTTP/REST
因为服务调用方式是 Dubbo 和 Spring Cloud 重要不同点,了解 RPC/gRPC/HTTP/REST 相关概念,有助于对比 Dubbo 和 Spring Cloud。
RPC 是远端过程调用,其调用协议通常包含传输协议和编码协议。
HTTP 严格来说跟 RPC 不是一个层级的概念,HTTP 本身也可以作为 RPC 的传输层协议。
传输协议包含: 如著名的 gRPC 使用的 HTTP 2.0 协议,也有如 Dubbo 一类的自定义报文的 TCP 协议。编码协议包含: 如基于文本编码的 XML Json,也有二进制编码的 ProtoBuf Binpack 等。
所谓的效率优势是针对 HTTP 1.1 协议来讲的,HTTP 2.0 协议已经优化编码效率问题,像 gRPC 这种 RPC 库使用的就是 HTTP 2.0 协议。
在跨语言调用的时候,REST 风格直接把 HTTP 作为应用协议(直接和服务打交道),不同语言之间调用比较方便。
而 RPC 可以把 HTTP 作为一种传输协议(比如 gRPC 使用 HTTP 2.0 协议传输),本身还会封装一层 RPC 框架的应用层协议,不同语言之间调用需要依赖 RPC 协议(需要跨语言 RPC 库实现,比如 Thrift)。
问题:为什么 Dubbo 比 Spring Cloud 性能要高一些?
回答:因为 Dubbo 采用单一长连接和 NIO 异步通讯(保持连接/轮询处理),使用自定义报文的 TCP 协议,并且序列化使用定制 Hessian2 框架,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况,但不适用于传输大数据的服务调用。而 Spring Cloud 直接使用 HTTP 协议(但也不是强绑定,也可以使用 RPC 库,或者采用 HTTP 2.0 + 长链接方式(Fegin 可以灵活设置))。
另外,Martin Fowler 的 MicroServices 一文,其定义的服务间通信是 HTTP 协议的 REST API。