乐趣区

关于后端:和耳朵聊聊微服务与分布式系统

我是 和耳朵 ,良久没有写文了,明天和大家聊聊 分布式

前段时间始终没有写文是因为忙于面试~,没错???? 到职了换了一家公司工作,新公司的零碎都是分布式的,入职一个月且写了点货色上线之后我才敢于写写这个分布式主题,不然怕本人没有生产教训误人子弟了。

明天呢,次要是想和大家聊一聊分布式系统的相干概念及其常见分布式组件和设计思维 (不波及计算机科学中分布式系统的技术实践之类的货色),之前为了筹备这次的面试我是把市面上的很多分布式组件都看了一遍,咱们公司所用的分布式组件根本也没出我理解的那个常识圈(公司用了Apollo 我没提前理解,大 E 了),如果对分布式相干技术栈不太理解,也能够当我这篇征文做你的扫盲贴,不过别忘了点赞????

单体利用与集群

单体利用、集群和微服务,这个题目一出你们可能就晓得我想说啥了,emm,就是架构的演进过程,很多人可能都看过相干常识,不过我为了文章的完整性还是打算简略讲一讲。

首先是 单体利用 ,在一个业务的起步阶段,往往是用户量不大且拜访申请少的阶段,这个时候咱们个别只须要部署一个 Web 利用和一台数据库就能满足咱们的业务需要,且随着SpringBoot 的风行,Web 服务器能够内置在利用外面,可能更加方便快捷的部署利用。

同时因为我的项目规模小,业务流程简略,保护和迭代起来也很不便,所以在以后这个阶段单体利用是非常适合的。

然而随着业务增长,单体利用不可避免的会呈现瓶颈,我举个例子:

如果咱们当初的单体 Tomcat 利用只能撑持QPS200,随着用户量的增大并发随之增大,缓缓超出了单台利用能接受的极限,如果当初达到了QPS300,那么多进去的 100 申请就只能等着后面的申请解决完了之后能力申请进去,这样带来的结果就是响应工夫变长,影响用户体验。

或者咱们利用中的业务比较复杂,单次申请响应工夫比拟长,这样的话大量申请挤压也会导致用户的体验很差,他们能显著的感觉到点击某个按钮之后隔了 1~2s 才有后果返回。

这个时候咱们就能够引入 集群架构 了,咱们能够将单体利用同时部署两份,并通过 Nginx 进行反向代理和负载平衡进行流量分流,这样每个单体利用接受的 QPS 就是 150 了,就在能够承受的范畴内,而且保护集群利用和保护单机利用区别不大,只是在波及到锁的时候可能要借助分布式锁来做。

至此,每当访问量增大零碎达到瓶颈时咱们就能够通过加机器这种形式进行横向扩容,一直的扩充利用的负载能力,然而如果这种形式白璧无瑕,咱们也就不须要微服务的架构了~~~

从单体利用过渡到集群架构,解决的其实是性能的问题,单台机器曾经无奈满足人民日益增长的拜访需要,所以呈现了集群架构。

那么从集群过渡到微服务架构的更多起因必定就不在性能了,这里我说说我本人的认识与感悟:

  1. 首先既然我的项目曾经是集群了证实业务量也不会十分小,这也就代表了代码肯定有一些规模了,这时候要面临的第一个问题就是所有开发人员都会在这一个我的项目外面批改代码,极大状况下是抵触一直。
  2. 其次这么多代码聚合在一块,当你进行一处性能批改的时候,如果须要进行全量回归测试的话那几乎太要命了。
  3. 再者说,所有业务块都在一个零碎这会导致资源无奈最大化利用,比方一个电商零碎必定是商品搜寻 / 举荐零碎为最罕用的零碎,天经地义在资源方面他们应该占有更多的机器资源,然而业务不进行拆分想进行横向扩大只能将所有业务一起扩大。
  4. 最初是有可能会引起雪崩效应,举个例子你的零碎中如果有一块十分不重要的业务(比方签到)代码写的有问题在生产环境中引发了OOM,那么它必然会连累到整个零碎中的所有业务都变成不可用,因为不同业务之间并没有物理隔离。

通过这几条能够晓得过渡到微服务更多的思考的曾经不是性能瓶颈,而是人,是业务,也是利用零碎最重要的高可用。

微服务与分布式

微服务是一种面向服务的软件架构模式,自 2014 年 Martin FowlerJames Lewis写了一篇 微服务架构 的文章之后 (微服务这个概念在此之前就有),微服务就被大量的探讨以及实际到生产我的项目中:Netflix、Amazon 这些商业公司都有微服务的胜利案例,商业公司最会思考的一件事就是老本,他们不会因为 Martin Fowler 是软件工程的名人(巨佬) 就对他提出的某个概念迅速披挂下马,肯定是通过了很多衡量之后,才对他们的我的项目应用微服务的架构模式。

上一节中我曾经简要说了说集群架构的毛病,微服务则是解决了那些毛病才变得如此受欢迎,微服务的相干定义,这里我援用一段 Martin Fowler 原文的配图和翻译来阐明:

简而言之,微服务架构格调,就像是把一个独自的利用程序开发为一套小服务,每个小服务运行在本人的过程中,并应用轻量级机制通信,通常是 HTTP API。

这些服务围绕业务能力来构建,并通过齐全自动化部署机制来独立部署。这些服务应用不同的编程语言书写,以及不同数据存储技术,并放弃最低限度的集中式治理。

如果非要我用本人的语言来了解一下就是:将一个大型零碎分为一个个的小型服务零碎,独特撑持大型零碎,每个小服务零碎都能够独立开发 / 测试 / 迭代 / 部署 / 扩容。

将大零碎拆分为小服务之后既领有了小服务的相干长处(利于团队合作 / 测试 / 迭代),又能在面对大流量时进行集群扩容,能够说是集两者长处于一身,可能这就是所谓的”天下大势,合久必分,分久必合。”

我新入职的这家公司也是在今年初全面转入微服务架构,咱们部门中所有的业务都曾经拆成了微服务在跑,微服务拆分这事算是见仁见智把,要依据具体业务具体分析,咱们的拆分过程中感觉比拟好的一点是:有一些在将来一两年内将要进行经营的业务也独自拆出来放在一个服务里跑。

其实微服务的概念不难理解,但真正入手起来做的话遇到的则个别不是微服务的问题而是分布式问题,有很多人常常把这两个概念搞混同,认为他俩说的是一个货色,其实是两个货色,咱们做进去的货色往往是涵盖了这两个概念。

微服务是指的一种面向服务的软件架构形式,而分布式则是一种为了某个独特指标而协调多台计算机节点进行工作的软件系统。

在上一节的解说中,有一句话始终呈现:随着业务量 / 访问量增大,这个日益增长的访问量 / 业务量 / 数据量是咱们应用微服务和分布式系统的次要起因:

  1. 业务的减少咱们通过业务拆分来解决其带来的问题,这能够算是微服务的领域。
  2. 不同的服务部署在不同的机器上,然而对于用户来说却和拜访一个零碎没什么区别,依附网络将多个计算机节点组成一个对立的整体,这能够算是分布式系统的领域。
  3. 因为数据量的一直减少咱们能够通过减少机器节点来摊派数据量,这算是分布式系统中分布式存储的领域。比方咱们的 Redis 数据一台机器曾经存不下了,就要思考应用 RedisCluster 将数据扩散到多台机器下面,其余例如 Kafaka、ES 都是分布式架构的中间件都能够进行分布式存储。
  4. 如果利用中某些计算量比拟大的工作应用一台机器执行会耗时过长,这时咱们能够拆分工作给多台节点同时执行,这算是分布式系统中分布式计算的领域。最近我在接手我的项目的时候就遇到了相似的问题,原工作单机执行工夫过久,让我改为所有在线节点同时执行,独特摊派工作,并且要能动静依据在线节点数量进行工作拆分。

通过下面四点的阐明,我想大家对微服务和分布式应该有个简略的辨别了把,再次总结一下:

微服务是指的一种面向服务的软件架构形式,而分布式则是一种为了某个独特指标而协调多台计算机节点进行工作的软件系统。

那为什么微服务和分布式系统老放在一块探讨,导致很多人对他俩的定义模糊不清呢,因为往往 咱们要实现一个微服务架构的利用时,咱们就在实现一个分布式系统。

如果你不明确我这句话,请好好想想应用微服务架构组成的利用是不是也同时合乎分布式的定义。

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,能够帮你做反向代理帮你做负载平衡,然而比它更弱小,分布式应用的所有申请第一站就是利用的网关层,在这里能够校验申请是否非法,阻挡网络攻击,也能够进行动静的申请散发。

申请被网关转发到对应的服务之后,就由对应的服务来解决了,这个时候问题又来了,咱们同一个服务可能部署了三四台节点,这个时候我该往哪个服务器转发呢?

咱们要想转发首先要晓得各个节点的 IP 和端口号,这个信息咱们不能写死,写死的话不利于动静加机器,所以这个时候咱们须要用到一个中间价:注册核心

咱们所有的服务都会注册到注册核心下面去,当然这个注册核心也要是一个集群,这样能够保障高可用。

举个例子:我有一个商品服务给它起了个名字叫做 goods-service,我给他起了三台服务器,这三台服务器都会注册到注册核心下来,而后咱们就能够在注册核心上看到有一个叫 goods-service 的货色上面又三台节点,每台节点的 IP 端口号都会在注册核心下面保留。

这时候咱们网关来转发的时候是通过 goods-service 这个名称去注册核心拿到三台节点的地址,而后依据不同的策略最终决定咱们是要将申请发到哪一台节点。

申请发送到服某某服务的这个过程,咱们能够称作为 服务通信,这个通信形式个别有两种:HTTP 和 RPC,这个其实我感觉没啥好说的,次要就是通信的协定不一样,协定的不同也造成了效率的不同。

下面说了三个比拟重要的组件,还有两个比拟重要的听我娓娓道来。

第一个是 配置核心,这个其实是属于用不必都行的货色,然而用起来还是更不便的,它的次要作用是将分布式应用的配置都放在一个中央治理,咱们须要更改的时候就能够让所有援用这些配置的利用感知到并在运行的过程中动静加载到这些被批改的配置。

比方咱们有六个微服务利用,咱们能够对立的把配置都放在配置核心中间件上,这个数据个别是放在配置核心所连的数据库里,所以等于把咱们所有我的项目的配置抽出来都放在数据库了,一旦线上运行有什么须要动静批改的配置,咱们都能够间接在中间件上批改而后所有利用都会收到批改的告诉,就会对批改的配置进行从新加载。

它对于某些公共的配置也很不便,比方六个微服务用的是一个 Redis 集群,咱们只须要配置一份就够了,而且集群配置有变动咱们也只须要批改一次,六个微服务利用都能感知到。

第二个是 熔断器 ,所谓熔断器,就是为了爱护利用而设计的中间件,比方淘宝双十一下单服务器顶不住的时候就会给你提醒一个 哎呀,服务器太火爆了,请稍后再试呢” 这种提醒,这个货色就是为了爱护淘宝服务不被冲垮而应用的一种限流措施,这种措施叫做服务降级。

应用熔断器还有一些场景,比方下单经验了商品服务和下单服务和库存服务,走到最初一步时库存服务崩掉了,这个时候下单服务这里会报错,进而引起羊群效应,所有和崩掉的节点有通信的节点都会产生谬误,这个时候就须要熔断器出场了,发现那个服务不会响应之后会给一个提醒,避免羊群效应的产生。

这两个概念体现形式很像,然而不要被表象蛊惑,他俩很次要的一个区别是引起的内因不一样,大家有机会写一次相干的代码就能明确了。

以上介绍的这些都是分布式开发中比拟根底的中间件,还有其余可选的中间件链路追踪我会在下一节提一下,在这就不多说了。

SpringCloud 与 Alibaba

上一节大略讲了五个分布式相干的组件,个别也就这五种:微服务网关、注册核心、配置核心、服务通信组件、熔断组件。

这一节要给大家说说相干的实现,给大家认认脸熟,因为咱们搞 Java 利用开发的个别都是用 Spring 全家桶的,在微服务开发这块 Spring 推出了它的 SpringCloud 全家桶用来做微服务分布式开发。

通过这几年的倒退其实大抵能够分为两套开发套件:SpringCloud 开发套件和 SpringCloudAlibaba 开发套件,这个只是我集体的分法,还有一些其余家的我也会提一下。

咱们先来看看 SpringCloud 这一套,这一套相干的组件一开始根本都是 Netflix 公司开发的,这是一个做流媒体利用的,能够了解为国外的爱奇艺。

这张导图左边的是三个注册核心中间件,Eureka就是 Netflix 公司开发的,Zookeeper这个性能比拟强不是简简单单只做注册核心,它还能够做注册核心和分布式锁,Consul则是一个 Go 语言开发的注册核心中间件(也能够用作配置核心),这几个外面 Eureka 是这两年用的比拟多的,更早之前国内可能 Zookeeper 用的更多。

右边第一个 SpringCloudGateway 则是网关中间件,由 Spring 开发,之前 Netflix 还有一个 Zuul,也是用来做网关中间件的。

Feign/OpenFeign/Rabbon这三个我放在一块说,Feign 和 OpenFeign 其实是一个货色,OpenFeign 是在 Feign 停更之后在其根底上开发的,都是用来做服务间通信的,他们应用 HTTP 做通信协议,其实就是 Spring 中的 RestTemplate,而 Rabbon 是一个做服务转发策略的中间件,前文咱们提到网关进行服务转发时能够依据肯定的策略比方:轮询、随机、权重这些策略,这块其实就是 Rabbon 在起效,咱们用 Eureka 的时候当初都是自带 Rabbon 不须要额定去引入相干 JAR 包了,毕竟都是 Netflix 一家的货色。

SpringCloudConfig是 Spring 开发的配置核心中间件,性能比起其余的后起之秀比方携程的 Apollo,阿里的 Nacos 稍弱,所以不举荐用。

Hystrix也是 Netflix 公司开发的中间件,它的作用就是熔断器,是一款十分经典的熔断器中间件,这些中间件外面它是相对来说最简单的。

Sleuth是一款链路追踪中间件,能够记录你的申请会通过哪些链路,Zipkin则能够以可视化的模式将其体现进去。

下面这一套货色在我当初的公司外面除了配置核心用的 Apollo 之外其余都用到了,算是比拟风行的套件了。


不同于下面的根本都是由 Netflix 开发的套件,上面我要介绍的套件是 SpringCloudAlibaba 套件,因为是由 Alibaba 开发的所以个别都这样称说。

下面这幅图相比上一张就要简略的多了。

Nacos是一个多功能中间件,同时能够做注册核心和配置核心,这个组件我本人也用过感觉还是蛮好用的,而且自带一套比拟好看的可视化界面。

Duubo这个可能大家比拟相熟,原来是由阿里开发起初捐给 Apache,当初是 Apache 的顶级我的项目之一,它是一个服务通信的组件,应用 RPC 通信形式。

Sentinel阿里开发的熔断器,名字翻译过去就是哨兵能够说是很贴切了,并且领有链路追踪的性能,还配有配套的可视化界面,能够说是一个人干了 Hystrix+Sleuth+Zipkin 的活。


像阿里这套中间件我是比拟举荐的,因为第一套 Netflix 公司根本都曾经发表进行更新了,比方 Feign 不更新之后 Spring 又接手进行二次开发搞了一个 OpenFeign。

这里在提一下 Apollo,携程开发的配置核心中间件,当初也有很多公司在用,咱们公司也在用集体用起来感觉还是能够的,很不便上手也简略。

其实别看这里列举了这么多的中间件,每中学一种,剩下的看看文档也就上手了,大同小异吧,开源界的货色就是喜爱弄的简略易上手,这对大家来说也是缩小学习老本。

框架学的越多用的越多,你越会发现其实大部分都是大同小异,越能明确学好 Java 根底的作用,越能晓得设计模式、算法才是一个软件工程师必备的技能。

下个月我应该会把这些中间件也逐个写文章写个入门够用的水平吧,大家一起加油????。

我是 和耳朵,欢送关注我的公众号,退出后端相干交换群:

退出移动版