不少开发团队已经认识到微服务架构比单体架构更优越。可是也有其余团队感受到这是一种消弱生产力的负担。就像任何软件架构,微服务架构一样有利弊。为了能作出一个明智的选择,你必须了解这些应用并将它们运用到你特定的环境中。html
微服务最大的好处是对功能模块的划分。这是个既重要又奇怪的好处,由于理论上没有理由来解释为什么微服务比单体架构有更强大的模块划分。
那到底什么是我说的模块边界。我想大多数人赞成,将软件划分红多个模块,很是好:彼此就能够分离解耦。若是我须要改变系统的一小部分,大多数的时候我只须要弄清楚这一小块,而后作些改动,咱们会发现小变更真的很容易。对于任何程序而言,好的模块化结构很是有用,特别是当软件的规模变大,模块化会显得格外重要。也许,它会变得更重要,由于团队的规模也在增长。
提倡微服务,须要快速介绍一下康威定律,该定律认为一个软件系统的结构反映了团队的沟通结构。对于较大的团队,特别对于那些分散在各地的团队,对软件实施结构化显得尤其重要,跨团队之间的沟通与一个团队内部沟通相比,将会变得不那么频繁且更加正式。微服务容许每一个团队用相似的沟通模式来照看相对独立的模块单元。
正如我前面所说,没有理由能够解释为什么一个单体系统不该该拥有一个良好的模块化结构[1]。可是不少人都观察到这彷佛不多见,所以大杂烩成了最多见的架构模式。事实上单体架构这种固有的困惑,驱动一些团队开始使用微服务架构。模块的解耦可以起做用,是由于模块的边界就是模块之间引用的障碍。麻烦的是,一个单体系统,一般都很容易绕过障碍。这样作,多是构建功能时有用的技术捷径,但是呢,若是普遍运用这种方法,将削弱模块化的结构和下降团队的生产力。将模块放入独立的服务,这样作使模块的边界更为牢固,使这种自杀式的解决方案更难实现。
耦合的重要部分是持久化的数据。微服务的关键特征是去中心的数据管理,也就是说每一个服务管理它本身的数据库,其它的服务必须经过该服务的API来交互。这就会消除集成数据库,这是大系统很是讨厌耦合的主要缘由。
值得强调的是在一个单体系统中,使用模块化彻底可能,可是它须要纪律来保证。一样地,你也可能获得微服务的大杂烩模式,可是对于自己已经是微服务的架构,要犯这样的错仍是不太容易的。在我看来,使用微服务,能够帮助你实现更好的模块化。若是你对团队纪律颇有信心,那么可能会消除这一优点,不过,随着团队的规模增长,保持纪律会变得愈来愈,这也就意味着维护模块边界将显得更为重要性。
若是你很差好管理模块的边界,这个优点就会变成障碍。这就是单体优先策略的两个主要缘由之一,也是为什么我更倾向于较早使用微服务,你只能在一个领域了解得很是透彻。
但我如今不会在这方面作出警告。只有通过时间的洗礼,你才能真正讲出要如何才能把一个系统的模块化维护好。因此只有咱们看到微服务系统已经运行好多年,才能够评估它是否会带来更好的模块化特性。并且,早期接纳者更有才华,也就是说在咱们可以评估通常团队构建的微服务系统的模块化优点以前,还有好几年的延迟。因此与其和高水平的团队比较成果,还不如比较那些已经使用单体架构的软件带来的变化,这是一个棘手的违背事实的评估。
全部我如今能作的,就是听听那些我认识的人,他们使用微服务架构的早期经验。他们的判断就是微服务能让他们更容易去维护功能模块。
有一个案例特别有意思。有一个团队作了一个错误的决定,在一个不那么复杂的系统上面使用微服务。后来这个项目碰到了问题,须要帮助,而后不少人就跑了进来。这方面,微服务仍是有所帮助的,由于这个系统可以吸引开发者的快速涌入,和单体架构相比,团队更容易扩张。最终这个项目的进度大大超过使用单体架构的预期,使整个团队遇上进度。固然也有负面的,和单体架构相比,微服务的方式耗费了更多的人力,可是微服务的架构可以支持将来更大的规模。
若是你想要知道更多有关于如何构建微服务系统,Sam Newman的这本书是很重要的资料。docker
微服务采用分布式系统来提升模块化。可是分布式软件有一个主要的缺陷,就是分布式系统自己。一旦你开始玩分布式系统,你就会碰到一堆复杂的问题。我不认为微服务社区对分布式系统所带来的成本没有概念,可是复杂性也确实存在。
首先是性能。这时候,你不得不以一种不常见的方式,看着进程内的函数调用转变成性能的瓶颈,远程调用是很慢的。若是你的服务调用了不少远程服务,这些远程服务自己也要调用了另一些远程服务,这些响应时间加起来,就会带来很恐怖的延迟特征。
固然你有办法减小延迟。首先,你能够增长调用的粒度,减小调用的数目。这会使你的编程模式变得复杂,使得你必须想清楚如何批量处理跨服务交互。因为你必须调用至少一次这些全部合做的服务,所以到目前为止,你能作的就这么多了。
第二种方法就是使用异步通讯。若是六个服务异步并行调用,延迟只会是那个最慢的调用,而不是全部调用延迟的总和。这大大改善了性能,但也带来了认知成本。异步编程很难,你很难用好它,并且很难调试。但我听到的大多数微服务的例子,都须要异步来得到预期的性能。
速度以后就是可靠性的问题。你指望in-process函数调用可以成功,但是一个远程调用可能在任什么时候间失败。在不少的微服务中,甚至有不少的潜在的故障点。明智的开发人员知道这些,为可能发生的故障事先设计。你为异步协做作的方案,也适应于故障处理,还可提升服务的弹性。然而,这些补偿仍然不够,仍然有着额外的复杂性,你须要弄明白每个远程调用失败的后果。
这就是分布式计算最主要的两个难题。
对于这个问题,还有一些要注意的地方。首先,不少这类的问题出如今单体架构规模扩充的时候。不多有单体架构能够真正独立运行,一般是跟其余系统一块儿,这些系统大部分是遗留系统。和这些系统经过网络进行交互,一样会碰到这些相似的问题。这就是为什么不少人都倾向于更快转移到微服务架构,来处理远程系统的交互问题。这个问题,一样也和经验有关系,更熟练的团队更有能力处理分布式特性所带来的问题。
固然,分布式特性永远都是一个成本。我老是不太愿意打分布式这张牌,由于想到不少不少人,因低估这些难题而太快地引入了分布式系统。数据库
我想你应该知道,网站的更新着实须要一点耐心。更新某一个东西以后刷新屏幕,但是更新的东西尚未出现。你等了一两分钟后,它出现了。
这是一个很是恼人的可用性问题,几乎能够确定是因为最终的一致性形成的。你的更新被节点P收到,但是呢,你的请求却被另外一个节点G处理。直到节点G从节点P那儿获得更新以前,你一直处于数据不一致的状态。最终,它会变成一致的,但在这以前,你会疑惑是否是有什么东西弄错了。
像这样的不一致是使人恼火的,但他们能够更严重。业务逻辑会停滞在对不一致的信息上作出决策,当这种事发生时,在不一致的窗口关闭以前,也难以诊断出到底什么出了问题。
微服务带来了最终一致性的问题,是由于他们坚持对去中心的数据管理,这种坚持值得称赞。单体架构,你能够一次更新一堆东西。微服务则须要多个资源的更新和分布式的处理,这确实头疼。因此如今,开发者须要意识到一致性问题,在写任何代码以前,弄明白如何检测数据的不一致。
单体架构在这些问题上一样不能全身而退。随着系统的增加,更须要使用缓存来提升性能,缓存失效是另外一个困难的问题。大多数应用程序须要脱机锁,以免长期的数据库事务处理。外部系统须要更新,不能与事务管理器协调。商业流程每每更具宽容的不一致性,由于企业对可用性要求更高(业务流程,一直以来对CAP理论都是一种直觉上的理解)。
和其余分布式问题同样,单体架构也不能彻底避免非一致性问题,但它们受到的困扰很少,特别当它们规模很小时。编程
微服务是DevOps革命后第一新的软件架构。-- Neal Ford
模块化和分布式系统的复杂性一直伴随着我整个职业生涯中。可是有一件事情发生了明显的变化,就是在过去的十年中,有关生产环境的发布。在二十世纪,生产环境的发布几乎老是痛苦且罕见的事情,周末的白天或晚上部署一些能用的软件。可是如今呢,熟练的团队频繁发布到生产环境,许多团队实行持续交付,使他们一天可以在生产环境发布不少次。
这种转变已经对软件产业产生了深远的影响,并与微服务运动深深交织在一块儿。当部分的小变化可能致使整个部署失败,微服务终于被单体架构的部署难题所激发出来。微服务的一个关键原则是,每一个服务都是系统的一个组件,都可独立部署。因此如今当你作出改变时,你只须要测试和部署一个小服务。若是你把它搞砸了,你不会把整个系统都搞砸。毕竟,事先对故障进行了设计,即便失败了,你的组件也不该该中止其余部分的系统工做,尽管功能上有些退化。
这种关系是双向的。因为许多微服务须要频繁部署,统一部署行为显得尤其重要。这就是为何应用的快速部署和快速配置是微服务的先决条件。对于任何以此为基础的服务,你都须要作持续的交付。
持续交付的好处是减小了由想法变成软件的时间。那么,团队能够快速响应市场变化,并快于竞争对手先引入新的功能。
尽管许多人认为持续交付是使用微服务的一个缘由,但值得注意的是,即便单体架构也能够持续交付。Facebook和Etsy是两个最好的例子。还有一些尝试微服务的例子,由于多个服务须要认真协调才能发布,所以没法独立部署[2]。同时我也听到不少人认为使用微服务能更容易作持续交付,我是不太相信模块化可使持续发布更容易,尽管它能够大大提升交付的速度。数组
可以迅速部署独立的小单位,是项目开发的一大福音,但因为几十个应用如今转变为几百个小的微服务,给运维额外增长了负担。许多组织会发现,处理这样一个迅速变化的工具,有一种使人望而却步的难度。
这增强了持续交付的重要性。而持续交付是单体架构一项有价值的技能,也是一个微服务所必须的。若是没有自动化协做,持续交付也没法处理那么多的服务。运维的复杂性也是由管理这些服务和监控的需求的增长而增长。运维的复杂性对单体架构的应用也有所帮助,不过对微服务来讲,这是必然的。
微服务的支持者指出,因为每一个服务更小,因此更容易理解。但风险在于,复杂性并无消除,它只是转移到服务之间的相互联系中。这会增长运维的复杂性,好比调试、跨服务的难度。良好的服务边界的选择将减小这个问题,但若是用错地方,则更糟糕。
处理这种运维复杂度,须要一个新的技能和工具——重点是技能。工具仍然是不成熟的,但个人直觉告诉我,即便有更好的工具,微服务还得靠高技能。
然而,对技能和工具的需求不是解决运维复杂性最难的部分。想要高效地解决,你还须要引入一个DevOps文化:开发者和运维之间的紧密合做,每一个人都参与软件交付。文化变革是困难的,尤为是在更大和更老的组织中。若是你不改变这个技能和文化,单体架构的应用只会受到阻碍,而微服务应用则会受到创伤。缓存
因为每一个微服务都是一个独立的部署单元,你有至关的自由选择须要的技术。微服务能够用不一样的语言,使用不一样的库,并使用不一样的数据存储方式。这使得团队能够选择合适的工具来工做,有些语言和库更适合某些类型的问题。
技术多样性一般以最佳的工具为中心进行讨论,但每每微服务最大的好处确是更使人头疼的版本问题。在单体架构中你能够只使用一个单一的版本库,这种状况常常致使升级出现问题。系统的一部分可能须要升级,来实现使用它的新功能,但不能由于升级而中断系统的另外一部分。处理库的版本问题是其中的一个难题,由于随着代码库的增大,难度会呈指数级增加。
这里有一个风险,有这么多的技术多样性,开发团队会被压倒。我所认识的大多数组织都鼓励有限的一组技术。这种鼓励是经过提供共同的工具来支持监测,使它更容易将服务稳定在一个小的通用环境中。
不要低估了支持使用新技术的价值。用单体架构系统,早期对语言和框架的决定是很难逆转的。通过十年左右,这些的决定可能会限制团队并使团队陷入尴尬的技术境地。微服务让团队尝试新工具,并逐步一次迁移系统的一个服务,使新老技术有所关联。安全
在我看来,上面的因素是做为首要权衡指标来考虑的。这里要讨论的一些事情,我认为就没那么重要了。
微服务的支持者们常常说服务更容易扩展:一个服务获得大量的负载,你就能够扩展,而不用对整个应用进行扩展。然而,我努力回忆起一个过往的经验报告,它使我相信,和千篇一概的应用复制相比,它其实是更有效地进行选择性扩展。
微服务容许你隔离敏感数据以及给数据增长安全性。此外,在保证微服务间交互安全的前提下,微服务难以被攻入。安全问题愈来愈重要,这能够成为使用微服务的主要考虑因素。即便不用微服务,对于单体架构的系统建立隔离服务来处理敏感数据,也是很常见的。
批评者说微服务应用的测试要比单体架构的应用难度更大。虽然这个真正的困难部分来自于分布式应用程序的复杂性,但仍是有好的方法能够测试微服务。在这里,最重要的是要有纪律,要认真测试,单体架构和微服务应用的测试方法的区别只是第二位的。cookie
任何有关架构的综述文章都会受到通常性建议的限制。因此读一篇这样的文章不能帮助你作决定,但这样的文章能够帮助你确保考虑到你应该考虑的各类因素。这里对不一样的系统,成本和收益作了不一样的权重,甚至成本收益会被颠倒过来(在更复杂的系统中强模块化更好,但对于一个简单的系统,这就增长了障碍),你所作的任何决定取决于环境中使用条件,评估哪些因素最重要,以及它们如何影响你的特定评估条件。此外,咱们对微服务架构经验相对有限。在一个系统成熟后,你一般只会在这个体系中决定相应的架构。咱们尚未不少关于长期运行的微服务架构的实例。
单体架构和微服务并非简单的二选一。二者都是模糊的定义,意味着大多数系统都将在一个模糊的边界区域。固然也还有其余系统,不适合这两个类别的。大多数人,包括我本身,讨论微服务时用单体架构做对比,这是由于它们更常见,但咱们必须记住,仍是有系统不属于这两类的。我认为,单体架构和微服务是架构设计领域重要的两部分。它们值得被讨论,由于它们存在有趣的特性,以及有用的讨论,可是没有合适的架构师能够对它们在架构设计领域进行一个全面的区分。
总结起来,微服务的好处:微服务提升了生产效率,但同时也带来了复杂性。因此若是你能够用单体架构管理好你的系统,那么就无需微服务。
对微服务的讨论不该该让咱们忘记了更重要的问题,驱动软件项目成功和失败的重要因素。软因素如团队中人的素质,以及他们如何彼此合做,与领域专家的沟通能力,这都会对是否使用微服务有更加的影响。在纯技术层面上来说,更重要的是把重点放在干净的代码、完善的测试,并持续关注架构的演化进步。网络
[1] 有些人认为“单体架构“是一种侮辱,老是意味着很糟糕的模块化结构。在微服务世界,大多数人不这样作,他们将单体架构定义为将整个应用构建为一个独立的单元。固然,微服务倡导者相信大多数单体架构最终会变成大杂烩,但我不知道有谁会认为创建一个结构良好的单体架构毫无可能。
[2] 能独立部署服务是微服务定义的一部分。因此这么说仍是有道理的,即必须在其部署时协调服务的架构不是微服务架构。也能够这么说,不少团队尝试微服务架构而陷入麻烦是由于他们最终不得不协调多个服务来部署。架构