(译)微服务——martinfowler

作者: MaxZing | 来源:发表于2019-04-06 18:10 被阅读23次

    Microservice

    将软件设计成一系列独立部署的服务的架构方式叫做【微服务】,这个词在过去的几年中越来越火爆。尽管目前尚没有对这种架构风格的明确定义,但是围绕组织结构、业务能力、自动化部署、终端结点的智能化程度,编程语言和数据的去中心化控制这几个方面,这种架构风格有着某些共同的特征。

    新的架构名词

    【微服务】——在软件架构拥挤的街道出现的又一个新词。尽管我们习惯性地投以这类事物轻蔑的一瞥,但是这个小小的词却描述了一种被发现越来越具有吸引力的软件架构风格。在过去的几年中,我们已经看到许多个项目使用了这种风格,目前为止这些项目的结果都是积极的,以至于对我的许多同事而言这已成为构建企业应用的默认风格。然而,令人沮丧的是,没有大量的信息明确指出微服务是什么以及我们如何实现它。

    简而言之,微服务架构风格是以一组小服务来开发单个应用程序的方法,每一个服务运行在自己独立的进程中并且使用轻量级的方法通信,通常是一个HTTP API接口。这些服务围绕相关业务范围构建并且由全自动化部署机器独立部署。这些服务只需要最低限度的管理,可以用不同的编程语言去编写并且使用不同的数据存储技术。

    若要解释清楚微服务风格,将它与单体风格(一个单个应用程序作为一个独立单元构建)对比将会很有帮助。企业应用程序通常由三个主要部分组成:一个客户端用户界面(由运行在用户机器上的浏览器中的HTML页面和javscript代码组合成),一个数据库(由多个插入到一种常见的,通常是关系型数据库管理系统中的数据表组合成),以及一个服务端应用程序。这个服务端应用程序将会处理HTTP请求,执行领域逻辑,从数据库获取和更新数据,并且选择和填充发送给浏览器的HTML视图。这个服务器端的应用程序就是单体——一个单一的可执行的逻辑。任何对这个系统的改动都需要重新构建和部署一个服务器端应用程序的新版本。

    很自然地,这样的单体服务器是构建这样一个系统的一种方式。处理一条请求的所有逻辑都在一个单一的进程中运行,这允许你使用编程语言的基本功能将应用程序拆分成类、函数和命名空间。更谨慎的做法是,你可以在一个开发者的笔记本上运行和测试这个应用程序,并且使用一个部署管道来确保改动都被正确的测试并且部署到了生产环境中。你可以通过在一个负载均衡器后运行多个实例的方式来横向缩放这个单体应用。

    单体应用可以被成功运用,但是渐渐地人们对单体应用感到不满——尤其是当越来越多的应用程序被部署到云端。任何改动都会牵一发动全身——哪怕是对应用程序一个小地方的改变都需要整个单体应用被重新构建和部署。随着时间的推移通常会很难保持一个良好的模块结构,使得控制变更仅影响模块内部变得越加困难。如要实现可伸缩,需要变动整个应用程序而不是应用程序的某一部分,这要求更多的资源。

    微服务架构的特征

    我们不能够说微服务有着一个正式地定义,但是我们可以尝试着描述那些被标上“微服务”标签架构的共同特征。尽管可以列出共同特征,但并非所有的微服务架构都具备所有的特征,但是我们猜想绝大多数的微服务架构都显现出多数特征。尽管我们两位作者已经成为微服务这个相当松散的社区的活跃成员,但我们的意愿是试图描述我们在自己和我们所知的团队的工作中所了解的情况。特别要指出,我们不会给出教条式的微服务的定义。

    通过服务实现组件化

    自软件工程诞生伊始,人们就期望有着通过将软件模块组合在一起来构建系统,就如同我们在现实生活中看到的制造东西的方法。在过去的几十年里,我们在公共组件库方面取得了长足的进展,这些大量的公共组件库已经成为多数编程语言平台的一部分。

    当我们讨论组件时,我们首先得回答“什么是组件”。我们的定义是:一个组件就是一个可以被独立替换和升级的软件单元。

    微服务架构也会使用软件库,但是用来实现软件组件化的主要方式是将软件拆分成服务。我们将被连接到一个程序并且通过内存函数调用的组件称为,而服务却是进程外加载的组件,它通过例如web服务请求或者远程过程调用的方式通信。(各种OO语言程序中服务又是另一个概念了[3])

    选择使用服务作为组件(而不是库)的一个主要原因是服务是可以独立部署的。假设你有一个包含多个库的应用程序[4]跑在一个单一的进程里,对任何单一组件的变更都将导致整个应用程序的重新部署。但是如果这个应用程序被分解成多个服务,那么你可以期望对单一服务的多项变更只需要重新部署那个服务。这不是绝对的,某些变更可能会改变服务接口从而导致某些内容协商问题,但是微服务架构的目的就是要通过明确的服务边界和演进设计的服务契约来最小化这些变更。

    使用服务作为组件的另一个好处是更加明确的组件接口。许多语言在定义明确的公共接口方面表现得不好。通常它只有一些文档来描述如何阻止客户端破坏组件的封装,这将导致组件间过度的耦合。服务通过使用明确的远程调用方法轻松地避免了这个问题。

    像这样使用服务也会带来副作用。远程调用比起进程内调用要花更多代价,因此远程API需要是粗粒度的,通常更加不便于使用。如果你需要更改两个组件的职责分配,在跨流程边界的情形下这种操作将会更加困难。

    我们经常将各个Service近似比作运行中的进程(process),但这只是近似的类比方式。一个Service可以包含很多个一起开发、部署的进程。例如一个应用服务和一个只在该服务中被使用的数据库

    围绕业务的组合

    当大型应用程序拆分成多个部分时,通常情况是在技术层面上分开管理,就有了UI团队,服务端逻辑开发团队,数据库团队。按这种分工模式,即使简单的小改动也会导致跨团队协商和预算评估。敏捷团队会围绕这些问题进行优化,在两个坏处中选择一个代价较小的来解决问题——强制把逻辑塞到所有可以访问的程序中。每个模块都有处理逻辑。这就是Conway's Law[5] 的实践示例

    设计系统(广义上)的组织,其产生的设计等同于组织之内、组织之间的沟通结构。

    -- Melvyn Conway, 1967

    Figure 2: Conway法则的实际应用

    微服务架构拆分方式不同之处在于,按照业务能力划分服务团队。这些服务需要采取该业务领域软件的最宽泛(broad-stack)配置,包括用户界面、持久化存储和其他外部协作。因此这样的团队是跨职能的,其内部需要完整的开发技能:用户体验,数据库和项目管理

    Figure 3: 团队职能范围增强的服务范围增强

    How big is a microservice?
    虽然,"微服务"已流行成为了这种风格架构的代名词,不幸的是这个名字会导致大家关注和争论服务的大小和"微"应该由什么组成。跟其他微服务实践者讨论过各种大小的"服务",最大的团队差不多跟亚马逊双比萨团队一样(整个团队可以吃掉两面比萨),意味着最多不超过12个人。我们也曾经见过更小的团队编制,6个人支撑了6个"服务"。

    这导致了一个问题:团队下12个人每个人负责的范围,和整个团队负责的范围差异较大,从而不能叫一个"微服务"团队。这种情况下我们认为最好将这俩范围组合在一起,但是当我们深入这种架构风格的时候,一定会改变这个看法

    www.comparethemarket.com就是按照这种方式组件的一家公司。跨职能团队负责构建与运营每个产品,每个产品拆分成多个服务,并通过一个消息总线(message bus)通信联系起来

    大型单体应用程序通常也可以围绕业务进行模块化拆分,尽管这种情况不常见。通常我们会组建一个大型团队来打造一个单体程序,好让其在业务线单独划分出来。但有太多的关联关系需要考虑是这种组织面临的主要问题。如果项目整体上跨越了多个模块边界,团队成员可能很难再短期内记住掌握这些关系。此外,还需要大量的强制规范来划分模块范围。组件分割的越明细,团队职责范围越清楚明确。
    未完待续

    做产品不是搞项目

    大多数程序开发的模式是:开发一些软件来满足一些功能,完成后把这些软件交付给维护团队,而开发这个项目的团队解散掉。

    而微服务支持者是倾向于避免这个模式的,他们更倾向于让团队负责整个软件的生命周期。亚马逊有个共同的认知:"you build, you run it"。让开发团队负责产品的整个生命周期。这使开发者能时时刻刻接触软件在生产环境的表现,并增加他们和用户之间的联系。因为他们至少得为支持(用户使用软件)负责。

    对产品的理解应联系在产品业务能力上,而不是将将软件视为一堆需要完善的功能的组合。这里面临的问题是软件如何辅助用户提高业务能力

    不是说相同的这套架构不能适应单体应用,但是粒度更小的服务可以更简单的将开发者和用户联系起来。

    强化终端弱化通讯通道

    在跨进程中通信方面,我们已经有了不少产品和方法,这些方法多在本身强加了一些敏捷通信的机制。一个很好的例子就是企业服务总线(ESB),其中ESB产品通常包括用于消息路由,编排,转换和应用业务规则的复杂工具

    微服务和 SOA

    谈起微服务就会有个常见的问题:这个架构不就是十年前的面向服务架构(SOA)么。这么说的根据是SAO的一些特征和微服务的风格非常相似,但是,SOA代表了一系列不同的东西。我们称之为SOA的大部分东西和我们描述的("微服务")的风格有很大区别,通常SOA专注于ESBs来整合单体程序。

    特别是, 我们已经看到了(SOA)如此多的糟糕的服务导向实施的结果 - 从隐藏ESB [6]中的复杂性的趋势,到耗资数百万研发多年却没有提供任何价值的失败计划,再到积极抑制变化的集中治理模型,有时候很难看出这些问题。

    当然,微服务社区使用的许多技术都是从开发人员将服务集成到大型组织中的经验中发展起来的。"olerant Reader"(容错读取)技术就是其中的一个例子。最大限度的利用网络资源,使用简单协议通讯是也是从这些经验中获取的方法——脱离中心化也能具备需要的复杂度标准。坦白说:真是让人叹为观止(任何时候你需要通过增加一个管理个体来管理其他个体,都会让你陷入一个大麻烦)

    SOA这种表现使微服务倡导者竭力反对给微服务加上SOA的标签。尽管微服务是SOA的一种形式,但微服务的倡导是正确的。无论哪种方式,SOA都意味着更多不同的东西,而(微服务)这是一个更能清晰定义这种架构风格的术语

    而微服务社区主张另一种方法:灵活的终端和笨拙的通道(重点放在终端而不是通讯)。微服务构建的应用应该致力于高内聚,低耦合。每个服务有自己的领域逻辑,像UNIX理念中的过滤器一样工作:接受请求,执行适当的逻辑处理数据。这些服务使用简单的RESTish协议做编排工具而不是其他复杂的协议如:WS-Choreography 或 BPEL

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

    Be of the web, not behind the web

    -- Ian Robinson

    微服务团队用的协议和规范都是构建互联网(更大程度上来说:是Unix)的协议和规范。从开发者和运营者上来说,通常使用的资源都是易于保存的。

    第二种轻量级消息传递是在消息总线上传递消息。这种基础设施通常是笨拙的(只能作为消息传输路由)。——如:RabbitMQ和ZeroMQ这种实现简单,支持可靠的异步通讯的。而服务中的智能灵活的终端去通过这些生产,消费消息。

    整体来说,组件在进程中的通讯是通过函数调用的方式。而将其拆分为微服务后,最大的问题就在于通讯方式的变化。原先从内存中方法调用变成RPC服务间通讯,而RPC的方式性能不及前者。但是,你必须使用这种粗粒度的方式来代替之前细粒度的通讯。

    去中心化治理

    技术单一化,标准化是集中治理的的后果之一。经验表明用这种方法的越来越少,并不是每个问题都是个钉子,而每个解决方案都是一个锤子。我们更喜欢用更好的(语言)工具,而在单体应用中使用不同语言的方式是不常见的。

    讲大型服务组件拆分成服务,那么我们就可以在构建每个最贱的时候自由选择。想使用Node.js去构建一个reports的页面,用C++构建适用的实时组件,没问题,去做吧。如果你想同步不同风格类型的数据库来适应组件的使用,我们自有技术去重新构建它。

    当然,即使你可以做,并不代表你应该那么做。这种系统划分方式只是意味着给你带来了更大的自由去选择合适的方式。

    微服务团队也喜欢采用不同标准的架构。他们比赛在纸上规范好标准,而是通过当前问题,编写能方便开发人员解决类似问题的工具。这些工具在现实中广泛共享,有时会使用开源模型。现在Git和Github已经成为普遍的版本控制系统,也让开源越来越普遍。

    Netflix就是遵循这一理念的组织的一个很好的例子。分享他们有用,经过他们实战考验的代码,而且鼓励开发者用类似的方式解决同样的问题。当然也可以选择不同的方式。共享组件会让开发人员目标集中到数据存储和进程通讯的问题上。下面我们将深入讨论基础架构的自动化。

    微服务社区中(组件)高开销是难以吸引人的,倒不是说社区不注重服务间的规范。相反,正是因为规范比较多,使开发人员寻找不同的方式去更好的管理(遵循)这些规范。像Tolerant Reader(读者容错模式)和Consumer-Driven(用户驱动模式)这些规则规范在微服务中经常提到。这些帮助规范服务的规则都在独立发展着。作为组成微服务的一部分,用户驱动可以增强开发者信心,并提供服务运行的能否正常运行的及时反馈。据我们所知,一个澳大利亚的团队就是利用用户驱动规则构建了他们的微服务,他们构建服务的工具很简单,没次增加新服务的时候工具代码会自动生成。一直维持到这个服务构建到满意的程度为止——一种避免软件开发中YAGNI[9]困境的方式。这些技术围绕所构建微服务一起成长,从而降低耦合性,减少集中管理的需求。

    多语言混编, 更多选择权
    最新例子是:(JVM支持)多语言混编导致JVM平台发展起来很快。最近几十年,用高级语言对编程进行更高级的抽象越来越普遍了。用低级语言构建性能敏感的底层引用渐渐不需要了。很多单体应用不用达到那么高的性能要求,也不需要DSL这样的高层次的抽象(让我们很遗憾),相反,单体应用使用单一语言,限制技术使用的范围和数量[10]

    也行去中心化治理的最高境界是build it / run it那句亚马逊广为流传的理念。团队的7*24小时负责他们自己构建的软件的各个方面。虽然这种职责下发是极不规范的,但是我们发现很多公司把越来越多的责任分给开发团队。Netflix就是这样做的公司之一[11]。3:00被喊醒改Bug无疑会激励你关注代码质量,也是从集中治理模式中脱离的好办法。

    去中心化数据管理

    去中心化数据管理现在有很多种方式,同一个世界的抽象模型在不同的系统是不一样的。每个用户拥有不同的视觉感受是大型服务整合是企业面临的常见问题。有些销售内容在用户界面上根本不会出现,它们确实可能有不同的属性和(更糟糕的)相同属性,这些相同属性在语义上有微妙的差别。

    实战测试标准和执行标准
    这里有点分歧,使用微服务团队倾向于避开企业体系结构组制定的那种严格的强制标准,而是趋向使用和倡导使用公开的标准(如HTTP、ATOM 和其他微型格式)

    这个两个标准关键区别在于制定和执行,只有在在现实中大量使用使用的标准,才会成为被组织管理的标准,如IETF,而使用方往往是成功的开源项目

    这些标准通常不是现有的企业标准,通常是出自一个变成经验不足的团队或者受到供应商影响过度而开发的。

    这个问题在程序之间比较常见,有时候也会出现在程序内部,尤其是程序被拆分成单独组件的时候。解决的有效途径是Domain-Driven Design(领域驱动设计)中的notion of Bounded Context有界Context。DDD设计可以将一个复杂的领域拆分成为多个有界Context,映射出他们之间的关系。这中处理流程对单体应用架构和微服务都很有用,但是服务之间的有界Context是一定存在相关性的,边界只是为了帮助更清晰的划分(职能),就像描述服务的业务能力范围一样。

    除了拆分概念模型的方法之外,微服务还可以使用分布式存储策略。虽然单体应用更偏向使用逻辑数据库来做数据持久化,但企业喜欢将多个应用程序公用一套存储系统,这样许多商业模型就可以通过这些逻辑数据来做决策。而微服务更喜欢让每个服务管理自己的数据库,或者使用同一数据库中的不同势力,或者完全干脆是不一样的数据存储系统。这个方式称之为Polyglot Persistence混合持久化。你可以在单体上使用混合持久化,但是微服务使用的频率更高。

    跨服务对数据进行操作会有数据不一致的问题,常见的处理办法是使用事务来保证数据的一致性,这种方法常出现在单体应用中。

    使用事务虽然可以解决数据一致性的问题,但是会明显增加时间耦合度。并会影响到多个相关的微服务。众所周知,分布式事务是非常难实现的。因此,微服务体系如何增强结构,尽量保证服务之间无事务处理。明确了解到一致性只是最终结果一致性的情况下,可以通过消息补偿来处理。

    使用这种方式处理数据不一致是开发团队们面临的新挑战,但他也往往和业务实践相匹配。通常,不管是业务中为了快速响应的需求,或回滚某些流程来处理错误,只要能修复企业的损失,这些都是值得权衡考虑的。

    软件构建自动化

    软件构建自动化技术在过去几年发生了翻天覆地的变化。——尤其是云和AWS的演变降低了构建,部署,运营,操作微服务的复杂性

    许多使用微服务构建的软件产品的技术团队都有过持续交付或持续集成(持续交付的前身)的经验。拥有这种经验的团队都曾经广泛使用软件构建自动化的技术,下图对这种方式做了说明:

    由于这篇文章不是关于持续交付的。我们这里只提几个比较关注的重点功能,为了提高我们软件运行的可靠性,我们做了很多自动化测试,软件升级流程化意味着部署可以自动化。

    让(运维部署)这件事情更容易做对

    由于自动化程度提高,我们发现随之出现了很多好用的工具帮助开发和运维人员操作。用于创建组件,管理代码库,创建简单监控服务或日志服务的工具相当普遍了。Web中最好的例子可能就是Netflix的一组开源工具了,还有一些我我们经常使用的带Dropwizard的其他工具。

    单体程序会非常容易构建,测试,推送到各个环境。一旦你将整个流程投入自动化中,那部署大量应用就没那么难了。持续部署的目标之一是让部署变的简单枯燥,不管是部署1个还是3个,只要部署过程都是简单枯燥的就行[12]。

    另一个地方用到自动化构建的时候是生产环境构建微服务的时候,虽然上面说的不同的是只要自动部署是简单枯燥的操作,单体应用和微服务没多大差别,然而各个实际操作环境其实差别很大。

    image

    为容错而设计

    使用服务当组件有一个后果,每个应用都需要设计成可以对内部Service容错。因为可能有运营商导致服务不可用等原因,跨服务通讯都可能出现失败,客户端需要尽可能优雅的应对这种失败。它带来额外的复杂处理逻辑,这一点比不上单体应用。使用微服务的团队不断思考:服务失效时如何(减少)影响用户体验。Netflix的Simian Army在工作日的时候,引导服务故障甚至数据库故障来测试应用的弹性和监控效果。

    熔断器和预备上线代码(production ready code)

    熔断器最早出现在《Release It!》中,还有与其结合在一起,用来构建高可用的通信应用的模式。如(隔离器)Bulkhead和(超时计时器)TimeOut。Netflix用了一个博客专门来做解释他们做出来的相关应用。

    生产环境下做这种测试足以让大多数运营团队不寒而栗,尤其是在休假之前的一周做这种测试。倒不是说单体架构应用不能监控得住这种测试,只是我们对这样的操作缺乏经验。

    由于服务随时可能宕机,及时处理这些问题并重启服务变得越来越重要。微服务应用内置了一大堆监控来实时监测应用。检查服务中的组件运行状态(如数据库请求数)和业务相关指标(如每分钟收到多少订单)。实时监控可以提供一个预警系统,方便及时追踪和调查。

    因为微服务对编排和事件协作的偏好会导致紧急行为,所以监控对微服务体架构格外重要。虽然很多专家认为偶发的事件有观察的价值,但是这种突发事件可能导致严重的后果。实时监控对及时发现这种紧急冲突事件,快速修复至关重要。

    有害的同步调用

    当服务器之间有多个同步调用的时候,就服务就会停机等待,且这个有倍增效应。简单来说,系统停滞时间约等于各个组件停机时间的乘积。你得在异步调用和管理停滞中选一个。www.guardian.co.uk 上实现的是每个用户每次只能同步调用一个接口。而Netflix平台重新设计接口,已经将异步性构建到 API 结构中。

    单体应用其实可以和微服务一样透明,事实上,他们也应该做到透明化。不同之处在于,微服务还务必需要知道运行在不同进程中的他们何时断开连接。而在同一进程中使用库时时(单体应用),考虑这种透明性(断开连接时机)是没什么作用的。

    微服务团队希望看到每个服务都有完善的监控日志记录,比如主机运行启动、关闭状态面板,运行指标,业务相关指标等。还有断路态,吞吐量,延迟信息,等我们经常遇到的一些事例。

    进化设计

    微服务从业人员大多有进化设计的背景,并视服务拆分为促进应用程序迭代更新的良好工具,使他们更好的控制和加快程序的更新。而且更新并不是精简——积极的态度和正确的工具会让你快速迭代出良好的软件

    当你尝试拆分软件系统时,你就需要面临如何划分粒度的问题——划分原则是什么?划分的组件的关键标准就是独立性和可升级性[13]——这样才能不影响协作的情况下,重写组件。事实上,微服务组织希望服务被精简废弃,而不是各自独立长期维护发展。

    卫报网站就是很好的一个例子,虽然是按照微服务方向架构发展的,但其设计上依旧构建的是一个整体。其整体性一直是网站的核心,但是开发人员更倾向通过调用整体中的API使用微服务增加添加新特性。这种方式在本质上处理临时功能非常方便,比如增加体育赛事的特殊页面。网站页面可以快速开发完成并组合到原服务一起。并在比赛结束之后删除页面。曾经有一家金融机构为了跟进市场机会有过类似的增加新服务的做法,但几个月甚至几周就放弃了。

    这种强调强替换性的模块化设计是一般设计原则中的一个特例。即通过变更驱动模块化[14]。如果你想将一个变更同时运用到相同的模块中。系统中不常变化的部分与经常发生变动的部分应该分放到不同的微服务里。如果一个服务的变动总会扰动另一个服务,那么意味着这俩应该合并到一起。

    组件拆分成服务就有机会更细粒度的控制发布计划。单体程序任意一处变更都需要程序重新构建和发布,但微服务,你只需要重新部署一下变更的服务即可。大大简化了迭代步骤,加快了更新速度。缺点是你需要考虑一个服务的变化会不会影响其他使用该服务的对象。传统单体应用集成方法是使用版本控制解决这个问题,而微服务中,版本控制只是解决这个问题的最后手段。我们可以通过设计更高容错性的服务来避免频繁的版本迭代。

    微服务是未来的方向吗?

    我们写这篇文章的主旨是为了阐释微服务的设计思想以及原则。通过大量时间的思考与实践,我们清楚地认识到微服务架构是值得企业认证考虑使用的重要架构方式之一。我们与最近使用这种架构风格构建系统的几个团队沟通过,他们非常支持使用这种架构方式。

    我们知道开创这一架构风格的公司有Amazon(亚马逊), Netflix(网飞), The Guardian(卫报), the UK Government Digital Service(英国政府数字服务), realestate.com.au(realestate地产) Forward(Forward医疗) 和 comparethemarket.co等,2013年网络上充满了全是正向微服务类别转移的公司的例子——包括Travis CI,另外还有一部分企业使用了这种架构风格开发软件,却没使用微服务这个名字(通常被认为是SOA架构——尽管我们在前面提出了SOA中的矛盾与微服务中的差别[15])

    虽然我们经验告诉我们微服务优点如此之多,但是我们仍然无法断定微服务架构就是未来发展的趋势,虽然经验告诉我们整体上微服务优点太多了,但是短时间内这些经验不足以让我们做出完善判断


    我们的同事Sam Newman在2014年花费了大部分时间将我们在建设微服务上的经验写成了一本书。如果你想深入了解构建微服务,这个是购买链接微服务设计(英文原版)

    PS:中文版:链接:https://pan.baidu.com/s/18j-a6tt9jJlW2mXdKEZXnA 提取码:isp1 。资源来自互联网,侵删

    通常架构真正的后果只有在使用几年之后才会显现。尽管我们看到优秀团队对模块化改造一个多年以前的破烂项目的热忱。而且许多人认为微服务不会出现衰退的可能,因为服务是边界明晰的且几乎不用到处修补。但是仍然需要很长一段时间我们才能看清系统缺陷。目前我们仍然不能评估微服务架构的成熟程度。

    认为微服务不够成熟是有原因的,在组件化进程中,架构的成败在于软件和组件的匹配程度。很难找到完美的边界在哪里,进化设计意识到了划分边界的困难性,所以将系统设计成易于重构是非常重要的。但组件内有远程通信时,重构就会比进程通讯组件重构困难的多。跨服务代码迁移更加困难,接口变化需要在两个服务之间做好协调,还要考虑增加前版本兼容层,测试也会更加复杂。

    另一个问题是,如果组件界限不够明晰,那么你所做的就是将复杂性从原组件内部转移到组件之间的连接上。转移的不只是复杂度,还有模糊的边界,这些更难控制。小而简单的组件会让你认为系统变得更好了,但其实你忽略组件之间连接变得更加混乱了。

    最后,还有团队技能因素。技术熟练的团队倾向使用新技术,但是不一定对不熟练的技术团队有用,我们见过太多技术薄弱团队搞得单体架构的程序混乱不堪的案例。但这种情况在微服务中仍需要时间观察。技术薄弱的团队常组件出一些混乱的糟糕的系统,现在很难判断微服务是减少了这些混乱,还是让混乱变得更糟。

    有个合理的论点,一开始不应该使用微服务架构。相反,服务应该从单体应用开始构建,保持整体性,直到整体性难以维持时,再逐渐拆分成微服务(虽然不是个很好的建议,因为应该好的进程通讯接口通常不是一个好的服务通讯接口)

    所以我们谨慎乐观的记下了这一点。到目前为止,我们见过好多微服务风格的应用,我们觉得这是一条可行之路。我们还不确定其重点到哪里结束,但是软件开发的挑战就是你得在目前信息还不够完善的时候做出决定。

    脚注(注释就不翻译啦)

    以下来自YYGCui翻译

    1. 2011年5月在威尼斯召开的软件架构研讨会上,“微服务”这一术语被讨论用来描述参与者一直在探索的一种常见的架构风格。2012年5月,该研讨会决定使用“微服务”作为最合适的名字。2012年3月在波兰克拉科夫市举办的33届Degree大会上,James介绍了这些想法作为一个案例研究微服务 - Java,Unix方式,Fred George也差不多在同一时间提出。Netflix的Adrian Cockcroft把这种方法描述为“细粒度的SOA”,在网域级开拓了这一风格,还有在该文中提到的许多人 - Joe Walnes, Dan North, Evan Botcher 和 Graham Tackley。

    2. 单体这一术语已被Unix社区使用了一段时间,在《Unix编程艺术》中用它来描述非常大的系统。

    3. 很多面向对象的设计人员,包括我们自己,在领域驱动设计意义上使用服务对象术语,该对象不依赖于实体执行一个重要进程。这和我们在本文中如何使用“服务”是不同的概念。不幸的是,服务这个词有两个含义,我们不得不忍受这个多义词。

    4. 我们认为应用程序是一个社会结构,它由代码基、功能组、资金体组合在一起。

    5. 原文可在Melvyn Conway的网站上找到,在这里

    6. 在极端规模下,组织通常移至二进制协议并权衡规模的透明度。例如protobufs。使用二进制协议的系统仍旧展现出智能端点、哑管道。大多数网站,当然绝大多数企业不需要做这种权衡,透明度可以是一个很大的胜利。

    7. 我们忍不住提起Jim Webber的说法,ESB全称是“令人震惊的意大利面条盒”

    8. Netflix使这种联系清晰起来 - 直到最近作为细粒度SOA提及他们的架构风格。

    9. “YAGNI”也就是“You Aren’t Going To Need It(你将不需要它)”是一个XP原则和劝诫,在你知道你需要它们时才添加特性

    10. 我们声称单体是单一语言的,这有一点不诚实 - 要在现在web上构建系统,你可能需要知道JavaScript、XHTML、CSS、选择的服务器语言、SQL和ORM方言。很难只用单一语言,但是你知道我的意思。

    11. 在2013年11月的Flowcon大会上提交的这个出色演讲中,Adrian Cockcroft特别提到“开发者自助服务”和“开发者运行他们自己写的代码”(原文如此)。

    12. 我们这里有一点不诚实。显然在更复杂的拓扑结构中部署更多的服务要比部署单一单体更困难。幸运的是,模式减少了这种复杂性 - 在工具上的投资仍是必须的。

    13. 事实上,Dan North提到这种风格是可更换的组件架构而不是微服务。因为这似乎是在讨论我们更喜欢的后者的一个特征子集。

    14. Kent Beck强调这是他《实现模式》一书中的设计原则之一。

    15. SOA几乎是这段历史的根源。我记得当SOA这一术语出现在本世纪初时,有人说“多年来我们一直这样做”。一个理由是,这种风格看其根源是在企业计算早期COBOL程序通过数据文件通信的方式。在另一个方向,有人可能会说微服务和Erlang编程模型相同,但被应用于企业应用程序上下文。


    参考

    原文[英]: microservices

    翻译前半部分参考: 微服务🔥——讨论这个新架构风格名词的定义

    对比参考:微服务


    喜欢请点个赞

    转载请注明出处:https://www.jianshu.com/u/4915ed24d1e3

    如有错误,请务必指正。谢谢

    我的博客:https://xzing.github.io/

    相关文章

      网友评论

        本文标题:(译)微服务——martinfowler

        本文链接:https://www.haomeiwen.com/subject/getdiqtx.html