垃圾简书,垃圾CEO,垃圾某豚,从此绝不再用。
本文是翻译 https://martinfowler.com/articles/microservices.html 的内容,旨在介绍一下微服务这种设计架构,希望大家尽量阅读原文。文中翻译难免有疏漏,希望大家不吝指正,共同学习。
————————————————————————————————————
微服务架构的定义
“微服务架构”(Microservice Architecture)一词在过去的几年间涌现出来,作为一套可以独立部署的服务,用来描述一种特殊的设计软件应用的方式。虽然没有这个架构风格没有明确的定义,但围绕业务功能的组织,自动部署(automated deployment),端智能(intelligence in the endpoints,)以及对语言和数据的分散控制存在某些共同的特征。
“微服务”,又一个出现在众多软件架构术语中的新词。虽然我们主观倾向于对这样的概念不屑一顾, 但这个词描述了一种让我们觉得越来越有吸引力的软件系统风格。我们已经看到在过去的几年间有多个项目使用这种风格,到目前为止,结果都是乐观的。以至于这已经逐渐成为了我们很多同事在构建企业级应用的默认方式。然而,遗憾的是,并没有太多的信息去概述什么是微服务以及如何去做。
简而言之,微服务架构风格就是将单一应用的开发分为多个小的服务,每个小的服务在自己的进程中运行并使用轻量级机制进行通信(通常是一个HTTP API源),这些服务围绕业务性能进行构建,并且通过完全自动化的部署机制独立的部署。这些只需要最低限度的集中管理的服务,可以使用不同的编程语言编写,以及使用不同的数据存储技术。
为了阐述微服务架构,有必要让其与Monolithic架构进行比较:一个Monolithic应用由一个单元构建。企业级应用通常由三部分构建:客户端界面(包括HTML页面和运行在客户机器上浏览器里的javascript脚本),数据库(许多表构成的、相互关联的关系型数据库管理系统)以及一个服务器端应用。服务器端应用处理HTTP请求,执行域逻辑(domian logic),从数据库中查询和更新数据,选择并填充将要发送到浏览器的视图。这个服务器端程度就是一个Monolithic - 单一的逻辑上可执行的应用。对这个系统的任何更改都会构建和部署一个服务器端应用的新版本。
Monolithic架构是构建这样一种系统很自然的方式。处理请求的逻辑都在一个单一的进程中,允许你使用编程语言的基本特性将应用分割为类,函数以及命名空间。在某些场景中,你可以在开发人员的计算机运行和测试应用,并使用部署管道来确保对更改进行正确的测试以及部署到生产环境中。你也可以横向扩展Monolithic应用,通过负载均衡将多个应用部署到多个服务器上。
Monolithic架构能够成功 , 但是越来越多的对其感到失望, 特别是越来越多的应用被部署到cloud中。变更周期被绑定了,对应用一个小的更改,将会重新构建者部署整个项目。随着时间的推移,通常很难保持一个良好的模块化结构,这使得更改时只影响应用的一个小模块变得更加困难,扩展时需要扩展整个应用,而不只是进行部分部署。
Monolithic架构的这些缺陷导致了Microservices架构的出现:通过一系列的服务去构建应用。服务除了可以独立部署和可扩展之外,每个服务还有固定的模块边界,甚至允许使用不同的语言去编写不同的服务。它们也能被不同的团队进行管理。
我们并不主张说Microservices架构是多么新的东西,它至少可以追溯到Unix设计规范之前。但是我们确实认为没有足够的人去考虑Microservices架构,如果他们使用Microservices架构,很多软件系统将会变得更好。
微服务架构的特征
我们不能说微服务架构有一个正式的定义,但我们可以去尝试描述与“微服务”这个标签相匹配的体系架构的共同特征。正如用一个定义概括任何其他具有共同特征的事物一样,并非所有的微服务架构具有这些所有的特征,但我们确实希望所有的微服务架构具有大多数的这些特征。
尽管笔者们已经是这个相当松散的社区的积极成员,我们的意图是尝试去描述在我们自己的工作中所发现的,以及我们所知道的其他团队类似的努力。特别是我们没有下明确的定义遵守这个架构的时候。
——————————————————————————————————————
组件化(Componentization) 与服务 (Service)
自从我们开创软件行业以来,就会一直希望将组件连接在一起的方式去构建系统,就像我们在物理世界中所看见的一样。在过去的几十年中,我们看见了大量简编的公共库取得的巨大进步,它们是大多数语言平台的一部分。
在谈论组件时,我们遇到了定义上的难题即什么构成了组件。我们的定义是,组件是一个独立的,可替换的和可升级的软件单元 。
微服务架构会使用库,但是其组件化自身软件的主要方式是将其拆分为服务。我们将库定义为连接到程序中的组件,并使用内存中的函数进行调用,而服务则是进程外的组件,这些组件通过webservice请求或者远程过程调用(RPC)等机制进行通信。(组件和服务在很多面向对象编程中是不同的概念)
使用服务作为组件(而不是库)的主要原因是服务是可以独立部署的。如果你的应用由单个进程中的多个库组成,则对单个组件的任何更改都将导致不得不重新部署整个应用。但是,如果将应用分解为多个服务,你可以期望单个服务的更改只需要重新部署该单个服务即可。当然,这也不是绝对的,一些更改将改变服务接口,从而会产生一些协调。但是优秀的微服务架构的目的是通过服务契约中的解耦服务边界和进化机制将这些更改最小化 。
使用服务作为组件的另一个结果是更显式的组件接口。 大多数语言都没有良好的机制来定义显式的发布接口。通常只有文档化和规则才能防止用户破坏组件的封装,从而避免组件之间的紧密耦合。通过使用显式的远程调用机制,服务可以更容易的避免这种这种情况。
使用这样的服务确实有缺陷。远程调用比在进程内调用更消耗资源,由于远程API需要粗粒度的,这通常更难于使用。如果你需要更改服务之间的职责分配,那么当你跨越进程边界时,这种行为方式将会变得更加困难。
在第一种类似情况中,我们注意到服务映射到运行时进程,但这只是第一种类似情况。服务可以由多个进程组成,这些进程将始终被开发和部署在一起,例如应用程序进程和仅由该服务使用的数据库 。
——————————————————————————————————————
围绕业务功能组织
当将一个大型应用分为多个部分时,通常管理会集中在技术层面,UI团队,服务端团队和数据库团队。当团队沿着这条线分开时,即使是简单的变更也会导致跨团队间的项目时间和预算审批的花费。一个聪明的团队会优化这个问题-两害相权取其轻-只需将逻辑置于它们想要访问的应用中。换句话说,逻辑无处不在。这是Conway定律得一个例子。
微服务的划分方法是不同的,它倾向于围绕业务功能的组织来分割服务。此类服务对该业务领域进行了广泛的软件实现,包括用户界面、持久化存储和任何的外部协作。因此,团队是跨职能的,包括开发过程所需的全部技能:用户体验、数据库和项目管理。
有一个以这样的方式进行组织的公司 :www.comparethemarket.com 。跨功能团队负责构建和执行每个产品,并将每个产品分割成多个单独的服务,通过消息总线进行通信。
大型的Monolithic应用也可以围绕业务功能进行模块化,尽管这不是常见的情况。 当然,我们会敦促一个构建Monolithi应用的大型团队,以便将其沿着业务线进行划分。
我们在这里看到的主要问题是,这种组件形式会导致太多的依赖。如果Monolithic跨越了许多模块化的边界,那么团体的个体成员很难将其融入到他们的短期记忆中。此外,我们还发现,模块化需要大量的规则来执行。服务组件要求的分割越明确,使得保持团队之间的界限变得越容易。
——————————————————————————————————————
微服务有多大?
尽管“微服务”已经成为了这种架构风格的流行名称,但是它的名字确实导致了对服务规模的不幸关注,以及关于什么构成“微”的争论。在我们与微服务实践者的交流中,我们看到了一系列服务的大小。 据报道,
最大的规模遵循了亚马逊“Two Pizza Team”的概念(即整个团队两个比萨就够了),也就是不超过12个人。在规模较小的团队里,我们看到的是小规模的团队提供小规模的服务这种配置。
这样就引出了一个问题:在这个范围内是否存在足够大的差异,即每个成员的服务和每个团队的服务的大小不应该被归入一个微服务标签。目前,我们认为最好将它们组合在一起,但当我们进一步探索这种架构风格时 ,我们当然有可能改变我们的想法。
——————————————————————————————————————
产品不是项目
我们看到的大多数应用开发工作都使用了一个项目模型:目的是为了交付一些软件,然后就被认为是完成了。软件完成后被移交给维护部门,构建软件的项目组解散。
微服务的支持者们倾向于避免这种模式,他们更倾向于一个团队应该负责产品的整个生命周期。这是一个共同的灵感,是亚马逊“你构建,你运维”的概念,一个开发团队对软件的开发承担全部的责任。
这使得开发人员每天接触到他们的软件在开发过程中的行为,并增加与用户的联系,因为他们至少要承担一些售后支持负担。
产品的理念,与业务功能联系在一起。并不只是将软件看成一组要完成的功能,还有一个持续性的问题,即软件如何帮助用户提高其业务能力。
我们并没有理由不能使用Monolithic应用,但是服务的粒度越小,就越容易在服务提供者和用户之间建立紧密关系。
——————————————————————————————————————
强化终端及弱化通道(Smart endPoints and dumb pipes)
在构建不同进程间的通信结构时,我们发现很多产品和方法能够更加有效的将其自身加入到通信机制中。其中一个很好的例子是企业服务总线(ESB),ESB产品通常包括用于消息路由,编排,转换和应用业务规则。
微服务社区支持的另一种方法:强化终端及弱化通道 。从微服务中构建的应用的目标是尽可能的解耦和尽可能的内聚-它们拥有自己的域逻辑,就像在经典的Unix意义上的过滤器-接收请求,适当的应用逻辑并生成响应。这些都是使用简单的RESTish协议编排的,而不是像WS-Choreorgaphy或BPE或者由集中式框架编制的复杂协议,最常见的两种协议是携带资源的HTTP请求-响应以及轻量级的消息传递。
——————————————————————————————————————
微服务和SOA
当我们讨论微服务时,一个常见的问题是:这是否仅仅就是我们10年前看到的面向服务的架构(SOA)。这一点是有价值的,因为微服务的风格非常类似于SOA的一些支持者所倡导的。然而,问题是SOA意味着太多不同的东西,而且大多数时候我们遇到的东西被成为“SOA”,它与我们在这里描述的风格有很大的不同,通常是因为ESB用于集成Monolithic应用。
特别是我们已经看到了许多面向服务的拙劣实现-从ESB中隐藏复杂性的倾向-到那些花费数百万美元但并无交付价值,到积极抑制改变的集中管理模式,有时很难看到过去的这些问题。
当然,在微服务中使用的许多技术都是从在大型组织中集成服务的开发人员的经验中成长起来的。Tolerant Reader模式就是一个例子。使用web的努力已经做出了贡献,使用简单的协议是从这些经验中获得的另一种方法 - 从那些已经达到复杂性的中心标准,坦率的说,是惊人的。(任何时候,你需要一个本体来管理你的本体,你知道你身陷困境)。
SOA的这一常见表现致使一些微服务的拥护者完全拒绝SOA,尽管其他人认为微服务是SOA的一种形式,或许面向服务是正确的。无论怎样,SOA都意味着不同的东西,这意味着又一个更清晰的定义这个架构风格的术语是很有价值的。
微服务团队使用万维网(很大程度上是Unix)构建的原则和协议。经常使用的资源可以通过开发人员或者操作人员很少的努力来缓存。
第二种方式是在轻量级消息总线上进行消息传递。这种通信协议非常单一(单一到只负责消息路由)- 简单的实现比如 RabitMQ 和ZeroMQ甚至没有提供可靠的异步机制,以至于需要依赖产生或者消费信息的终端或者服务来处理这类问题。
在Monolith架构中,组件在进程中执行,它们之间的通信通过方法调用或者函数调用来进行。将Monolith架构转换为微服务架构的最大问题在于改变通信模式。从内存调用到RPC的转换会导致不好的信息通信。相反,你需要使用粗粒度的通信方式来代替细粒度的通信。
——————————————————————————————————————
去中心化管理
去中心化管理的结果之一是在单一的技术平台上进行标准化的趋势。经验表明,这种方法是相对的-并不是所有的问题都是钉子,并不是每个解决方案都是锤子。我们更喜欢使用合适的工具来来完成工作,而Monolithic应用可以在一定程度上利用不同的语言,这并不常见。
将Monolithic的组件拆分为服务,我们可以在构建它们的时候有一个选择。你想要使用Node.js来建立一个报表页面?去吧!对于一个几乎接近实时的组件使用C++ ? 很棒。你想要换一种不同的数据库,以便更好的适应一个组件的读取行为吗?我们有重新构建它的技术。
当然,仅仅是因为你可以这样做,并不意味着你应该这样做-但是以这种方式划分的系统意味着你有选择。
构建微服务的团队也喜欢用不同的方法来达到标准。与其将一组定义的标准写在纸上,它们更倾向于使用其他开发人员可以使用的有用工具来解决他们面对的类似问题。这些工具通常从实现中获取,并与更广泛的团队共享,但不完全使用内部的开源模型。现在,git和github已经成为了事实上的版本控制系统,开源实践正变得越来越普遍。
Netflix是遵循这种理念的一个很好的例子。共享有用的,最重要的是,当代码库鼓励其他开发人员以类似的方式解决类似的问题时,如果需要的话,还可以选择不同的方法。共享库往往集中在数据存储、进程间通信等常见问题,以及我们在下面讨论的基础设施自动化。
对于微服务社区来说, 开销问题是特别引人注意的 。 这并不意味着社区不重视服务 交互的价值。 恰恰相反,因为发现它们的价值。这使得它们在寻找各种方法解决它们。像 Tolerant Reader Pattern和Consumer_Driven Contracts Pattern 这样的模式经常被应用到微服务中。这些模式解决了独立服务在交互过程中的交互问题。作为构建的一部分,使用Consumer_Driven Contracts 增强了信心,并提供了关于服务是否运行的快速反馈。事实上,我们知道澳大利亚一个团队,他们使用Consumer_Driven Contracts 来推动新服务的建立。它们使用简单的工具来定义服务的接口。 在新服务的代码编写之前,就已经成为了自动化构建的一部分。然后,只需要指出这些接口的适用范围,这是一种优雅的方法,可以避免在构建新软件时出现"YAGNI"困境。这些技术和工具在使用过程中完善,通过减少服务之间的耦合来限制集中式 管理的需求。
也许去中心化最高点是亚马逊推广的 build it/ run it理念。团队负责他们构建的软件的所有方面,包括全天候的运营软件。移交这一级别的责任肯定不是常态,但是我们确实看见越来越多的公司将责任推给开发团队。Netflix是另一个采用这种理念的组织。每天晚上3点被你的寻呼机吵醒,毫无疑问是你在编写代码时专注质量的强大动力。这些想法与传统的中心化管理模式相去甚远,然而它是可能的。
——————————————————————————————————————
去中心化的数据管理
数据管理的去中心化有许多不同的方式。在最抽象的层次上,这意味着通用概念模型将在系统之间有所不同。在跨大型企业集成时,这是一个常见的问题,客户的销售视图与支持视图不同。在销售视图中,一些被称为客户的东西可能就根本没有出现在支持视图中。那些可能有不同的属性和(更糟糕的)公共属性,具有微妙的不同语义。
这个问题在应用之间很常见,但是也会发生在应用内,特别是应用被划分为独立的组件时。一种有用的思考方式是有界上下文(Bounded Context)的领域驱动设计概念。领域驱动设计将一个复杂的域分割成多个有界的上下文,并映射出它们之间的关系。这个过程对Monolithic架构和微服务架构都很有用,但是在服务和上下文边界之间存在自然的相关性,正如我们在业务功能所描述的那样,强行进程拆分。
除了决定将概念模型去中心化,微服务还决定将数据存储的去中心化。虽然Monolithic应用更喜欢单一逻辑的数据库来持久化数据。但企业更喜欢跨多个应用的单一数据库。许多决策也通过供应商的商业模式授权来驱动。微服务更喜欢让每个服务管理自己的数据库,或者同一数据库技术的不同实例,又或者完全不同的数据库系统 - 一种被称为多持久化(Polyglot Persistence)的方法。你可以在Monolithic架构中使用多持久化的方法,但是它更频繁的出现在微服务中。
在微服务中对数据去中心化对管理更新有影响。处理更新的常用方法是在更新多个资源时使用事务的一致性。这种方法常用于Monolithic架构。
使用这样的事务有助于保持一致性,但是在跨多个服务中造成了严重的耦合问题。众所周知,分布式事务很难实现,因为微服务架构强调服务之间的事务协调并明确一致性可能只是最终的一致性,而问题是通过补偿操作来处理的。
选择以这种方式来管理非一致性对许多开发团队来说是一个全新的挑战,但它常常与业务实践相匹配。通常,企业会处理一定程度的非一致性,以快速响应需求,同时有一些逆转过程来处理错误。只要纠正错误的成本低于在更大的一致性下损失的业务的成本,这种权衡就是值得的。
——————————————————————————————————————
基础设施自动化
基础设施自动化技术宅过去几年中有了巨大的发展-特别是云和AWS的发展,降低了构建、部署和运维微服务的复杂性。
许多使用微服务构建的产品或者系统都是由具有广泛持续部署(Continuous Delivery)经验的团队构建的,这是一个持续集成(Continuous Integration)的先驱,以这种方式构建软件的团队广泛使用基础设施自动化技术。这在下面所示的构建管道中说明。
由于这不是一篇关于自动部署的文章,我们将会把注意力集中在这里的几个关键特性上。我们希望我们的软件应该这样方便的工作,所以我们运行大量的自动化测试。
一个Monolithic应用通过这些环境会构建,测试和推动得非常愉快。事实证明,一旦你为Monolithic应用进入自动化的道路,然后部署更多的应用程序,看起来就不那么可怕了。请记住,CD(持续部署)的目标之一是使发布变得无趣,所以无论是它的一个或者多个应用,它都一样的无趣。
我们看到团队使用广泛的基础设施自动化的另一个领域是在生产中管理微服务。与我们上面断定的不同的是,只要部署很无趣,Monolithic应用和微服务应用之间就没有那么大的差别,每个操作环境都有明显的不同。
——————————————————————————————————————
容错性设计
使用服务作为组件的结果是,应用需要被设计,以便它们能够忍受服务的故障。任何服务调用都可能由于供应商的无法使用而故障,客户端必须尽可能的优雅的做出响应。与Monolithic架构相比,这是一个缺点,因为它引入了额外的复杂性。其结果是,微服务团队不断的想到服务失败如何影响用户体验。Netfix的 Simian Army 可以为每个应用的服务及数据中心提供日常故障监测和恢复。
这种自动化的生产测试足以让大多数的运维团队在一周的工作中能正常上下班。这并不是说Monolithic架构的应用不能进行复杂的监控, 只是在我们的经验中并不常见。
由于服务在任何时候都可能故障,所以能够进行快速检测以及自动恢复 服务是很重要的(如果可能的话)。微服务应用非常重视对应用的实时监控,同时检查架构元素(每秒请求数据库的连接是多少)和业务相关的度量标准(例如:每秒钟收到多少订单)。语义监控可以提供一些异常的早期警报系统,从而触发开发团队的跟进和调查。
这对于微服务的架构尤其重要,因为微服务相互的通信会导致紧急行为。虽然许多专家称赞偶发情况的价值,但事实是,紧急行为有时候是一件坏事。监测对于及时发现不良的紧急行为是至关重要的,以便能够进行修复。
Monolithic应用可以被构建为像微服务一样透明 - 事实上,它们应该像这样。区别在于,你必须知道在不同的进程中运行的服务何时断开。对于同一进程中的库,此类透明度不太可能有用。
微服务团队希望看到每个单独服务的复杂监控和日志设置,如显示 上/下状态的仪表盘以及各种操作和业务相关的度量。关于断路器状态、当前吞吐量和延迟的详细信息是我们经常遇到的其他例子。
——————————————————————————————————————
设计改进
微服务实践者,通常来自于一个不断改进设计的背景,他们将服务分解看作是进一步的工具,使应用的开发人员能够在不减慢更改的情况下控制应用的更改。变更控制并不意味着更改的减少 - 使用正确的方式和工具,你可以对软件进行频繁、快速和可控的更改。
当你试图将一个软件系统分割为组件时,你将作出如何分割这些组件的决定 - 我们决定将应用分割的原则是什么 ? 一个组件的关键属性是独立的、可替换的和可升级的概念,这意味着我们要寻找到一个点,可以在不影响其之前的协作的情况下而重写组件。事实上,许多微服务组织都明确的希望,许多服务是能被取消的,而不是长期的发展下去。
《卫报》网站是一个应用很好的例子,它被设计为Monolithic架构,但是它在向着微服务的方向发展。Monolithic架构仍然是网站的核心,但是它们更喜欢通过使用Monolithic API的微服务来构建新的功能。这种方法对于那些本质上是临时的特性特别有用,比如专门的页面来处理体育赛事。网站的这一部分可以很快的和快速开发语言结合起来,一旦赛事结束,就可以删除。我们在一家金融机构看到了类似的方法,在那里,新的服务会被加入到新的市场机遇中去,并在几个月甚至几周后抛弃。
这种可替换性的强调,是模块化设计一般原则的一个特例,即通过改变的模式来驱动模块化。你希望在同一模块中同时保留更改的内容。一个系统的某些部分,几乎不应该对那些正在经历大量生产的系统提供不同的服务。如果你发现自己在不断的在一起更改两个服务,这表明它们应该被合并。
将组件放入服务中为更细粒度的发布计划提供了机会。对于Monolithic应用,任何更改都需要整个应用的完整构建和部署。然而,对于微服务,你只需要重新部署你修改过的服务。这可以简化并加速发布过程。缺点是,你不得不担心对一个服务的更改会破坏它的使用者。传统的集成方式是使用版本控制来解决这个问题,但是在微服务领域是只将版本控制作为最后的手段。我们可以通过设计服务来避免产生很多的版本,以尽可能的容忍供应商的变化。
————————————————————————————————————————————
微服务架构是未来吗?
我们写这篇文章的主要目的是解释微服务的主要思想和原则。通过花时间来做这件事,我们清晰的认为,微服务架构是一个很重要的想法,它值得企业应用认真的考虑。我们最近建立了几个使用这种风格的系统,并了解使用和支持这种方式的其他人。
我们所知道的那些在某种程度上开创了架构风格的人,包括亚马逊、Netflix、《卫报》、英国政府数字服务公司、realestate.com.au、Forward和comparethemarket.com。在2013的会议上,有很多公司的例子,他们正在转移一些可以使用微服务的东西,包括 Travis.CI。 此外,还有许多组织长期以来一直在做我们认为可以作为微服务的东西,当从来没有使用过这个名称。(通常这被称为SOA - 尽管我们已经知道,SOA有许多相互矛盾的形式)
尽管有这些积极的经验,但是我们并不确信微服务是软件架构的未来方向。虽然到目前为止我们的经验以Monolithic架构相比是积极的,但我们意识到,没有足够的时间让我们做出全面的判断。
通常,你的结构决策的真实结果在你完成后几年才会显现出来。我们已经看到了一些项目,一个好的团队,对模块化的强烈愿望,已经建立了一个Monolithic架构,多年来已经衰败。很多人认为,这种衰败不太可能发生在微服务架构上,因为服务的边界是明确的,很难修补。然而,在我们看到足够多的老系统之前,我们无法真正评估微服务架构是如何成熟的。
有一些原因可以解释为什么人们会认为微服务很不成熟。在组件化的任何努力中,成功取决于软件与组件的匹配程度。很难弄清组件边界的确切位置。进化设计意识到正确的获得边界的困难,因此明白简单重构的重要性。但是,当你的组件是远程通信的服务时,重构比在进程内要困难得多。移动代码很难跨越服务边界,任何接口的更改都需要在参与者之间协调,需要添加层次的向后兼容性,并且测试更加复杂。
另一个问题时,如果组件不干净,那么你做的事情就是将复杂性从组件内部转移到组件之间的连接上。这不仅仅是将复杂性转移到一个更不明确,更难以控制的地方。当你看到一个简单的小组件内部时,很容易会认为事情会更好,同时还会忽略服务之间的混乱连接。
最后,还有团队技能的因素。新技术往往被更熟练的团队使用。但是对于一个更熟练来说,一个更有效的技术并不一定能为不太熟练的团队工作。我们已经看到了许多不太熟练的团队构建杂乱的Monolithic架构的案例,但是要知道这种情况发生在微服务上的时候会带来什么。一个差劲的团队总会创造一个糟糕的系统。- 很难判断微服务是否能减少这种情况,或者使其变得更糟。
我们听到的一个合理的观点是,你不应该从一个微服务架构开始。相反的是,可以从一个Monolithic架构开始,一旦Monolithic架构成为一个问题,就使用模块化,并将其分解为微服务。(尽管这个建议并不理想,因为良好的进程内接口通常不是一个好的服务接口)。
所以我们审慎乐观的写这篇文章。到目前为止,我们已经看到了足够多的微服务风格,认为这是一条值得涉足的道路。我们不能确定我们最终会在哪里,但是软件开发的一个挑战是,你只能根据你目前掌握的不完全信息做出决定。