微服务概述
我们都知道微服务现在越来越流行,关于微服务有很多内容可以讨论,笔者最近也阅读了很多相关资料,准备开始一个关于微服务的系列文章,今天就先来和大家来聊一聊什么是微服务。
概述
所谓微服务简单来说就是围绕一个business domain来实现的可以独立release的各种服务。每个服务都有各自的功能,并且能够被别的服务通过网络来进行访问,从而构建一个整体完整的功能。就像我们在淘宝购物,一个服务显示当前的库存,一个服务管理相应的订单,一个服务管理订单的发货,然后他们整合在一起构成了我们一个购物的系统(只是随便说了几个服务,显然现实中的淘宝要比这个复杂得多)。
从另外一个角度来说,我们也可以认为微服务是一个面向服务的架构。每一个“微服务”本身我们可以认为是一个黑盒,它实现了某些特定的功能,外面对它是如何实现的并不需要关心,只关心它的网络接口(REST API或者Queue等)就可以了,不管是别的微服务还是别的代码,都可以通过这些接口来调用相应的功能。下图就是一个简单的示例:
在这个示意图中,发货的这个微服务提供了REST API给consumers调用(比如说查看某个产品是否已经发货),同时它也向Topic中发送了Shipping的Event,这样Consumers只要到对应的Topic中consume event就可以得到相应的event信息了(比如说已经发货的消息,不需要一直不停地进行调用查询)。
核心概念
要想清楚理解微服务,下面几个概念是非常重要的:
独立部署
所谓独立部署,就是我们可以单独修改微服务内部的内容,单独部署它,release相关的修改,别的任何微服务都不需要进行重新部署。这其实也是微服务一个很大的特点,要想做到这一点就意味着我们需要保证我们的微服务是松散耦合的,这一点说起来容易,实现就比较难,比如说和别的微服务共享数据库就是一个常见的问题。这一点我们后面单独来写一篇关于部署的文章进行详细介绍。
围绕Business Domain定义微服务
如何定义微服务的boundary是一个很复杂的事情,有很多方面需要考虑,不过从大的方面来说,围绕Business Domain来进行定义是一个不错的原则,这样尤其有助于我们开发新的功能,也就是说当我们开发一个新的功能的时候,我们不需要修改多个微服务(修改多个微服务会涉及很多问题,我们后面会详细说明),这样整个修改的工作和roll out都会简单很多。
管理自己的状态
这一点我们前面也提到过就是微服务要能够独立地对自己状态进行管理,比如说它有自己独立的数据库,能够独立部署等等。它要能够针对business的功能进行端到端的封装,包括UI,business逻辑以及数据。把它们实现的细节都隐藏到微服务的内部。
大小
这其实也是经常会问到的一个问题,一个微服务究竟多大比较合适呢?我们都知道微服务里面有个微字,但是这个微究竟多大合适呢?这个问题不好回答,因为你没法来判断大小,是用代码的行数还是文件的个数来判断,不同工作经验的人对这个大小都会有不同的理解。更重要的是这个大小有时候并没有意义。不过这里倒是有两个问题你可以尝试来回答一下,一个就是你能处理多少微服务?当微服务个数增加的时候,相应的维护和开发成本也会增加,你也会遇到越来越多的挑战,所以也许渐进地转变到微服务是一个更好的方法。第二个问题就是你如何来定义微服务的boundary,怎么让各个微服务之间不会紧密地couple在一起。这两个问题也许比微服务的大小更加重要。
灵活性
这个世界的变化很快,我们可能会遇到各种我们之前完全没有想到的问题,我们希望有一个架构能够更好的适应这个变化的世界,而微服务的理念从某种程度上给我们带来了更多的灵活性,不过它也从另外一个方面给我们带来了很多新的痛点,所以渐进式的转变是一个很好的思想,不要总想着一口吃成一个胖子。
代码架构和组织架构一致
我们以前一个经典的代码结构是前端UI,中间backend,后面数据库。所以组织架构可能就是前端UI开发人员,后端开发人员和数据库工程师。而到了微服务可能就不能再这么简单划分成这三个组了,可能需要根据微服务对应的Business功能来进行相应的re-org,从而从开发人员上也de-couple开来。
Monolith
我们在提到微服务的时候,不可避免需要聊到和他对应的一种架构,那就是Monolith,因此真正理解Monolith的定义对我们理解微服务也是很有帮助的。很多时候Monolith是从deployment这个角度来讲得,也就是说当我们必须把一个系统一起进行deployd的时候,我们可以认为它就是一种Monolith的架构。它可以简单分成下面几种架构:
Single-Process Monolith
这是一种最常见的现象,就是所有的代码都被打包成了一个process(当然你可以运行多个不同的instance),比如常见的一个web网站,它就简单从数据库读写数据,然后展示到前端网页上,如下图所示:
模块化的Monolith
模块化的monolith是上面single-process monolith的一种,也就是说上面的single process其实是由多个模块组成的,每个模块之间是独立的,但是他们在部署的时候还是放在了一起,如下图所示:
这种架构其实也是蛮好的,各个模块之间相互独立开发,只是部署放在一起,这样一来也会降低部署的复杂度。上面这种架构值得讨论的地方就是他们还是使用同一个database,这样一来假如我们想要把这些模块完全独立开来就不太方便了,我们也看到有些公司会尝试把数据库也独立开来,如下所示:
分布式Monolith
这是一种比较特殊的形式,它有很多service组成,但是因为一些历史或者各种各样的原因,他们必须在一起部署。有人说这种形式的monolith大概拥有所有的分布式系统的弊端和single process monolith的弊端。
Monolith的优点
Single process monolith和模块化monolith都有很多的好处,他们的部署很简单,所以整个开发流程,监控系统,debug系统,端到端的测试等等都会方便很多。而且Monolith的代码reuse非常方便,我们不需要考虑要不要把reuse的代码放到一个库中,或者放到一个可以share的服务中等,直接使用那些代码就好了。
这里有一个误区,有人会觉得Monolith是一个很差的过时的架构,我们上来就应该考虑微服务,不要考虑Monolith,其实不然,很多专家其实都是推荐Monolith作为一个默认的框架(这也是为什么很多startup开始都会选择monolith),只有当你发展到一定阶段才会考虑转到微服务,所以从这个角度来讲,我们需要考虑的是为什么要使用微服务,而不是关注于有哪些原因让我们不使用Monolith。
微服务的优点
在我们考虑为什么要用微服务的之前,我们首先来看看微服务有哪些优点,看看这些优点是否可以解决你目前monolith所面临的的困境。
技术的多样性
当我们使用微服务的时候,因为每个服务的独立性,那么我们可以选择不同的语言来开发不同的服务。比如我们的服务对性能很敏感,我们可以选择性能比较好的技术栈来实现,我们也可以根据不同服务的特性来选择底层不同的数据库实现方式。假如有什么新的技术在某一个方面做得很好,我们也可以很方便地把这些技术引进进来。如下所示:
健壮性
这一点还是蛮重要的,在monolith的系统中,只有一个服务,它要是有问题,那么整个系统都会出问题(当然你可以在多个机器上运行同样的系统来减少fail的概率)。但是在微服务的架构中,容错性就大大增强了,一个服务挂了并不会影响整体,其它方面的功能还是可以正常运行的。当然微服务也会引入一些新的影响健壮性的问题,比如服务之间的网络通信变多了,他们之间通信的健壮性就相比monolith变得差了一点,所以这个健壮性的改变并不是绝对的。
扩展性
在Monolith的架构中,假如我们服务中的某一个部分需要进行scale,那么我们只能整体进行scale。而微服务在这个方面则天然有一些优势,我们可以单独对各个服务进行scale,这样一来就可以精准扩展比较hot的service,从而达到节约资源的目的。如下图所示,不同的服务我们可以有不同的scale程度。
方便部署
在原有的Monolith架构中,你哪怕只改变一行代码,也需要部署所有的代码。而当有很多修改发生在Monolith的各个角落时,并同时apply到一个部署中的时候,如果出问题就很难定位到问题所在。而微服务则可以很好地解决这个问题,只要关心单个服务,部署相对独立。哪怕出了问题,也很容易定位到问题所在点,并进行有针对的roll back,fix等。
组织架构的协调
很多时候我们会说微服务和相应的组织架构是一致的,这样一来一个组就负责一个单独的(或者特定的几个)服务,相对来说责任和效率都会有所提升。
模块化
微服务因为各个模块的独立性,当我们想要再利用现有服务的时候就会很方便,因为各个服务天然就是向外提供接口的,并不关心具体是谁来调用它。
微服务的痛点
世间万物有利必有弊,聊完了微服务的优点不要着急开心,我们再来看看微服务有哪些痛点:
Dev开发体验
因为我们把系统拆分成了越来越多的微服务,在我们Dev开发环境中搭建这些微服务进行测试的时候就会越来越困难。所以有时你就不能在整个local device上运行所有的微服务,然而当你要使用外部环境(比如云服务的时候)进行测试,无形中就增加了开发环境的复杂度。
过度使用新技术
我们上面提到微服务的一个优点就是可以使用任何语言来进行开发,也很容易使用新的技术来实现相应的功能。而程序员又恰恰是一个喜欢折腾的职业,很多时候这种flexibility会让我们压抑不住去尝试一些新的技术和实现。然后所谓的新也就意味着没有经历过足够时间的考验,当我们在production环境中使用它们的时候就会遇到很多我们之前没有遇到的问题,而又正因为新,我们对它不够了解,解决这些问题的代价也往往比较大。
Cost
当我们使用微服务之后,很大可能会发现Cost会增加很多。这个cost可能来自于多个方面,比如说你需要更多的资源来运行这些服务:更多的技术资源,更多的存储资源,更多的网络开销,更多的软件license(比如你每个微服务使用一个数据库)等等。又比如说你想对组织架构做一些调整,都可能引入短期的cost,因为各个组(负责不同的微服务)之间的技术可能完全不相同,他们之间的任何改变都需要重新进行学习,所以对组与组之间的任何调整都会相比之前有更大的cost。所以有人说微服务其实从cost的角度来看是没有大的节省的,假如你很care cost,那么慎重选择(当然从另外一个角度来看,假如微服务这个架构能给你带来更多的收益,你当然也需要一起进行考虑)。
分析报告
在Monolith的架构中,因为所有的数据都在一个数据库中,我们要是想对数据进行分析就比较容易了,只要分析一个数据库中的数据就可以了,如下图所示:
而微服务的架构中,所有的数据都散列在不同的地方,这就让数据的分析变得困难了很多。当然现在也有很多方法来解决这个问题,比如说使用stream来build实时的report,或者把所有的需要分析的内容再统一到一个中心的report的数据库,不过这些操作都意味着复杂度的增加。
监控和分析
在monolith的架构中,监控相对比较简单,只要对整体进行监控就可以了。而到微服务下,我们可能需要对单个servcie进行监控,而且当我们有成本上千个服务的时候,单个服务出问题的情况下我们是不是要立即发送一个Sev2的alert也是一个值得考虑的问题。当然分布式系统也有一套Observability的方法,这是另外一个可以讨论的问题。
安全性
安全性在现在越来越收到重视,在Monolith的架构中,很多信息流其实都在一个process内,而在微服务中则有很大的不同,很多信息都是通过网络进行交互的,这也就意味着给了中间攻击更多的可乘之机,相对来说安全性就需要做跟多额外的事情。我们以后也会专门来聊这个问题。
测试
在进行function test的时候,我们希望能够测试的scope足够大/多。在微服务的架构中,引入越多的服务来进行测试,就需要我们为更多的服务准备各种测试数据,所以测试的复杂度在微服务的架构中也会更加复杂。
延时
可以想象,原本我们可以在一个process中完成的事情,现在要拆分到多个微服务中执行,假如是通过网络进行交互,你还需要Serialize,网络传输,Deserialize,想想也会知道这里相比以前必然会增加很多latency。当然这些latency是不是我们可以接受的,我们首先需要通过一些方法来获取latency的数值,然后再来分析和决定是否需要improve。
数据一致性
之前Monolith的架构中,因为使用单个数据库,我们可以使用数据库的transaction来保证数据一致性,但是现在微服务架构中数据一致性的保证就变得尤其困难了,我们后面也会专门开一章来详细聊聊这个问题。
应不应该使用微服务
这是一个很难回答的问题。有人建议说在一个假如你在一个新的产品或者是一个start-up,那么微服务对你来说可能并不是一个好的选择。一方面是因为你的产品没有那么多用户量,另一方面随着产品的发展,你会发现很多东西需要重新定义,原有的微服务之间的boundary可能已经不再正确了,而这个修改很多时候代价很大。也许你会argue说,我就有信心我们的产品马上就会有很多人用,我可能马上就需要scale,先不说你这个信心是不是正确,即使是正确的那可能最终很多人用的产品和你现在的最初想要做的产品可能也完全不相同了。对startup来说,主要的困扰还是人手的问题,微服务的开发对小的team来说会带来很多不必要的麻烦。
那什么时候使用微服务比较好呢,一个比较常见的原因就是一些公司希望有很多人在同样的系统上工作的时候,能够相互之间不影响,尤其是当你的组织架构也在同时快速增长的时候,这一点尤其重要。从技术角度来看,微服务和cloud平台天生匹配,你可以单独进行部署,可以用选用不同的VM,PasS平台等等。当然,如果你想把你的服务提供给不同的用户,微服务其实也是不错的助力。
总得来说,微服务带来了很多便利性,你可以做更多的东西,但是随之也带来很多复杂性和cost,你可能需要在这些之间进行取舍。
总结
本文初步介绍了什么是微服务,什么是monolith。他们各有什么优缺点,最后简单介绍了我们是否应该使用它,希望对你能够有所帮助。
Recent Comments