扫盲帖:聊聊微服务与分布式系统,Java 校招面试指南
同时因为项目规模小,业务流程简单,维护和迭代起来也很方便,所以在当前这个阶段单体应用是非常适合的。
但是随着业务增长,单体应用不可避免的会出现瓶颈,我举个例子:
假如我们现在的单体 Tomcat 应用只能支撑 QPS200,随着用户量的增大并发随之增大,慢慢超出了单台应用能承受的极限,假如现在达到了 QPS300,那么多出来的 100 请求就只能等着前面的请求处理完了之后才能请求进去,这样带来的后果就是响应时间变长,影响用户体验。
或者我们应用中的业务比较复杂,单次请求响应时间比较长,这样的话大量请求挤压也会导致用户的体验很差,他们能明显的感觉到点击某个按钮之后隔了 1~2s 才有结果返回。
这个时候我们就可以引入集群架构了,我们可以将单体应用同时部署两份,并通过 Nginx 进行反向代理和负载均衡进行流量分流,这样每个单体应用承受的 QPS 就是 150 了,就在可以接受的范围内,而且维护集群应用和维护单机应用区别不大,只是在涉及到锁的时候可能要借助分布式锁来做。
至此,每当访问量增大系统到达瓶颈时我们就可以通过加机器这种方式进行横向扩容,不断的扩大应用的负载能力,但是如果这种方式完美无缺,我们也就不需要微服务的架构了~~~
从单体应用过渡到集群架构,解决的其实是性能的问题,单台机器已经无法满足人民日益增长的访问需求,所以出现了集群架构。
那么从集群过渡到微服务架构的更多原因肯定就不在性能了,这里我说说我自己的看法与感悟:
首先既然项目已经是集群了证明业务量也不会非常小,这也就代表了代码一定有一些规模了,这时候要面临的第一个问题就是所有开发人员都会在这一个项目里面修改代码,极大情况下是冲突不断。
其次这么多代码聚合在一块,当你进行一处功能修改的时候,如果需要进行全量回归测试的话那简直太要命了。
再者说,所有业务块都在一个系统这会导致资源无法最大化利用,比如一个电商系统肯定是商品搜索/推荐系统为最常用的系统,理所当然在资源方面他们应该占有更多的机器资源,但是业务不进行拆分想进行横向扩展只能将所有业务一起扩展。
最后是有可能会引起雪崩效应,举个例子你的系统中假如有一块非常不重要的业务(比如签到)代码写的有问题在生产环境中引发了 OOM,那么它必然会连累到整个系统中的所有业务都变成不可用,因为不同业务之间并没有物理隔离。
通过这几条可以知道过渡到微服务更多的考虑的已经不是性能瓶颈,而是人,是业务,也是应用系统最重要的高可用。
微服务与分布式
=======
微服务是一种面向服务的软件架构模式,自 2014 年 Martin Fowler 与 James Lewis 写了一篇微服务架构的文章之后(微服务这个概念在此之前就有),微服务就被大量的讨论以及实践到生产项目中:Netflix、Amazon 这些商业公司都有微服务的成功案例,商业公司最会考虑的一件事就是成本,他们不会因为 Martin Fowler 是软件工程的名人(巨佬)就对他提出的某个概念迅速披挂上马,一定是经过了很多权衡之后,才对他们的项目使用微服务的架构模式。
上一?节中我已经简要说了说集群架构的缺点,微服务则是解决了那些缺点才变得如此受欢迎,微服务的相关定义,这里我引用一段 Martin Fowler 原文的配图和翻译来说明:
简而言之,微服务架构风格,就像是把一个单独的应用程序开发为一套小服务,每个小服务运行在自己的进程中,并使用轻量级机制通信,通常是 HTTP API。
这些服务围绕业务能力来构建,并通过完全自动化部署机制来独立部署。这些服务使用不同的编程语言书写,以及不同数据存储技术,并保持最低限度的集中式管理。
如果非要我用自己的语言来理解一下就是:将一个大型系统分为一个个的小型服务系统,共同支撑大型系统,每个小服务系统都可以独立开发/测试/迭代/部署/扩容。
将大系统拆分为小服务之后既拥有了小服务的相关优点(利于团队协作/测试/迭代),又能在面对大流量时进行集群扩容,可以说是集两者优点于一身,可能这就是所谓的”天下大势,合久必分,分久必合。”
我新入职的这家公司也是在今年初全面转入微服务架构,我们部门中所有的业务都已经拆成了微服务在跑,微服务拆分这事算是见仁见智吧,要根据具体业务具体分析,我们的拆分过程中感觉比较好的一点是:有一些在未来一两年内将要停止运营的业务也单独拆出来放在一个服务里跑。
其实微服务的概念不难理解,但真正动手起来做的话遇到的则一般不是微服务的问题而是分布式问题,有很多人经常把这两个概念搞混淆,认为他俩说的是一个东西,其实是两个东西,我们做出来的东西往往是涵盖了这两个概念。
**微服务是指的一种面向服务的软件架构方式,而分布式则是一种为了
某个共同目标而协调多台计算机节点进行工作的软件系统。**
在上一节的讲解中,有一句话一直出现:随着业务量/访问量增大,这个日益增长的访问量/业务量/数据量是我们使用微服务和分布式系统的主要原因:
业务的增加我们通过业务拆分来解决其带来的问题,这可以算是微服务的范畴。
不同的服务部署在不同的机器上,但是对于用户来说却和访问一个系统没什么区别,依靠网络将多个计算机节点组成一个统一的整体,这可以算是分布式系统的范畴。
由于数据量的不断增加我们可以通过增加机器节点来分摊数据量,这算是分布式系统中分布式存储的范畴。比如我们的 Redis 数据一台机器已经存不下了,就要考虑使用 RedisCluster 将数据分散到多台机器上面,其他例如 Kafaka、ES 都是分布式架构的中间件都可以进行分布式存储。
如果应用中某些计算量比较大的任务使用一台机器执行会耗时过长,这时我们可以拆分任务给多台节点同时执行,这算是分布式系统中分布式计算的范畴。最近我在接手项目的时候就遇到了类似的问题,原任务单机执行时间过久,让我改为所有在线节点同时执行,共同分摊任务,并且要能动态根据在线节点数量进行任务拆分。
通过上面四点的说明,我想大家对微服务和分布式应该有个简单的区分了吧,再次总结一下:
微服务是指的一种面向服务的软件架构方式,而分布式则是一种为了某个共同目标而协调多台计算机节点进行工作的软件系统。
那为什么微服务和分布式系统老放在一块讨论,导致很多人对他俩的定义模糊不清呢,因为往往我们要实现一个微服务架构的应用时,我们就在实现一个分布式系统。
如果你不明白我这句话,请好好想想使用微服务架构组成的应用是不是也同时符合分布式的定义。
Tips:?分布式计算/存储也是一门计算机科学中的研究方向,所以它们其实还是可以挺深奥的一堆东西。
分布式与 CAP
=======
看了上一节大家应该已经明白了微服务和分布式的关系了吧,我这篇文章的重点其实是分布式,因为微服务只是一个面向服务的软件架构概念,让我理解起来它的主要作用就是提出了服务拆分、独立开发部署这些概念,emm~概念,但是一个分布式系统却有很多各种各样的实际问题需要解决,所以我的重点是在分布式。
先来说说分布式的 CAP 原则,但凡对分布式有点了解的,都不能不知道这个 CAP,先来看看它的定义:
CAP 原则又称 CAP 定理,指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。
CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。
分区容错性:?是指在分布式系统中部署在不同地点的机器可能出现网络连接失败的情况,这就像我的推荐服务会请求商品服务里面的数据,但有可能发生了网络波动导致我推荐服务发起的请求网络连接超时。
可用性:?是指用户的请求必须返回结果,要做到这个程度就需要我们在不同机房部署应用避免出现某些地方机房遭遇了事故导致服务宕机的情况。
一致性:?是指数据被修改后,之后读到的数据一定是最新的数据。
上面的定义已经说了,CAP 只能最多同时实现两点,因为我们是分布式系统,所以多台服务节点是无法避免的,也就是分区容错性我们必须要保证,所以我们只能保证实现 CP 或者 AP。
为什么不能同时实现 CAP 呢?原因很简单,因为可用性这个要求需要每个节点的数据都要有几个冗余的副本,用来保证有一个节点挂掉之后副本能顶上去。然而副本节点和主机节点之间因为有网络通信所以往往这个数据的传输是有延迟的,这也就不能保证主机的数据被修改后副本能立即收到修改,而是经过一顿延迟后才能收到主机修改的数据。
为了方便大家理解,我再举一个例子来说明一下,比如说分布式中间件 Redis:
它在单机的情况下可以保证 CP,因为只有一台 Redis 节点所以数据被修改后之后的请求所访问到的数据都是最新的。
它在集群的情况下可以保证 AP,AP 是强调可用性,集群架构下如果主节点挂掉之后,副本节点还可以接着响应请求。
既然 CAP 无法同时保证,那我们就要退而求其次,这里将会引出一个新的理论:BASE。
BASE 是 Basically Available(基本可用)、Soft state(软状态)和 Eventually consistent(最终一致性)的简写。
BASE 是对 CAP 中一致性和可用性权衡的结果,契合性思想是即使无法做到强一致性,但每个应用都可以根据自身的业务特点,采用适当的方式来使得系统达到最终一致性。
基本可用:?是指某些情况下允许部分可用性的丢失,比如我们的双十一大促,可能会由于下单量激增导致你下不了单,这就属于下单服务不可用了,但是并不会持久太久,而是短暂的。
软状态:?是指允许副本同步过程中出现延迟而导致副本不一致的情况。
最终一致性:?是指系统的所有系统数据副本可以经过一段延迟后最终达到数据的一致性,不需要保证实时的数据一致。
我们既想要可用性也想要一致性,然而二者无法兼得,所以 BASE 理论就提出了这样一种兼顾的思想,代价是强可用和强一致的损失。
现实中的很多系统中都是 BASE 理论这种思想,达到系统的一个基本可用和最终一致。
分布式开发与组件
========
这节我们来聊聊我们分布式系统的常见的各种组件以及相关特性,大家接触过分布式开发的话就会发现分布式开发中有一大箩筐的名词等着你:注册中心、配置中心、网关、熔断、远程调用等等。
初来乍到,不要被这些名词吓住,别人能会的你也能,这一节我会自顶向下的讲解一下分布式开发的基本组成,你可以先忘记这些名词,慢慢看我的讲解,看完这一章后我相信对这些都不会再迷茫。
前面我已经说过,分布式系统是多个节点组成一个整体,那不同节点的 IP 肯定不同,想要感觉像是一个整体,就得有一个部件在所有节点的最前面承担一个请求分发的作用,这个东西就叫:网关。
一般的网关有两层,第一层是服务器的 Nginx+LVS 这种,第二层是分布式应用的网关,我这里说的是分布式应用的网关。
这个网关的作用有点像 Nginx,可以帮你做反向代理帮你做负载均衡,但是比它更强大,分布式应用的所有请求第一站就是应用的网关层,在这里可以校验请求是否合法,阻挡网络攻击,也可以进行动态的请求分发。
评论