微服务与微服务架构的主要思想和原则

版权声明:本文为博主原创文章,如果觉得写的不错需要转载,在转载时请注明博文出处! https://blog.csdn.net/Hello_World_QWP/article/details/84929615

                                                  《 微服务与微服务架构 》

前言

再来谈谈微服务,关于“ 微服务架构 ” 早在2014 年一位名为 马丁.福勒 的工程师提出到现在(最早是在1967年,梅尔文.康威的康威定律中提及),经过了几年的沉淀与企业实战运用,已经很健壮了,但是在技术的辩论中,任然会有不少的开发工程师会提及微服务或者微服务架构是,并谈论各自对其的理解与定义,当然我也谈了个大概,其依据是因为在以前看了一篇技术博客,一篇  马丁.福勒 的博客,是关于对 微服务与微服务架构 概述,博主觉得非常有用,可以很好的帮助自己引导自己理解 微服务与微服务架构,并且从他文章中看出了,他是一个非常谦虚的人,所以博主必须向他学习啦,关于本篇博文,篇幅较长,博主也是耗费了一个周左右的时间来构建的这篇文章,如果有什么不足之处,欢迎指正。

 

微服务与微服务架构

微服务定义:

“ 微服务架构 ” —— 这个术语在过去几年里兴起,用来描述一种将软件应用程序设计为可独立部署的服务套件的特殊方式。虽然这种体系结构样式没有精确的定义,但是围绕着系统组织、业务构成、自动化部署、智能终端系统以及对语言和数据分散控制,存在一些共同的特征。

" 微服务 " —— 在软件架构这条拥挤道路上又一个新的名词。 虽然我们自然的倾向是带着轻蔑的眼光看待这些事情,但是这个术语描述了一种软件系统的风格,并且发现这种风格越来越有吸引力。 在过去的几年里,我们已经看到许多项目使用这种架构风格,到目前为止,结果是积极的,以至于对于我们的许多同事来说,这正在成为构建企业应用程序默认的一种架构风格。 然而,遗憾的是,目前乃没有多少信息概述微服务的风格具体是什么以及如实现它。

简而言之,微服务架构风格是一种将单个应用程序开发为一套小服务的方法,而其中每个小服务又运行在自己的进程中,并使用轻量级机制(通常是 HTTP 资源的 API ,也就是博主后面讲到的 REST)进行通信。 这些服务是围绕业务功能构建的,可以通过完全自动化的部署机制独立部署。 这些服务可以用不同的编程语言编写,并使用不同的数据存储技术。

 

在开始介绍微服务风格前,先来比较一下整体风格(如上图):一个单一的应用程序作为一个单一的单位。 企业应用程序通常由三个主要部分构建: 客户端用户界面(由 HTML 页面和运行在用户机器上的浏览器中的 javascript 组成)、数据库(由许多插入到通用的关系型数据库管理系统中的表组成)和服务器端应用程序。服务器端应用程序将处理 HTTP 请求、执行域逻辑、从数据库中检索和更新数据,以及选择和填充要发送到浏览器的 HTML 视图。 这个服务器端应用程序是一个庞然大物——一个逻辑可执行文件。 对系统的任何更改都涉及构建和部署服务器端应用程序的新版本。

这样一个单一的服务器就是构建这样一个系统的自然方法。 处理请求的所有逻辑都在一个进程中进行,允许您使用语言的基本特性将应用程序划分为类、函数和命名空间等。 稍加处理,您就可以在开发人员的笔记本电脑上运行和测试该应用程序,并使用部署管道(Pipeline)来确保正确地测试更改并将其部署到生产环境中。 通过在运行的负载均衡器后面新增多个实例来实现该单体的水平伸缩。

单体应用程序可以提供业务服务,但是越来越多的人对此感到沮丧的——特别是随着越来越多的应用程序被部署到云服务器上。 变更周期是连在一起的 —— 对应用程序的一小部分进行更改,需要重新构建和部署整个程序。 随着时间的推移,到最后通常很难保持一个良好的模块结构,这使得一个模块的更改只影响该模块变得更难(可能会影响到其它业务模块)。 扩展性需要扩展整个应用程序,而不是它的一部分,这样做需要更多资源。

 

 图1:单体应用 VS 微服务(左为单体的横向扩展,右为微服务)

一个单体应用所产生的一系列问题便有了微服务架构风格: 将应用程序构建为服务的套件。 除了服务是独立部署运行和可伸缩之外,每个服务还提供一个稳定的模块边界,甚至允许用不同的编程语言编写不同的服务。 他们也可以由不同的团队研发和管理。

我们并不是说微服务的风格是新颖的或创新的,它的根源至少可以追溯到 Unix 的设计原则(还要往前)。 但我们认为,没有足够多的人考虑在应用程序中使用微服务架构风格,如果他们使用了,或许软件开发将会变得更容易或更方便些。

 


微服务架构特点

我们不能说对微服务架构风格有一个正式的定义,但是我们可以尝试描述我们所看到的适合这个标签的架构的共同特征。 正如勾勒出共同特征的任何定义一样,并非所有微服务架构都具有所有的特征,但我们确实希望大多数微服务架构具有多的特征。 虽然我们的作者一直是这个相当松散的社区的活跃成员,我们的目的是尝试描述我们在自己的工作中看到的情况,以及我们所知的团队在类似的努力中看到的情况。 特别是我们没有定下一些定义来符合。

 

通过服务的组件化

自从我们涉足软件行业以来,人们就一直希望应用程序通过以组件方式组合在一起来构建成一个系统,我们看到的很多东西都是在物理世界中制造出来的。 在过去的几十年里,我们已经看到了在作为大多数语言平台一部分的大量公共库在组合方面取得了相当大的进展。

当我们在谈论组件时,我们遇到了一个困难的组件定义的问题。 我们的定义是:组件是独立可替换的和可升级的单个软件单元。

微服务架构将使用各种库,但这种架构会把软件给拆分成各种不同的服务来实现组件化。 这里我们定义两个重要的概念:第一个是库,库指的我们将库定义为链接到程序中并使用内存中的函数来调用的组件,第二个是服务,服务是指进程外的组件,它们与诸如 web 服务请求或远程过程调用等机制进行通信(注意:这儿和很多诸如面向对象程序里服务对象的机制是不同的 )。 

之所以在组件化的软件里用服务,而不是库,是因为每个服务是独立部署的。 比如说,如果在同一个软件里用了多个库,那么就算只是修改了其中一个,都会导致整个软件要被重新部署运行; 但是,如果该应用程序被分解为多个服务,那么只需要重新部署修改过的服务即可。但这并不是绝对的---- 例如,一些变化会改变服务接口,从而导致一些接口调用问题,为避免这些问题,一个好的微服务架构的目标是通过高内聚的服务边界和服务契约的演化机制来最小化这些变化的。

将服务用作组件的另一个结果是一个更明确的组件接口。大多数语言都没有定义显式发布接口的良好机制。 通常只有文档和规则才能防止客户端打破组件的封装,从而导致组件之间的耦合过于紧密。 通过使用显式的远程调用机制,服务可以更容易地避免这种情况。

使用这样的服务也有缺点。即远程调用比进程内调用开销更大,因此远程 api 需要更粗粒度,但这通常更难于使用。 如果您需要更改组件之间的职责分配,那么当您跨越过程边界时,这种行为将更加困难。

我们可以观察到服务映射到运行时进程,但这只是第一次近似。一个服务可能进程组成,这些进程将始终会一起开发和部署,例如应用进程和该服务所用到的数据库。

 

围绕业务功能进行组织

当需要将大型应用程序拆分为多个部分时,管理层通常关注于技术层,从而形成了 UI 团队、服务器端逻辑团队和数据库团队。 当团队按照这些原则分开时,即使是简单的更改也可能导致跨团队项目需要时间和预算批准 。一个聪明的团队会优化这一点,然后选择两害相权取其轻的方式——只要将逻辑强加于他们能够访问的任何应用程序即可。 换句话说,逻辑无处不在。 这是康威定律在实际运用中的一个例子。

任何设计系统(广义定义)的组织都会产生一种其结构是组织通信结构副本的设计。
——梅尔文 · 康威(Melvyn Conway) ,1967年

 

 图二:康威定律动作示意图

对于微服务划分方法是不同的,康威定律将服务围绕业务能力的不同来组织分解服务。这些服务需要对该业务领域的软件进行广泛的实施,包括用户界面、持久性存储和任何外部协作。因此,团队是跨职能的,包括开发所需的全部技能:用户体验、数据库和项目管理等。

 

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

(如上图)这样组织起来的一个公司是 www.comparethemarket.com。跨职能团队负责构建和操作每个产品,每个产品划分成多个单独的服务,服务间通过消息总线进行通信。

大型单片应用程序也可以围绕业务功能进行模块化,尽管这种情况并不常见。当然,我们会敦促构建完整应用程序的大型团队沿着业务线进行自我划分。我们在这里看到的主要问题是,它们往往围绕太多的上下文进行组织。如果过大的跨越了这些模块的许多边界,那么团队中的单个成员就很难将它们融入他们的短期记忆中。此外,我们发现模块化后的代码行需要大量的规则来执行。服务组件需要更明确的分离,这样便使得保持团队边界更加清晰。

 

^ 微服务到底有多大?&

尽管 “ 微服务 ” 已经成为这种体系架构风格的一个流行的名称,但它的名称确导致了对服务大小的不当焦点,以及关于什么是 “ 微 ” 的争论。在与微服务从业人员的对话中,我们看到了各种各样的服务。据报道,最大的规模是按照亚马逊的概念,即两个披萨团队(即整个团队可以吃两个披萨),即不超过12个人。在较小的规模上,我们已经看到了由6人组成的团队支持6种不同服务的设置。

这就引出了这样一个问题: 即在这个大小范围内是否存在足够大的差异,即每6人的服务规模和每人的服务规模不应该被归为一个微服务标签下。目前我们认为将它们组合在一起是最好的,但是随着我们进一步对这种风格的探索,我们当然有可能会改变这种主意的。

 

产品而非项目

我们看到的大多数应用程序开发工作都使用项目模型:目标是交付一些软件,然后这些软件被认为已经完成。完成后,软件被移交给维护组织,构建它的项目团队被解散。

微服务的支持者倾向于避免这种模型,他们更喜欢团队应该在整个生命周期内拥有一个产品的概念。一个常见的灵感是Amazon的 “ 您构建的产品,您维护它 ” 的概念,在这个概念中,开发团队对生产中的软件承担全部责任。这将使开发人员每天接触他们的软件在生产中的行为,并增加开发人员与用户的接触,因为他们必须承担至少一部分支持负担。

对于产品心态,与业务能力挂钩。与其将软件看作一组要完成的功能,还不如将软件看作是一种持续的关系,在这种关系中,问题就是软件如何帮助用户增强业务能力。

没有理由不能在单体应用程序中采用相同的方法,但是更细粒度的服务,可以更容易地在服务开发者和他们的用户之间建立良好的人际关系。

 

智能终端和无声管道

在不同流程之间构建通信结构时,我们已经看到许多产品和方法都强调在沟通机制本身中投入大量的智慧。企业服务总线(Enterprise Service Bus,ESB)就是一个很好的例子,其中 ESB 产品通常包括复杂的消息路由设施、编排、转换和应用业务规则等。

微型服务社区更倾向于另一种方法:智能端点和无声管道。基于微服务构建的应用程序的目标是尽可能地解耦和内聚——它们拥有自己的业务逻辑,更像是经典 Unix 意义上的过滤器——接收请求,适当地应用逻辑并生成响应。这些是使用简单的 RESTish 协议编排的,而不是使用复杂的协议,如WS-Choreography、BPEL或由中心工具编制的编排。

最常用的两种协议是带有资源 API 的 HTTP 请求-响应协议和轻量级消息传递协议。第一个的最好表达是:

成为 Web 的一部分,而不是落后于 Web 之后

微服务团队使用构建在万维网(很大程度上是Unix)上的原则和协议。开发人员或操作人员只需很少的努力就可以缓存经常使用的资源。

第二种常用的方法是通过轻量级消息总线进行消息传递的。所选择的基础设施通常是无声的(无声作为消息路由器)——简单的实现,如 RabbitMQ 或 ZeroMQ,除了提供可靠的异步架构外,不会做更多的事情——智能仍然存在于产生和消费消息的终端上;存在于服务种。

在一个单体应用中,组件是在进程内执行的,组件之间的通信是通过方法调用或函数调用进行的。将一个单体变成微型服务的最大问题在于改变通信模式。 从内存中方法调用再到 RPC 的简单转换会导致通信不畅,无法很好地执行。相反,您需要用粗粒度的方法取代细粒度的通信。

 

^ 微服务和 SOA &

当我们谈到微服务时,一个常见的问题是,这是否只是我们十年前看到的面向服务体系架构(Service Oriented Architecture, SOA )。这一点是有好处的,因为微服务风格非常类似于一些 SOA 倡导者所支持的风格。然而,问题是“ SOA ” 意味着太多不同的东西,而且大多数时候我们遇到的所谓的 “ SOA ” 与我们在这里描述的风格有很大的不同,这通常是由于对用于集成单体应用程序的“ ESB ” 的关注。

特别是我们已经看到这么多糟糕的面向服务的实现——倾向于在ESB中隐藏的复杂性,到多年的计划失败,数以百万计的成本和交付变得没有价值,再到集中治理模式,积极抑制变化,导致了很难看到过去的这些问题。

当然,在微服务社区中使用的许多技术都是从大型集成系统服务开发人员的经验中发展而来的。 Tolerant Reader 模式就是一个例子。web的使用已经为此做出了贡献,使用简单的协议是从这些经验中衍生出来的另一种方法——一种远离已经达到复杂程度(坦率地说,令人激动)的中心标准的反应(任何时候你需要一个实体来管理你的众多实体,你就知道你有多大麻烦了!)。

对于SOA 的这种常见表现形式已经导致一些微服务倡导者完全拒绝 SOA 标签,尽管其他人认为微服务是 SOA 的一种形式,也许面向服务的做法是正确的。不管怎样,SOA 意味着如此不同的东西,这意味着有一个更清晰地定义这种架构风格的术语是有价值的。

 

服务分散治理

集中化治理的后果之一,是在单一技术平台上标准化的趋势。经验表明,这种方法是有局限性的——不是每个问题都是钉子,也不是每个解决问题的方案都是锤子。我们更喜欢使用适合这项工作的工具,虽然单一应用程序可以在一定程度上利用不同的语言,但这种情况并不常见。

在构建每个组件时,我们可以选择将整个应用程序以组件的方式拆分成不同模块的服务。你想用 Node.js 来建立一个简单的报告页面吗? 去吧。一个特别粗糙的接近实时的组件使用 C++?很好。您希望切换到更适合某个组件的读取行为的不同风格的数据库吗?我们有重建他的技术。

当然,仅仅因为您可以做一些事情,并不意味着您应该这么做——但是以这种方式对系统进行分区意味着您可以选择。

构建微服务的团队也喜欢采用不同的标准方法。相对于使用一套写在纸上定义好的标准,他们更喜欢产生有用的工具,其他开发人员可以使用这些工具来解决与他们面临的类似的问题。这些工具通常从实施中获取,并与更广泛的群共享,但有时并不会完全使用内部开源的模型。现在 git 和 github 已经成为现实的版本控制系统的选择,使得开源实践在其内部变得越来越普遍。

Netflix 组织就是遵循这一理念的一个很好的例子。作为共享库,共享有用的、经过实战考验的代码可以鼓励其他开发人员以类似的方式解决类似的问题,但是如果需要,也可以选择不同的方法。共享库往往关注数据存储、进程间通信以及基础设施自动化等常见问题。

对于微服务社区,管理费用尤其没有吸引力。这并不是说社区不重视服务合约。恰恰相反,因为它们的数量往往更多。只是他们在寻找管理这些合约的不同方式。像 Tolerant Reader(容错读取)和 Consumer-Driven Contracts (消费驱动合约)模式这样的模式经常应用于微服务。这些帮助服务合约独立发展。作为构建的一部分,执行消费者驱动的合约可以增强信心,并提供关于服务是否正常运行的快速反馈。事实上,我们知道在澳大利亚有一个团队,他们用消费者驱动的合约来驱动新服务的构建。它们使用简单的工具来定义服务的合约。在为新服务编写代码之前,这已经成为自动化构建的一部分。然后,服务被构建到满足合约的程度——这是一种优雅的方法,可以在构建新软件时避免 “ YAGNI ”困境。通过减少服务之间的时间耦合,这些技术和围绕它们成长起来的工具限制了对中央合约管理的需求。

或许,服务的治理的巅峰是由亚马逊(Amazon)推广的"建设、管理、创新"(build it/run it)的理念(这儿就是博主在前面文章中提到的,谁构建它,谁运行它)。 团队负责他们构建的软件的所有方面,包括7*24小时软件运维。 在这种级别的责任<下放>肯定不是标准,但我们确实看到越来越多的公司将责任推给开发团队。 Netflix 是另一个采纳了这种理念的组织。 每天凌晨3点被传呼机吵醒肯定是一个强大的激励,让你在编写代码时专注于质量。 这些想法与传统的集中式治理模式相比甚远。

 

多语言、多选择

JVM 作为平台的发展仅仅是一个最新的在通用平台上实现多语言的例子。数十年来,为了利用更高层次抽象的优势,更高级的语言已经被普遍采用。正如在更底层的水平上,降低到硬件层面去编写性能敏感的代码一样。然而,许多大型系统并不需要这个层面的性能优化,也不需要DSL和更高层面的抽象(这让我们感到非常沮丧)。相反,大型系统使用的开发语言通常是单一的,其趋势是限制使用的技术的数量。

 

经过实战检验的标准和强制执行的标准

微服务团队倾向于避开企业架构团队制定的那种严格执行的标准,而是乐于使用甚至推广HTTP、ATOM和其他微格式等开放标准,这是一种有点类似于二分法的情况。

关键的区别在于标准是如何制定和执行的。关键的区别在于如何制定标准以及如何执行标准。 由 IETF 等组织管理的标准只有在更广泛的领域中有多个实际实现的情况下才会成为标准,这些标准往往来自成功的开源项目。

这些标准与企业界中的许多标准是不同的,企业界中的许多标准通常是由缺乏编程经验或或者过度受供应商影响的团体开发的。

 

分散式数据管理(去中心化数据管理)

数据管理的分散化有许多不同的方式。在最抽象的层次上,它意味着全世界的概念模型在不同的系统之间是不同的。在跨大型企业集成时,这是一个常见的问题,客户的销售视图与支持视图不同。 在销售视图中称为客户的一些内容可能根本不会出现在支持视图中。 如此以来就可能具有不同的属性,而且(更糟糕的是)具有细微不同语义的公共属性。

这个问题在应用程序之间很常见,但也可能发生在应用程序内部,特别是当应用程序被划分为单独的组件时。 关于这个问题,一个有用的思考方式是有界上下文的领域驱动设计理念(Domain-Driven Design,DDD)。 DDD 将复杂域划分为多个有界上下文,并绘制出它们之间的关系。 这个过程对于单体架构和微服务架构都很有用,但是服务和上下文边界之间存在一种自然的相关性,这种相关性有助于澄清,正如我们在业务功能部分所描述的那样,加强了分离。

除了分散有关概念模型的决策外,微服务还分散数据存储决策。 虽然单片应用程序更喜欢使用单个逻辑数据库来存储持久性数据,但是企业通常更喜欢跨一系列应用程序使用单个数据库——这些决策中的许多都是通过供应商的商业模型围绕许可做出来的。微服务更喜欢让每个服务管理自己的数据库,要么是相同数据库技术的不同实例,要么是完全不同的数据库系统——这是一种称为 Polyglot Persistence 的方法。您可以在一个单片应用中使用 Polyglot Persistence,但是它在微服务中出现的频率更高。

图4:微服务架构演变(单片应用对应单实例数据库——到微服务对应的应用程序数据库)

对于跨微服务分散数据责任对管理更新具有影响。处理更新的常用方法是在更新多个资源时使用事务来保证一致性。这种方法通常在单片应用程序中使用。

像这样使用事务有助于提高一致性,但是增加了显著的时间耦合,这在多个服务之间是有问题的。 众所周知,分布式事务是难以实现的,因此微服务架构强调服务之间的无事务协调,并明确承认一致性可能只是最终一致性,问题通过补偿操作来解决的(这儿在后面的文章中还要具体的讲解)。

对于许多开发团队来说,选择以这种方式管理不一致性是一个新的挑战,但是它经常与业务实践相匹配。为了对需求做出快速反应,企业通常会处理一定程度的不一致,同时会有某种逆转过程来处理错误。只要修正错误的成本低于在更大的一致性下业务损失的成本,这种权衡是值得的。

 

基础设施自动化

在过去几年里,基础设施自动化技术有了很大的发展——云计算和AWS的发展降低了构建、部署成本和降低了操作微服务的操作复杂性。

许多使用微服务构建的产品或系统都是由具有大量持续交付经验的团队构建的,它的前身是持续集成。以这种方式构建软件的团队广泛使用了基础设施自动化技术。这在下面的构建管道中进行了说明:

图5:基本构建管道示例

由于这不是一篇关于持续交付的文章,我们将在这里只关注几个关键特性。我们希望我们的软件能够正常工作,所以我们运行了大量的自动化测试。将工作软件“升级”到管道意味着我们可以自动部署到每个新的环境。

单片应用程序将很随意地构建、测试和推送到这些环境中。事实证明,一旦你投身于自动化生产过程,那么部署更多的应用程序看起来就不那么可怕了。请记住,CD 的目标之一是让部署变得无聊枯燥,所以不管它是一个还是三个应用程序,只要它仍然无聊,就没有关系。

我们看到团队使用广泛的基础设施自动化的另一个领域是在生产中管理微服务。与我们上面的论断相反,只要部署是无聊枯燥的,那么单体服务和微服务之间就没有太大的区别,两者的运营环境可能会截然不同。

图6:模块部署通常是不同的(单片应用,多个模块在同一个进程中——微服务,模块运行在不同的进程中)

 

让做正确的事情变得容易

我们发现,由于持续交付和部署,自动化程度提高的一个副作用就是创建了一些有用的工具来帮助开发人员和操作人员。用于创建人工制品、管理代码库、建立简单服务或添加标准监视和日志记录的工具现在非常常见。WEB 上最好的例子可能是 Netflix 的一套开源工具,但是还有其他一些工具,包括 Dropwizard,我们已经在广泛使用了。

 

为失败而设计(为故障做好准备而设计)

将服务作为组件使用的结果是,需要设计应用程序,以便它们能够容忍服务的失败。任何服务调用都可能由于供应商不可用而失败,客户端必须尽可能优雅地对此作出响应。与整体设计相比,这是一个缺点,因为它引入了额外的复杂性来处理它。其结果是,微服务团队不断反思服务失败会如何影响用户体验。Netflix 的 Simian Army 在日常工作中引入服务甚至数据中心出现故障,以测试应用程序的弹性和监控能力。

在生产中,这种自动化测试足以让大多数运维团队在休假一周之前感到不寒而栗。这并不是说单片应用架构风格不能进行复杂的监视设置——只是在我们的经验中不太常见。

由于服务可能在任何时候失败,因此能够快速检测故障并在可能的情况下自动恢复服务非常重要。微服务应用程序非常强调对应用程序的实时监控,检查架构元素(数据库每秒接收多少请求)和业务相关指标(例如每分钟接收多少订单)。语义监视可以提供一个错误的早期预警系统,从而引导开发团队进行跟踪和调查。

这对于微服务体系结构尤其重要,因为微服务对编排和事件协作的偏好会出现紧急行为。尽管许多权威人士赞扬偶然出现的价值,但事实是,偶然出现的行为有时可能是一件坏事。监控对于快速发现不良紧急行为是至关重要的,这样才能修复它。

可以把单片应用架构得像微型服务一样透明——事实上,它们应该是透明的。 不同之处在于,您绝对需要知道在不同进程中运行的服务何时断开连接。 对于同一进程中的库,这种透明性不太可能有用。

微服务团队希望看到每个单独服务的复杂监视和日志设置,比如显示启动/ 关闭状态的仪表板,以及各种与操作和业务相关的指标。关于断路器状态、流的吞吐量和延迟的详细信息是我们经常遇到的其他例子。

 

^断路器和生产准备代码&

断路器出现在释放它!与Bulkhead 和Timeout等其他模式一起。这些模式一起实现,在构建通信应用程序时非常重要。这篇 Netflix 博客很好地解释了它们的应用。

 

^同步调用被认为是有害的&

任何时候,只要服务之间有多个同步调用,都会遇到停机时间带来的倍增效应。简单地说,这就是当系统的停机时间成为单个组件停机时间的产物时。您面临一个选择,是异步调用还是管理停机时间。在 www.guardian.co.uk,他们在新平台上实现了一个简单的规则——每个用户请求一次同步调用,而在 Netflix,他们对平台 API 的重新设计将异步性嵌入了 API 结构。

 

演进式设计

微服务从业人员,通常来自一个进化的设计背景,并将服务分解视为一个进一步的工具,使应用程序开发人员能够控制应用程序中的更改,而不会减慢更改的速度。 变更控制并不一定意味着变更减少——通过正确的态度和工具,您可以对软件进行频繁、快速和良好的控制变更。

无论何时,当您试图将软件系统拆分为组件时,您都面临着如何划分这些组件的决定——我们决定将应用程序拆分的原则是什么?或者拆分的依据是什么? (组件的关键属性是独立的,可替换和可升级的)——这意味着我们需要寻找可以在不影响其协作的情况下重写组件。 实际上,许多微型服务团队通过明确地预期将许多服务废弃,而不是长远发展。

卫报网站就是一个很好的例子,这个应用程序被设计和构建成一个整体,但是一直在向微服务的方向发展。 其 monolith 仍然是网站的核心,但是他们更喜欢通过构建使用 monolith API 的微服务来添加新的功能。 这种方法对于本质上是临时性的特性尤其方便,比如处理体育赛事的专用页面,这种方法特别方便。 网站的这一部分可以使用快速开发语言快速组合在一起,并在活动结束后删除掉。 我们在一家金融机构看到过类似的做法,为了市场机遇而增加新服务,但几个月甚至几周后就放弃并删除了这些新增的服务。

这种对可替换性的强调是模块化设计的一个更普遍原则的特殊情况,该原则是通过更改模式来驱动模块化。您希望在同一个模块中保存同时更改的内容。系统中很少改变的那部分应该在不同的服务中,而不是存在于那些经常大量变动的服务中。如果您发现自己反复地同时更改两个服务,那说明你应该合并这两个服务了。

将组件放入服务中为更细粒度的发布计划提供了机会。对于一个整体服务来说,任何更改都需要完整地构建和部署整个应用程序。然而,对于微服务,您只需要重新部署您修改的单个服务组件。这可以简化和加快发布过程。缺点是您不得不担心一个服务的更改会不会影响到其使用的用户。传统的集成方法是尝试使用版本控制来处理这个问题,但是在微服务领域中更倾向于只将版本控制作为最后的手段。我们可以通过设计服务尽可能容忍其供应商中的更改,以此来避免产生大量的版本控制。

 


微服务即未来?

我们写这篇文章的主要目的是解释微服务的主要思想和原则。 通过花这么多时间这样做,我们清楚地认为微服务架构风格是一个重要的想法——一个值得企业应用程序认真考虑的想法。 我们最近已经构建了几个使用这种风格的系统,并且了解了其他使用和支持这种体系架构风格的人。

据我们所知,在某种程度上开创这种架构风格的公司包括亚马逊(Amazon)、Netflix、卫报(the Guardian)、英国政府数字服务公司 、realestate.com.au、Forward 和 comparethemarket.com。2013年的架构师研讨会议上,到处都是公司正在转向微服务领域的例子——包括特拉维斯·CI (Travis CI)。此外,还有很多组织长期以来一直在做我们称之为微服务的工作,但从未使用过这个名称。(这通常被称为 SOA ——尽管正如我们所说的,SOA 有许多相互矛盾的形式)。

尽管有这些积极的经验,但是,我们并不认为微服务是软件架构的未来方向。虽然到目前为止,我们的实际应用经验与单片应用程序相比是积极的,但是我们意识到我们还没有足够的时间来做出全面的判断。

通常,您的架构决策的只有在您做出这些决策的几年之后才会体现出来其真正的效果来。我们已经看到过这样的项目: 一个对模块化有着强烈渴望的优秀团队,构建了一个已经过时多年的单片应用的架构。 许多人认为这种过时的现象在微服务中不太可能发生,因为服务边界是显式的,而且很难修补。 然而,在我们看到足够多的具有足够年龄的系统之前,我们不能真正判断出微服务架构是如何成熟的。

人们当然有理由认为微服务会不成熟。在任何组件化工作中,成功与否取决于软件与组件的配合程度。很难确切地指出组件边界应该位于何处。因为进化设计认识到了正确划分边界的困难,从而认识到了重构边界的重要性。但是,如果您的组件是具有远程通信的服务,那么重构就比使用进程内库困难得多。跨服务边界移动代码是困难的,任何接口的更改都需要在参与者之间进行协调,需要添加向后兼容层,测试也变得更加复杂化。

另一个问题是,如果组件组合不清晰,那么您所做的就是将复杂性从组件内部转移到组件的连接之间。 这不仅仅是把复杂性转移了,它还把复杂性转移到了一个不那么明确、更难控制的地方。 当您看到一个小的、且简单的组件内部时,很容易认为事情会更好,而忽略了服务之间混乱的连接问题。

最后,还有团队技能因素。新技术往往会被经验丰富的团队所采用。 但是,对于一个经验丰富的团队来说更有效的技术并不一定适用于技术水平较低的团队。 我们已经看到许多缺乏经验的的团队构建混乱的单片架构的案例,但是需要时间来了解当这种混乱出现在微服务中时会发生什么。 一个糟糕的团队总是会创建一个糟糕的系统——在这种情况下,很难判断微服务让这个系统是减少了混乱,还是让这个系统变得更糟糕。

我们听到的一个合理的论点是,您不应该从微服务架构开始。 取而代之的是从一个单片应用开始,保持它的模块化,一旦这个单片应用出现问题,就把它拆分成微型服务。 (尽管这个建议并不理想,因为一个好的进程内接口通常不是一个好的服务接口)。

因此,我们怀着谨慎乐观的态度撰写这篇文章。到目前为止,我们已经看到了足够多的关于微服务风格的信息,因此认为这是一条值得走的道路。 我们不能肯定地说我们将在哪里结束,但软件开发的挑战之一是,您只能基于您目前必须掌握的不完全信息做出决定。

参考资料:
克莱门斯·韦斯特斯的博客
https://blogs.msdn.microsoft.com/clemensv/
大卫·莫甘蒂尼的博客
http://davidmorgantini.blogspot.com/2013/08/micro-services-introduction.htm
英国政府的数字服务设计原则
https://www.gov.uk/design-principles
吉米·尼尔森的博客
http://jimmynilsson.com/blog/
有关更多信息的最新资源列表,请参阅 Microservice 资源指南
https://martinfowler.com/microservices/


好了,关于微服务与微服务架构的主要思想和原则  就写到这儿了,如果还有什么疑问或遇到什么问题欢迎扫码提问,也可以给我留言哦,我会一一详细的解答的。 
歇后语:“ 共同学习,共同进步 ”,也希望大家多多关注CSND的IT社区。


作       者: 华    仔
联系作者: [email protected]
来        源: CSDN (Chinese Software Developer Network)
原        文: https://blog.csdn.net/Hello_World_QWP/article/details/84929615
版权声明: 本文为博主原创文章,请在转载时务必注明博文出处!

猜你喜欢

转载自blog.csdn.net/Hello_World_QWP/article/details/84929615