外行人都能看懂的 Spring Cloud,错过了血亏!
这篇主要来讲讲 Spring Cloud 的一些基础知识。以下是SpringCloud GitHub Demo ,看完文章的同学可以自己练手玩玩:
https://github.com/ZhongFuCheng3y/msc-Demo
一、集群/分布式/微服务/SOA是什么?
技术小白看到这些词(集群/分布式/微服务/SOA)时,感觉遥不可及。但真正接触到"面向切面编程"的时候,发现原来如此啊,只不过当时被它的名字给唬住了。下面我就简单说说这些名词的意思:
1. 什么是集群
计算机集群简称集群是一种计算机系统,它通过一组松散集成的计算机软件和/或硬件连接起来高度紧密地协作完成计算工作。在某种意义上,他们可以被看作是一台计算机。
集群技术特点:
通过多台计算机完成同一个工作,达到更高的效率。
两机或多机内容、工作过程等完全一样。如果一台死机,另一台可以起作用。
2. 什么是分布式
分布式系统是一组计算机,通过网络相互连接传递消息与通信后并协调它们的行为而形成的系统。组件之间彼此进行交互以实现一个共同的目标。
好处:
模块之间独立,各做各的事,便于扩展,复用性高
高吞吐量。某个任务需要一个机器运行 10 个小时,将该任务用 10 台机器的分布式跑(将这个任务拆分成 10 个小任务),可能 2 个小时就跑完了
3. 集群/分布式
集群和分布式并不冲突,可以有分布式集群
Java,前端,测试,DBA 的关系看作是分布式的
5 个 Java 看作是集群的(前端,测试同理)
4. 分布式/微服务/SOA
其实我认为分布式/微服务/SOA 这三个概念是差不多的,了解了其中的一个,然后将自己的理解往上面套就好了。
二、CAP 理论
从上面所讲的分布式概念我们已经知道,分布式简单理解就是:一个业务分拆多个子业务,部署在不同的服务器上。一般来说,一个子业务我们称为节点。
如果你接触过一些分布式的基础概念,那肯定会听过 CAP 这个理论。就比如说:你学了 MySQL 的 InnoDB 存储引擎相关知识,你肯定听过 ACID!
1. CAP 分别代表的是什么意思:
C:数据一致性(consistency)
A:可用性(availability)
P:分区容错性(partition-tolerance)
下面有三个节点(它们是集群的),此时三个节点都能够相互通信:
![](https://ask.qcloudimg.com/http-save/developer-news/12vzozr8ee.jpeg?imageView2/2/w/1620)
由于我们的系统是分布式的,节点之间的通信是通过网络来进行的。只要是分布式系统,那很有可能会出现一种情况:因为一些故障,使得有些节点之间不连通了,整个网络就分成了几块区域。
数据就散布在了这些不连通的区域中,这就叫分区
![](https://ask.qcloudimg.com/http-save/developer-news/t8ewy7e6pc.jpeg?imageView2/2/w/1620)
现在出现了网络分区后,此时有一个请求过来了,想要注册一个账户。
![](https://ask.qcloudimg.com/http-save/developer-news/mnsvopwa8m.jpeg?imageView2/2/w/1620)
此时我们节点一和节点三是不可通信的,这就有了抉择:
如果允许当前用户注册一个账户,此时注册的记录数据只会在节点一和节点二或者节点二和节点三同步,因为节点一和节点三的记录不能同步的。
如果不允许当前用户注册一个账户(就是要等到节点一和节点三恢复通信)。节点一和节点三一旦恢复通信,我们就可以保证节点拥有的数据是最新版本。
三、Spring Cloud 就是这么简单
下面来讲讲 SpringCloud 最基础的知识:
1. 为什么需要 Spring Cloud
举个可能不太恰当的例子:
![](https://ask.qcloudimg.com/http-save/developer-news/3lmvuxtnwk.jpeg?imageView2/2/w/1620)
拆分出多个模块以后,就会出现各种各样的问题,而 SpringCloud 提供了一整套的解决方案!
2. Spring Cloud 的基础功能:
服务治理: Spring Cloud Eureka
客户端负载均衡: Spring Cloud Ribbon
服务容错保护: Spring Cloud Hystrix
声明式服务调用: Spring Cloud Feign
API 网关服务:Spring Cloud Zuul
分布式配置中心: Spring Cloud Config
四、引出 Eureka
当子系统与子系统之间不是在同一个环境下,那就需要远程调用。远程调用可能就会想到 httpClient,Web Service 等这些技术来实现。在服务多的情况下,手动来维护这些静态配置就是噩梦!
为了解决微服务架构中的服务实例维护问题(ip地址), 产生了大量的服务治理框架和产品。在 Spring Cloud 中我们的服务治理框架一般使用的就是 Eureka。
1. Eureka 细节
Eureka 专门用于给其他服务注册的称为 Eureka Server(服务注册中心),其余注册到 Eureka Server 的服务称为 Eureka Client。
![](https://ask.qcloudimg.com/http-save/developer-news/14k79bcdvi.jpeg?imageView2/2/w/1620)
Eureka Client 分为服务提供者和服务消费者。
但很可能,某服务既是服务提供者又是服务消费者。
如果在网上看到 SpringCloud 的某个服务配置没有"注册"到 Eureka-Server 也不用过于惊讶,很可能只是作者把该服务认作为单纯的服务消费者,也就无须注册到 Eureka 中了。
五、引出 RestTemplate 和 Ribbon
通过 Eureka 服务治理框架,我们可以通过服务名来获取具体的服务实例的位置了(IP)。一般在使用 Spring Cloud 的时候不需要自己手动创建 HttpClient 来进行远程调用。可以使用 Spring 封装好的 RestTemplate 工具类,使用起来很简单:
![](https://ask.qcloudimg.com/http-save/developer-news/lch5p36jop.jpeg?imageView2/2/w/1620)
为了实现服务的高可用,我们可以将服务提供者集群。Spring Cloud 也支持的负载均衡功能,只不过它是客户端的负载均衡,这个功能实现就是 Ribbon!
负载均衡又区分了两种类型:
客户端负载均衡(Ribbon)
服务端负载均衡(Nginx)
所以,我们的图可以画成这样:
![](https://ask.qcloudimg.com/http-save/developer-news/5of2t2lcpa.jpeg?imageView2/2/w/1620)
1. Ribbon 细节
Ribbon 是支持负载均衡,默认的负载均衡策略是轮询,我们也是可以根据自己实际的需求自定义负载均衡策略的。
实现起来也很简单:继承 AbstractLoadBalancerRule 类,重写 public Server choose(ILoadBalancer lb, Object key)即可。SpringCloud 在 CAP 理论是选择了 AP 的,在 Ribbon 中还可以配置重试机制的。
六、引出 Hystrix
到目前为止,我们的服务看起来好像挺好的了:能够根据服务名来远程调用其他的服务,可以实现客户端的负载均衡。
![](https://ask.qcloudimg.com/http-save/developer-news/nq3twdhzt9.jpeg?imageView2/2/w/1620)
但是,如果我们在调用多个远程服务时,某个服务出现延迟,会怎么样?
![](https://ask.qcloudimg.com/http-save/developer-news/mjo823ste3.jpeg?imageView2/2/w/1620)
在高并发的情况下,由于单个服务的延迟,可能导致所有的请求都处于延迟状态,甚至在几秒钟就使服务处于负载饱和的状态,资源耗尽,直到不可用,最终导致这个分布式系统都不可用,这就是“雪崩”。
![](https://ask.qcloudimg.com/http-save/developer-news/2lgo03heon.jpeg?imageView2/2/w/1620)
针对上述问题, Spring Cloud Hystrix 实现了断路器、线程隔离等一系列服务保护功能。Hystrix 提供几个熔断关键参数:滑动窗口大小(20)、 熔断器开关间隔(5s)、错误率(50%)
1. Hystrix 仪表盘
它主要用来实时监控 Hystrix 的各项指标信息。通过 Hystrix Dashboard 反馈的实时信息,可以帮助我们快速发现系统中存在的问题,从而及时地采取应对措施。
启动时的页面:
![](https://ask.qcloudimg.com/http-save/developer-news/qv5ipj4cll.jpeg?imageView2/2/w/1620)
监控单服务的页面
![](https://ask.qcloudimg.com/http-save/developer-news/qbo3ruzlc0.jpeg?imageView2/2/w/1620)
我们现在的服务是这样的:
![](https://ask.qcloudimg.com/http-save/developer-news/tc3waawxpq.jpeg?imageView2/2/w/1620)
除了可以开启单个实例的监控页面之外,还有一个监控端点 /turbine.stream 是对集群使用的。 从端点的命名中,可以引入 Turbine, 通过它来汇集监控信息,并将聚合后的信息提供给 HystrixDashboard 来集中展示和监控。
![](https://ask.qcloudimg.com/http-save/developer-news/qdjg0vqcks.jpeg?imageView2/2/w/1620)
七、引出 Feign
为了简化我们的开发,Spring Cloud Feign 出现了!它基于 Netflix Feign 实现,整合了 Spring Cloud Ribbon 与 Spring Cloud Hystrix, 除了整合这两者的强大功能之外,它还提供了声明式的服务调用(不再通过 RestTemplate)。
Feign 是一种声明式、模板化的 HTTP 客户端。在 Spring Cloud 中使用 Feign, 我们可以做到使用 HTTP 请求远程服务时能与调用本地方法一样的编码体验,开发者完全感知不到这是远程方法,更感知不到这是个 HTTP 请求。
下面就简单看看 Feign 是怎么优雅地实现远程调用的:
服务绑定:
![](https://ask.qcloudimg.com/http-save/developer-news/sxmmyuwfxr.jpeg?imageView2/2/w/1620)
Feign 中使用熔断器:
![](https://ask.qcloudimg.com/http-save/developer-news/ca3xd2jv26.jpeg?imageView2/2/w/1620)
调用:
![](https://ask.qcloudimg.com/http-save/developer-news/f35eelevmg.jpeg?imageView2/2/w/1620)
八、引出 Spring Cloud Config
随着业务的扩展,我们的服务会越来越多。每个服务都有自己的配置文件,既然是配置文件,给我们配置的东西,那难免会有些改动的。比如我们的 Demo 中,每个服务都写上相同的配置文件。万一我们有一天,配置文件中的密码需要更换了,那就得三个都要重新更改。
Spring Cloud Config 项目是一个解决分布式系统的配置管理方案。它包含了Client 和 Server 两个部分,server 提供配置文件的存储、以接口的形式将配置文件的内容提供出去,client 通过接口获取数据、并依据此数据初始化自己的应用。
简单来说,使用 Spring Cloud Config 就是将配置文件放到统一的位置管理(比如GitHub),客户端通过接口去获取这些配置文件。
在GitHub上修改了某个配置文件,应用加载的就是修改后的配置文件。
![](https://ask.qcloudimg.com/http-save/developer-news/d9pgukm3qa.jpeg?imageView2/2/w/1620)