序
终于,还是到了该学习Spring Cloud
的时间了,其实一直不太愿意学习Spring Cloud
,不是因为它有多难,反而觉得它比较简单,上手比较容易,需要了拿来几个例子学学就能上手了。而是觉得,自己本身关于jvm
、jdk
源码、Mybatis
源码甚至Spring
源码都没有去深入研究和掌握,同时自己实际开发中还没有涉及到微服务相关使用技术,因此不太想浪费时间去掌握一些太表面的东西,然而春节期间看源码看的不太能静下心,同时看到隔壁微服务小组整天左口一个“配置中心”,右口一个“网关”的,想着不如趁最近看看微服务基本概念和使用方法,方便后续有机会了直接上手。
Spring Cloud
微服务
Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization’s communication structure.
– Melvyn Conway, 1967
我们从Melvyn Conway的这句话入手,当我们设计一个系统时,将人员划分为 UI 团队,中间件团队,DBA 团队,那么相应地,软件系统也就会自然地被划分为 UI 界面,中间件系统,数据库。而微服务的划分方法不同,它倾向于围绕业务功能组织进行服务的划分,通过这些服务的组合来形成最终的商业领域的软件,每一个服务中包括用户界面,持久化存储等等,所以每一个小团队也不再像传统的方式进行划分,每一个小团队都需要拥有独立开发一个项目的所有技能。
而这些服务之间,通过消息总线、rpc
以及http
等方式进行相互通信,以此来构成整个项目。
微服务与分布式
先来说说分布式,分布式侧重系统的部署模式,强调服务部署在不同的机器上,将系统部署在超过一台机器上,且通过各种通讯协议进行交互的设计,就可以算是分布式。所以分布式强调并解决的问题主要是高并发。
而微服务则更加强调架构的设计,通过将具有不同职责和功能的应用进行拆分,使得单个服务满足职责单一的设计原则,并在这些原则之上设计出来的系统变可以称做微服务。微服务并没有强调机器数量,可以在一台机器上部署多个服务,只要每一个服务的职责单一即可。所以微服务强调的是职责单一。
随着微服务的不断发展,也带动了基于DDD
的设计开发模式的发展,所以DDD
也逐渐开始成为了设计微服务的最佳实践。
Spring Cloud
前面我们简单介绍了微服务的概念和注意点,我在这里还需要再次说明一下,微服务强调职责单一,强调团队划分。
接下来我们来看看微服务在java
中的思想实现结晶 – Spring Cloud
Spring Cloud
是一系列框架的集合,它利用Spring Boot
的开发便利性简化了分布式系统基础设施的开发,一般来说一个基于Spring Cloud
的微服务应用,会具有服务注册发现、配置中心、消息总线、负载均衡、熔断器、数据监控等功能组成。Spring Cloud
针对这些功能通对现有框架的包装,在满足Spring Boot
的约定大于配置的基础上,整合出了一套简单易用、易部署、易维护的分布式系统开发包。
图片来源:请回答1994
Spring Cloud组成
我们从分布式系统实现功能角度出发,分析Spring Cloud
以及实现类似功能的框架,它们每一个都属于哪一类功能框架。
服务注册发现
传统类rpc
框架中,如果我们想要远程调用某个服务,那么我们肯定需要知道目标服务的ip
地址和端口,然后在调用者的配置文件中配置好这些端口号和ip
地址,然后通过注解的方式获取到这些信息进行调用。
但是这样的方式可能会出现麻烦,如果目标服务的这些信息出现更改,那么调用者也需要随之更改相关信息,也就是说我们作为调用者会随着被调用者的信息更改而被迫更改某些信息,这是一件十分糟糕的事情。如果仅仅是一两个系统我们况且还可以容忍,但是如果是成百上千的系统都是以这样的方式进行调用,那么将会十分地影响开发和维护的效率,因为调用者完全不应该去关心被调用者的这些信息更改,它只需要这个接口能够通信即可。
为了解决类似这样的问题,有人想到让所有的服务将各自的这些信息都注册到统一平台去,然后让服务调用者通过服务别名去寻找目标服务的信息,再去进行远过程调用,这样就能够满足当目标服务的信息变更的时候,也不会影响到服务调用者,降低了服务与服务之间的耦合性。
在Spring Cloud
中,拥有和实现此功能的框架有Spring Cloud Eureka
、Spring Cloud Consul
、Spring Cloud Zookeeper
等。
Spring Cloud Eureka
提供在分布式环境下的服务发现和服务注册功能,Eureka
主要由服务端和客户端组成,Eureka
客户端是一个java
客户端,用来简化与服务器的交互、作为轮询负载均衡器,并提供服务的故障切换支持。
Consul
是一个支持多数据中心分布式高可用的服务发现和配置共享的服务软件,由 HashiCorp 公司用 Go
语言开发,基于 Mozilla Public License 2.0 的协议进行开源。Consul
支持健康检查,并允许 HTTP
和DNS
协议调用API
存储键值对。Spring Cloud Consul
封装了Consul
操作,Consul
是一个服务发现与配置工具,与Docker
容器可以无缝集成。
除了Spring Cloud
的注册中心之外,Spring Cloud Zookeeper
也是一个用来实现分布式服务注册发现的好工具。Spring Cloud Zookeeper
是Zookeeper
的封装,ZooKeeper
是一个分布式的,开放源码的分布式应用程序协调服务,是Google
的Chubby
一个开源的实现,是Hadoop
和Hbase
的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
配置中心
了解了上面的注册中心,那么配置中心就很简单了,配置中心主要是用来集中管理集群的配置,这样统一的管理方式可以方便之后的升级的配置。
Spring Cloud Config
主要是用来实现该功能的框架,Spring Cloud Config
把应用原本放在本地文件的配置抽取出来放在中心服务器,本质是配置信息从本地迁移到云端。从而能够提供更好的管理、发布能力。 Spring Cloud Config
分服务端和客户端,服务端负责将git(svn)
中存储的配置文件发布成REST
接口,客户端可以从服务端REST
接口获取配置。但客户端并不能主动感知到配置的变化,从而主动去获取新的配置,这需要每个客户端通过POST
方法触发各自的/refresh
。
除此之外,还有携程的Apollo
也提供了集中化管理应用不同环境、不同集群的配置的功能,目前Apollo
所提供的功能相对于Spring Cloud Config
更加强大。
消息总线
Spring Cloud Bus
,分布式消息队列,是对Kafka
、MQ
的封装可与Spring Cloud Config
联合实现热部署。
负载均衡
Spring Cloud Ribbon
针对Ribbon
包装,Ribbon
客户端组件提供一系列完善的配置选项,比如连接超时、重试、重试算法等。Ribbon
内置可插拔、可定制的负载均衡组件。它是一个基于 HTTP
和 TCP
客户端 的负载均衡的工具。它可以 在客户端 配置 RibbonServerList
(服务端列表),使用 HttpClient
或 RestTemplate
模拟http请求,步骤相当繁琐。
Spring Cloud Feign
针对netflix-feign
的封装,Feign
是在 Ribbon
的基础上进行了一次改进,是一个使用起来更加方便的 HTTP
客户端。采用接口的方式, 只需要创建一个接口,然后在上面添加注解即可 ,将需要调用的其他服务的方法定义成抽象方法即可, 不需要自己构建HTTP
请求。然后就像是调用自身工程的方法调用,而感觉不到是调用远程方法,使得编写 客户端变得非常容易。
熔断器
熔断机制在任何场景都是十分必要的,为了避免因为单个服务不可用而导致整个系统不可用的雪崩效应出现,熔断机制能够在服务不可用的第一时间内,返回相应的替代结果,而非停留在服务调用过程中,避免问题的出现。
Spring cloud Hystrix
主要就是为了实现熔断的功能,它是netflix-hystrix
的封装,Hystrix
的主要特性有:
- 断路由机制
当Hystrix Command
请求后端服务失败数量超过一定比例(默认50%), 断路器会切换到开路状态(Open
)。这时所有请求会直接失败而不会发送到后端服务。 断路器保持在开路状态一段时间后(默认5秒),自动切换到半开路状态(HALF-OPEN
),这时会判断下一次请求的返回情况, 如果请求成功, 断路器切回闭路状态(CLOSED
),否则重新切换到开路状态(OPEN
)。Hystrix
的断路器就像我们家庭电路中的保险丝,一旦后端服务不可用,断路器会直接切断请求链,避免发送大量无效请求影响系统吞吐量,并且断路器有自我检测并恢复的能力。
- Fallback
Fallback
相当于是降级操作。对于查询操作,我们可以实现一个fallback
方法,当请求后端服务出现异常的时候,可以使用fallback
方法返回的值。fallback
方法的返回值一般是设置的默认值或者来自缓存。
- 资源隔离
在Hystrix
中,主要通过线程池来实现资源隔离。通常在使用的时候我们会根据调用的远程服务划分出多个线程池。例如调用产品服务的Command
放入A
线程池,调用账户服务的Command
放入B
线程池。这样做的主要优点是运行环境被隔离开了。这样就算调用服务的代码存在bug
或者由于其他原因导致自己所在线程池被耗尽时,不会对系统的其他服务造成影响。但是带来的代价就是维护多个线程池会对系统带来额外的性能开销。如果是对性能有严格要求而且确信自己调用服务的客户端代码不会出问题的话,可以使用Hystrix
的信号模式(Semaphores
)来隔离资源。
服务网关
|
|
- 路由转发
接收外部请求,转发到后端微服务上去,有点类似Nginx
的转发和代理功能。
- 过滤器
在服务网关处完成一些操作,例如权限校验、限流以及监控等等。有点类似于Spring
中的拦截器和过滤器的功能。
单系统开发条件下,这部分功能我们一般都是交给了Nginx
和Spring
代为处理,但是在微服务下,如果还是交给这两者进行处理的话,那么就会显得有点乱和重复,在多个系统中会存在重复的过滤功能,而Nginx
一般是处于最外层进行路由转发,这里不会涉及到业务逻辑,服务网关中往往会涉及到业务逻辑在其中(请求的url
中携带逻辑)。
Spring Cloud GateWay
作为Spring
官方基于Spring 5.0
、Spring Boot2.0
和Project Reactor
等技术开发的网关,它的目标是替代Spring Cloud Zuul
,旨在提供一种简单而有效的方式来对API进行路由,并为他们提供切面。
总结
本文其实并没有介绍任何框架的使用和操作方式,所以阅读起来可能比较费劲,但是这篇文章的目的也是十分明确,就是为了让我们针对微服务中的一些常见概念进行解释和说明,以及这些概念对应的Spring Cloud
中的框架进行说明,期望通过这篇文章的介绍,能够让我们对Spring Cloud
有个基本的印象。