[译]微服务-Martin Fowler(转)

做者:YYGCuigit

出处:http://blog.cuicc.com/blog/2015/07/22/microservices/github

 

在过去几年中,“微服务架构”这一术语如雨后春笋般涌现出来,它描述了一种将软件应用程序设计为一组可独立部署的服务的特定方式。虽然这种架构风格没有明确的定义,但在组织、业务能力上有一些共同的特征:自动化部署,端点智能化,语言和数据的去中心化控制。web

 

“微服务” - 软件架构拥挤大街上的有一个新术语。虽然咱们天然的倾向是轻蔑的一瞥将它一带而过,然而咱们发现这一术语描述了一种愈来愈吸引人的软件系统风格。咱们已看到,在过去的几年中有许多项目使用了这种风格,而且到目前为止结果都还不错,以至于这已变成了咱们同事在构建企业级应用程序时默认使用的架构风格。然而,遗憾的是并无太多的信息来概述什么是微服务风格以及怎样用这种风格。数据库

简单来讲,微服务架构风格[1]是一种将一个单一应用程序开发为一组小型服务的方法,每一个服务运行在本身的进程中,服务间通讯采用轻量级通讯机制(一般用HTTP资源API)。这些服务围绕业务能力构建而且可经过全自动部署机制独立部署。这些服务共用一个最小型的集中式的管理,服务可用不一样的语言开发,使用不一样的数据存储技术。编程

与单体风格做对比有助于开始解释微服务风格:单体应用程序被构建为单一单元。企业级应用程序一般由三部分组成:客户端侧用户接口(由运行于开发机上的浏览器里的HTML页面和Javascript组成),数据库(由插入到通用关系型数据库管理系统中的许多数据表格组成),服务端应用程序。服务端应用程序处理HTTP请求,执行领域逻辑,从数据库中检索、更新数据,选择、填充将要发送到浏览器的HTTP视图。服务端应用程序是一个单一的逻辑可执行单体[2]。系统的任何改变都将牵涉到从新构建和部署服务端的一个新版本。浏览器

这样的单体服务器是构建这样一个系统最天然的方式。处理请求的全部逻辑都运行在一个单一进程中,容许你使用编程语言的基本特性将应用程序划分类、函数和命名空间。你认真的在开发机上运行测试应用程序,并使用部署管道来保证变动已被正确地测试并部署到生产环境中。该单体的水平扩展能够经过在负载均衡器后面运行多个实例来实现。缓存

单体应用程序能够是成功的,但人们日益对他们感到挫败,尤为是随着更多的应用程序被部署在云上。变动周期被捆绑在一块儿 —— 即便只变动应用程序的一部分,也须要从新构建并部署整个单体。久而久之,一般将很难保持一个良好的模块架构,这使得很难变动只发生在须要变动的模块内。程序扩展要求进行整个应用程序的扩展而不是须要更多资源的应用程序部分的扩展。性能优化

 

图1: 单体和微服务服务器

这些挫败导向了微服务架构风格:构建应用程序为服务套件。除了服务是可独立部署、可独立扩展的以外,每一个服务都提供一个固定的模块边界。甚至容许不一样的服务用不一样的的语言开发,由不一样的团队管理。网络

咱们不会声称微服务风格是新颖的、创新的,其本质至少能够回溯到Unix的设计哲学。但咱们的确认为没有足够的人仔细考虑微服务架构,而且若是使用它不少软件实现将会更好。

微服务架构的特征

咱们没法给出微服务架构风格的一个正式定义,但咱们能够尝试去描述咱们看到的符合该架构的一些共性。就概述共性的任何定义来讲,并不是全部的微服务架构风格都有这些共性,但咱们指望大多数微服务架构风格展示出大多数特性。虽然本文做者一直是这个至关松散的社区的活跃用户,咱们的目的是试图描述咱们工做中和咱们知道的一些团队的类似努力中的所见所闻。特别是咱们不会制定一些可遵照的定义。

经过服务组件化

只要咱们一直从事软件行业,一个愿望就是经过把组件插在一块儿构建系统,如同咱们看到的现实世界中事物的构造方式同样。在最近的二十年中,咱们看到做为大多数语言平台一部分的公共库的大量汇编工做取得了很大的进展。

当谈到组件时,咱们遭遇困难的定义:组件是什么。咱们的定义是:组件是一个可独立替换和独立升级的软件单元。

微服务架构将使用库,但组件化软件的主要方式是分解成服务。咱们把库定义为连接到程序并使用内存函数调用来调用的组件,而服务是一种进程外的组件,它经过web服务请求或rpc(远程过程调用)机制通讯(这和不少面向对象程序中的服务对象的概念是不一样的[3]。)

使用服务做为组件而不是使用库的一个主要缘由是服务是可独立部署的。若是你有一个应用程序[4]是由单一进程里的多个库组成,任何一个组件的更改都致使必须从新部署整个应用程序。但若是应用程序可分解成多个服务,那么单个服务的变动只须要从新部署该服务便可。固然这也不是绝对的,一些变动将会改变服务接口致使一些协做,但一个好的微服务架构的目的是经过内聚服务边界和按合约演进机制来最小化这些协做。

使用服务做为组件的另外一个结果是一个更加明确的组件接口。大多数语言没有一个好的机制来定义一个明确的发布接口。一般只有文档和规则来预防客户端打破组件的封装,这致使组件间过于紧耦合。服务经过明确的远程调用机制能够很容易的避免这些。

像这样使用服务确实有一些缺点,远程调用比进程内调用更昂贵,所以远程API被设计成粗粒度,这每每更不便于使用。若是你须要更改组件间的责任分配,当你跨进程边界时,这样的行为动做更难达成。

直观的估计,咱们观察到服务与运行时进程一一映射,但这仅仅是直观的估计而已。一个服务可能由多进程组成,这些进程老是被一块儿开发和部署,好比只被这个服务使用的应用进程和数据库。

围绕业务能力组织

当想要把大型应用程序拆分红部件时,一般管理层聚焦在技术层面,致使UI团队、服务侧逻辑团队、数据库团队的划分。当团队按这些技术线路划分时,即便是简单的更改也会致使跨团队的时间和预算审批。一个聪明的团队将围绕这些优化,两害取其轻 - 只把业务逻辑强制放在它们会访问的应用程序中。换句话说,逻辑无处不在。这是Conway法则[5]在起做用的一个例子。

任何设计系统(普遍定义的)的组织将产生一种设计,他的结构就是该组织的通讯结构。

-- Melvyn Conway 1967

 

图2: Conway法则在起做用

微服务采用不一样的分割方法,划分红围绕业务能力组织的服务。这些服务采起该业务领域软件的宽栈实现,包括用户接口、持久化存储和任何外部协做。所以,团队都是跨职能的,包括开发须要的全方位技能:用户体验、数据库、项目管理。

 

图3: 团队边界加强的服务边界

www.comparethemarket.com是按这种方式组织的一个公司。跨职能团队负责建立和运营产品,产品被划分红若干个体服务,这些服务经过消息总线通讯。

大型单体应用程序也老是能够围绕业务能力来模块化,虽然这不是常见的状况。固然,咱们将敦促建立单体应用程序的大型团队将团队自己按业务线拆分。咱们看到这种状况的主要问题是他们趋向于围绕太多的上下文进行组织。若是单体横跨了多个模块边界,对团队个体成员来讲,很难把它们装进他们的短时间记忆里。另外,咱们看到模块化的路线须要大量的规则来强制实施。服务组件所要求的更加明确的分离,使得它更容易保持团队边界清晰。

侧边栏:微服务有多大?

虽然,“微服务”已成为这种架构风格的代称,这个名字确实会致使不幸的聚焦于服务的大小,并为“微”由什么组成争论不休。在与微服务实践者的对话中,咱们发现有各类大小的服务。最大的服务报道遵循亚马逊两匹萨团队(也就是,整个团队吃两个披萨就吃饱了)的理念,这意味着团队不超过12我的。在更小的规模大小上,咱们看到这样的安排,6人团队将支持6个服务。

这致使这样一个问题,在服务每12我的和服务每1我的的大小范围内,是否有足够打的不一样使他们不能被集中在同一微服务标签下。目前,咱们认为最好把它们组合在一块儿。但随着深刻探索这种风格,咱们必定有可能改变咱们的见解。

是产品不是项目

咱们看到大多数应用程序开发工做使用一个项目模式:目标是交付将要完成的一些软件。完成后的软件被交接给维护组织,而后它的构建团队就解散了。

微服务支持者倾向于避免这种模式,而是认为一个团队应该负责产品的整个生命周期。对此一个共同的启示是亚马逊的理念 “you build, you run it” ,开发团队负责软件的整个产品周期。这使开发者常常接触他们的软件在生产环境如何工做,并增长与他们的用户联系,由于他们必须承担至少部分的支持工做。

产品思想与业务能力牢牢联系在一块儿。要持续关注软件如何帮助用户提高业务能力,而不是把软件当作是将要完成的一组功能。

没有理由说为何一样的方法不能用在单体应用程序上,但服务的粒度更小,使得它更容易在服务开发者和用户之间创建我的关系。

智能端点和哑管道

当在不一样进程间建立通讯结构时,咱们已经看到了不少的产品和方法,把显著的智慧强压进通讯机制自己。一个很好的例子就是企业服务总线(ESB),在ESB产品中一般为消息路由、编排(choreography)、转化和应用业务规则引入先进的设施。

微服务社区主张另外一种方法:智能端点和哑管道。基于微服务构建的应用程序的目标是尽量的解耦和尽量的内聚 - 他们拥有本身的领域逻辑,他们的行为更像经典UNIX理念中的过滤器 - 接收请求,应用适当的逻辑并产生响应。使用简单的REST风格的协议来编排他们,而不是使用像WS-Choreography或者BPEL或者经过中心工具编制(orchestration)等复杂的协议。

最经常使用的两种协议是使用资源API的HTTP请求-响应和轻量级消息传送[6]。对第一种协议最好的表述是

自己就是web,而不是隐藏在web的后面。

-- Ian Robinson

微服务团队使用的规则和协议,正是构建万维网的规则和协议(在更大程度上,是UNIX的)。从开发者和运营人员的角度讲,一般使用的资源能够很容易的缓存。

第二种经常使用方法是在轻量级消息总线上传递消息。选择的基础设施是典型的哑的(哑在这里只充当消息路由器) - 像RabbitMQ或ZeroMQ这样简单的实现仅仅提供一个可靠的异步交换结构 - 在服务里,智能仍旧存活于端点中,生产和消费消息。

单体应用中,组件都在同一进程内执行,它们之间经过方法调用或函数调用通讯。把单体变成微服务最大的问题在于通讯模式的改变。一种幼稚的转换是从内存方法调用转变成RPC,这致使频繁通讯且性能很差。相反,你须要用粗粒度通讯代替细粒度通讯。

去中心化治理

集中治理的一个后果是单一技术平台的标准化发展趋势。经验代表,这种方法正在收缩 - 不是每一个问题都是钉子,不是每一个问题都是锤子。咱们更喜欢使用正确的工具来完成工做,而单体应用程序在必定程度上能够利用语言的优点,这是不常见的。

把单体的组件分裂成服务,在构建这些服务时能够有本身的选择。你想使用Node.js开发一个简单的报告页面?去吧。用C++实现一个特别粗糙的近乎实时的组件?好极了。你想换用一个更适合组件读操做数据的不一样风格的数据库?咱们有技术来重建它。

固然,仅仅由于你能够作些什么,而不意味着你应该这样作 - 但用这种方式划分系统意味着你能够选择。

团队在构建微服务时也更喜欢用不一样的方法来达标。他们更喜欢生产有用的工具这种想法,而不是写在纸上的标准,这样其余开发者能够用这些工具解决他们所面临的类似的问题。有时,这些工具一般在实施中收获并与更普遍的群体共享,但不彻底使用一个内部开源模型。如今git和github已经成为事实上的版本控制系统的选择,在内部开放源代码的实践也正变得愈来愈常见。

侧边栏:微服务和SOA

当咱们谈论微服务时,一个常见问题是它是否仅仅是十年前咱们看到的面向服务的架构(SOA)。这一点是有可取之处的,由于微服务风格和SOA赞同的某些主张十分类似。然而,问题是SOA意味着不少不一样的东西,而大多数时候,咱们遇到的所谓的SOA和这里咱们描述的风格明显不一样,这种不一样一般因为SOA专一于用于集成单体应用的ESB。

特别是咱们已看到太多的搞砸的服务导向的实现,从趋向于隐藏ESB中的复杂性[7],到花费数百万并不产生任何价值的失败的多年举措,到积极抑制变化的集中治理模型,这有时很难看到过去的这些问题。

固然,微服务社区用到的许多技术从开发者在大型组织机构整合服务的经验中成长。Tolerant Reader模式就是这样的一个例子。使用简单协议是衍生自这些经验的另外一个方法,使用网络的努力已作出远离中央标准的反应,坦率地说,中心标准已达到使人叹为观止的复杂性。(任什么时候候,你须要一个本体来管理你的本体,你知道你深陷困境。)

SOA的这种常见表现使得一些微服务倡导者彻底拒绝SOA标签,尽管其余人认为微服务时SOA的一种形式[8],也许服务导向作得对。不管哪一种方式,事实上,SOA意味着如此不一样的事情,这意味着有一个术语来更清晰地定义这种架构风格是有价值的。

Netflix是遵照这一理念的很好的例子。尤为是,以库的形式分享有用的且通过市场检验的代码,这激励其余开发者用相似的方式解决类似的问题,同时还为采用不一样方法敞开了大门。共享库倾向于聚焦在数据存储、进程间通讯和咱们接下来要深刻讨论的基础设施自动化的共性问题。

对为服务社区来讲,开销特别缺少吸引力。这并非说社区不重视服务合约。偏偏相反,由于他们有更多的合约。只是他们正在寻找不一样的方式来管理这些合约。像Tolerant Reader和消费者驱动的契约(Consumer-Driven Contracts)这样的模式一般被用于微服务。
这些援助服务合约在独立进化。执行消费者驱动的合约做为构建的一部分,增长了信心并对服务是否在运做提供了更快的反馈。事实上,咱们知道澳大利亚的一个团队用消费者驱动的合约这种模式来驱动新业务的构建。他们使用简单的工具定义服务的合约。这已变成自动构建的一部分,即便新服务的代码还没写。服务仅在知足合约的时候才被建立出来 - 这是在构建新软件时避免"YAGNI"[9]困境的一个优雅的方法。围绕这些成长起来的技术和工具,经过减小服务间的临时耦合,限制了中心合约管理的须要。

侧边栏:许多语言,许多选项

JVM做为平台的成长就是在一个共同平台内混合语言的最新例子。几十年来,破壳到高级语言利用高层次抽象的优点已成为一种广泛的作法。如同下拉到机器硬件,用低层次语言写性能敏感的代码同样。然而,不少单体不须要这个级别的性能优化和常见的更高层次的抽象,也不是DSL的。相反,单体一般是单一语言的并趋向于限制使用的技术的数量[10]。

也许去中心化治理的最高境界就是亚马逊广为流传的build it/run it理念。团队要对他们构建的软件的各方面负责,包括7*24小时的运营。这一级别的责任下放绝对是不规范的,但咱们看到愈来愈多的公司让开发团队负起更多责任。Netflix是采用这一理念的另外一家公司[11]。天天凌晨3点被传呼机叫醒无疑是一个强有力的激励,使你在写代码时关注质量。这是关于尽量远离传统的集中治理模式的一些想法。

去中心化数据管理

数据管理的去中心化有许多不一样的呈现方式。在最抽象的层面上,这意味着使系统间存在差别的世界概念模型。在整合一个大型企业时,客户的销售视图将不一样于支持视图,这是一个常见的问题。客户的销售视图中的一些事情可能不会出如今支持视图中。它们确实可能有不一样的属性和(更坏的)共同属性,这些共同属性在语义上有微妙的不一样。

这个问题常见于应用程序之间,但也可能发生在应用程序内部,尤为当应用程序被划分红分离的组件时。一个有用的思惟方式是有界上下文(Bounded Context)内的领域驱动设计(Domain-Driven Design, DDD)理念。DDD把一个复杂域划分红多个有界的上下文,而且映射出它们之间的关系。这个过程对单体架构和微服务架构都是有用的,但在服务和上下文边界间有自然的相关性,边界有助于澄清和增强分离,就像业务能力部分描述的那样。

侧边栏:久经考验的标准和执行标准

这有一点分裂,微服务团队倾向于避开企业架构组规定的那种严格的执行标准,但又很乐意使用甚至传教开放标准,好比HTTP、ATOM和其余威格士。

关键的区别是如何定制标准和如何执行。由诸如IETF等组织管理的标准仅当在世界范围内有几个有用的实现时才变成标准,这每每会从成功的开源项目成长起来。

这些标准是远离企业世界的标准。每每被一个几乎没有近期编程经验的或受供应商过分影响的组织开发的。

和概念模型的去中心化决策同样,微服务也去中心化数据存储决策。虽然单体应用程序更喜欢单一的逻辑数据库作持久化存储,但企业每每倾向于一系列应用程序共用一个单一的数据库 - 这些决定是供应商受权许可的商业模式驱动的。微服务更倾向于让每一个服务管理本身的数据库,或者同一数据库技术的不一样实例,或彻底不一样的数据库系统 - 这就是所谓的混合持久化(Polyglot Persistence)。你能够在单体应用程序中使用混合持久化,但它更常出如今为服务里。

对跨微服务的数据来讲,去中心化责任对管理升级有影响。处理更新的经常使用方法是在更新多个资源时使用事务来保证一致性。这个方法一般用在单体中。

像这样使用事务有助于一致性,但会产生显著地临时耦合,这在横跨多个服务时是有问题的。分布式事务是出了名的难以实现,所以微服务架构强调服务间的无事务协做,对一致性可能只是最后一致性和经过补偿操做处理问题有明确的认知。

对不少开发团队来讲,选择用这样的方式管理不一致性是一个新的挑战,但这一般与业务实践相匹配。一般业务处理必定程度的不一致,以快速响应需求,同时有某些类型的逆转过程来处理错误。这种权衡是值得的,只要修复错误的代价小于更大一致性下损失业务的代价。

基础设施自动化

在过去的几年中,基础设施自动化已经发生了巨大的变化,特别是云和AWS的演化已经下降了构建、部署和运维微服务的操做复杂度。

许多用微服务构建的产品或系统是由在持续部署和它的前身持续集成有丰富经验的团队构建的。团队用这种方式构建软件,普遍使用了基础设施自动化。以下面的构建管线图所示:

图5: 基础构建管道

由于这不是一篇关于持续交付的文章,咱们这里将之光住几个关键特性。咱们但愿有尽量多的信心,咱们的软件正在工做,因此咱们运行大量的自动化测试。促进科工做软件沿管道线“向上”意味着咱们自动化部署到每一个新的环境中。

一个单体应用程序能够十分愉快地经过这些环境被构建、测试和推送。事实证实,一旦你为单体投入了自动化生产之路,那么部署更多的应用程序彷佛也不会更可怕。请记住,持续部署的目标之一是使部署枯燥,因此不管是一个或三个应用程序,只要它的部署仍然枯燥就不要紧[12]。

侧边栏:使它容易作正确的事情

咱们发现,做为持续交付和持续部署的一个后果,增长自动化的一个反作用是创造有用的工具,以帮助开发人员和运营人员。用于创造人工制品、管理代码库、起立(standing up)简单服务或添加标准监控和日志记录的工具如今都是很常见的。web上最好的例子多是Netflix的开源工具集,但也有其余咱们普遍使用的工具,如Dropwizard。

咱们看到团队使用大量的基础设施自动化的另外一个领域是在生产环境中管理微服务时。与咱们上面的断言(只要部署是枯燥的)相比,单体和微服务没有太大的差异,各运营场景能够明显不一样。

图6: 模块部署经常不一样

为失效设计

使用服务做为组件的一个结果是,应用程序须要被设计成可以容忍服务失效。任何服务调用均可能由于供应者不可用而失败,客户端必须尽量优雅的应对这种失败。与单体应用设计相比这是一个劣势,由于它引入额外的复杂性来处理它。结果是,微服务团队不断反思服务失效如何影响用户体验。Netflix的Simian Army在工做日诱导服务甚至是数据中心故障来测试应用程序的弹性和监测。

在生产环境中的这种自动化测试足够给大多数运营团队那种毛骨悚然,一般在结束一周的工做以前。这不是说单体风格不可以进行完善的监测设置,只是在咱们的经验中比较少见。

侧边栏:断路器和产品就绪代码

断路器(Circuit Breaker)与其余模式如Bulkhead和Timeout出如今《Release it!》中。这些模式是被一块儿实现的,在构建通讯应用程序时,它们是相当重要的。这篇Netflix博文很好的解释了使用这些模式的应用程序。

既然服务随时均可能失败,那么可以快速检测故障,若是可能的话,能自动恢复服务是很重要的。微服务应用程序投入大量比重来进行应用程序的实时监测,既检查构形要素(每秒多少次数据请求),又检查业务相关指标(例如每分钟收到多少订单)。语义监测能够提供一套早期预警系统,触发开发团队跟进和调查。

这对微服务架构特别重要,由于微服务偏好编排和事件协做,这会带来突发行为。虽然不少专家称赞偶然涌现的价值,事实的真相是,突发行为有时多是一件坏事请。监测对于快速发现不良突发行为是相当重要的,因此它能够被修复。

单体能够被构建成和微服务同样透明 - 事实上,它们应该是透明的。不一样的是,你绝对须要知道在不一样进程中运行的服务是否断开。对同一进程中的库来讲,这种透明性是不大可能有用的。

侧边栏:同步调用被认为是有害的

任什么时候候,在服务间有大量的同步调用,你将遇到停机的乘法效应。简单地说,就是你的系统的停机时间编程各个组件停机时间的乘积。你面临一个选择,让你的调用变成异步或者管理停机时间。在www.guardian.co.uk,他们已在新平台实现了一个简单的规则 - 每一个用户请求一个同步调用,而在Netflix,他们的平台API重设计成在API交换结构(fabric)创建异步性。

微服务团队但愿看到为每一个单独的服务设置的完善的监控和日志记录,好比控制面板上显示启动/关闭状态和各类各样的运营和业务相关指标。断路器状态、当前吞吐量和时延的详细信息是咱们常常遇到的其余例子。

进化式设计

微服务从业者,一般有进化式设计背景而且把服务分解看作是进一步的工具,使应用程序开发者可以控制他们应用程序中的变动而不减缓变动。变动控制并不必定意味着变动的减小 - 用正确的态度和工具,你能够频繁、快速且控制良好的改变软件。

当你试图把软件系统组件化时,你就面临着如何划分红块的决策 - 咱们决定分割咱们的应用的原则是什么?组件的关键特性是独立的更换和升级的理念[13] - 这意味着咱们要找到这样的点,咱们能够想象重写组件而不影响其合做者。事实上不少微服务群组经过明确地预期许多服务将被废弃而不是长期演进来进一步找到这些点。

卫报网站是被设计和构建成单体应用程序的一个好例子,但它已向微服务方向演化。网站的核心还是单体,但他们喜欢经过使用调用单体API构建的微服务添加新功能。这种方法对自然临时性的特性特别方便,好比处理体育赛事的专题页面。网站的这样一部分可使用快速开发语言迅速的被放在一块儿,而且一旦赛事结束当即删除。在金融机构中,咱们看到相似的方法,为一个市场机会添加新服务,并在几个月甚至几周后丢弃掉。

强调可替代性是模块设计更通常原则的一个特例,它是经过变动模式来驱动模块化的[14]。你想保持在同一模块中相同时间改变的事情。系统中不多变动的部分应该和正在经历大量扰动的部分放在不一样的服务里。若是你发现你本身不断地一块儿改变两个服务,这是它们应该被合并的一个标志。

把组件放在服务中,为更细粒度的发布计划增长了一个机会。对单体来讲,任何变动都须要完整构建和部署整个应用程序。而对微服务来讲,你只须要从新部署你修改的服务。这能够简化和加速发布过程。坏处是,你必须担忧一个服务的变化会阻断其消费者。传统的集成方法试图使用版本管理解决这个问题,可是微服务世界的偏好是只把版本管理做为最后的手段。咱们能够避免大量的版本管理,经过把服务设计成对他们的提供者的变化尽量的宽容。

微服务是将来吗?

咱们写这篇文章的主要目的是讲解微服务的主要思想和原则。经过花时间作这件事情,咱们清楚地认为微服务架构风格是一个重要的思想 - 它值得为企业应用程序认真考虑。咱们最近用这种风格构建了一些系统,也知作别人用这种风格并同意这种风格。

那些咱们知道的以某种方式开拓这种架构风格的包括亚马逊,Netflix,卫报,英国政府数字服务部门,realestate.com.au,前锋和comparethemarket.com。2013年的会议电路中全是正向微服务类别转移的公司 - 包括Travis CI。此外还有大量的组织长期以来一直在作可归为微服务类别的事情,可是尚未使用这个名字。(这一般被称为SOA - 虽然,正如咱们说过的,SOA有许多矛盾的形式。[15])

尽管有这些积极的经验,可是,咱们并不认为咱们确信微服务是软件架构的将来发展方向。虽然到目前为止,与单体应用程序相比,咱们的经验是正面的,但咱们意识到这样的事实,并无通过足够的时间使咱们作出充分的判断。

一般,你的架构决策的真正后果是在你作出这些决定的几年后才显现的。咱们已经看到对模块化有强烈愿望的一个好团队用单体架构构建的项目,已经衰败了多年。不少人相信微服务是不太可能出现这种衰败的,由于服务界限是明确的,而且很难围绕它打补丁。然而,知道咱们看到通过足够岁月的足够的系统,咱们不能真正评估微服务架构有多么成熟。

人们固然有理由但愿微服务时多么不成熟。在组件化中作任何努力,成功取决于软件在多大程度上适用于组件化。很难弄清楚组件边界在哪里。进化式设计认可获取正确边界的困难性和使它们易于重构的重要性。但当你的组件是带有远程通讯的服务时,那么重构它比重构带有进程内库的服务难不少。跨服务边界移动代码是很困难的,任何接口变动都须要在参与者之间进行协调,须要添加向后兼容层,而且测试也变得更加复杂。

侧边栏:《构建微服务》

咱们的同事Sam Newman花费2014年的大部分时间写了一本书,捕捉了咱们构建微服务的经验。若是你想深刻到这个话题中,这应该是你的下一步。

另外一个问题是,若是组件不组成的干净利索,那么全部你作的是将复杂度从组件内部转移到组件之间的链接。不只仅是把复杂性移到周围,它将复杂性移动到一个不太明确、难以控制的地方。在没有服务间的凌乱链接的状况下,当你在看一个小的、简单的组件内部时,你能够很容易的认为事情是更好的。

最后,有团队技能的因素。更熟练的团队倾向于采用新技术。可是对更熟练的团队更有效的一种技术不必定适合于不太熟练的团队。咱们已经看到大量的例子,不太熟练的团队构建了凌乱的单体架构,但这须要时间去看当微服务发生这种凌乱时会发生什么。一个差的团队老是建立一个差的系统 - 很难讲在这个例子中微服务会减小这种凌乱仍是使它更糟糕。

咱们听到的一个合理的说法是,你不该该从微服务架构开始。相反,从单体开始,使它保持模块化,一旦单体成为问题时把它分解成微服务。(虽然这个建议是不理想的,由于一个好的进程内接口一般不是一个好的服务接口。)

因此咱们怀着谨慎乐观的态度写了这篇文章。到目前为止,咱们已经看到关于微服务风格足以以为这是一条值得探索的路。咱们不能确定地说,咱们将在哪里结束,但软件开发的挑战之一是,你只能基于目前能拿到手的不完善的信息做出决定。

相关文章
相关标签/搜索