Skip to content

Latest commit

 

History

History
101 lines (52 loc) · 16.8 KB

寻根溯源:微服务模式发展简史.md

File metadata and controls

101 lines (52 loc) · 16.8 KB

寻根溯源:微服务模式发展简史

探索过去的软件设计模式对创建微服务的影响

标签: Cloud Foundry,DevOps,Java,云计算,容器,平台即服务,微服务

原文链接

Kyle Brown

发布: 2017-02-08


简介

微服务是商业应用程序开发中最热门的新事物。 微服务 这个词取代了敏捷、DevOps 和 RESTful,成为了所有简历和大会演讲中都必须提及的新热门词。但微服务并不只是一个流行词或人们一时的兴趣。事实上 ,它们是所有这些以前的概念的演化结果,是一种开始表现出巨大潜力的,有望解决应用程序开发中许多长期存在的问题的方法。在阅读本 文的过程中,您可以观看 MicroservicesTV 第 13 集第 14 集(参见下文),了解微服务是如何发展的、为何获得发展,以及朝哪个方向发展。

MicroservicesTV 第 13 集:微服务的演化(第 1 部分)

点击查看视频演示

回到最初

要了解此演变过程,我们需要回到最初,分析微服务是什么、它们取代了什么,以及它们为什么变得必不可少。让我们回到 上世纪 80 年代初,第一种重要的系统分发技术“远程过程调用 (RPC)”诞生的时候。RPC 是 Sun Microsystems 最初的 ONC RPC 背后的设想理念,也是 DCE(1988 年)和 CORBA(1991 年)背后的基本理念。

在这些技术中,基本思路都是让远程调用对开发人员保持 透明。这么做的愿景是,如果开发人员不必关心他们调 用的过程调用或方法是位于本地还是远程位置,那么他们就可以构建更大的跨机器系统,从而避免影响当时的系统的处理问题和内存扩展问 题。(请记住,当时最常用的处理器是具有 64K 地址空间的 16 位处理器!)

随着处理器改进和本地地址空间的扩大,这个问题变得不太重要。此外,DCE 和 CORBA 的第一组大型实现告诉了架构师一个有关分布式计算的重要观察结论:

某个功能 能够 分散化,并不代表着它就 应该 分散化。

一旦大内存空间得到普及,选择将方法分散到多个机器上显然会给系统性能带来极大的影响。将所有功能分散化的早期动力 催生了许多拥有各式各样接口的系统 — 这种分散化甚至达到了分散面向对象的语言中的变量 getter 和 setter 的程度。在类似这样的系统中,网络开销带来的弊端远远超过了分散带来的优势。

这导致我们提出了第一种模式,该模式旨在解决上述观察结论 — 而且是我与 John Crupi 和 Martin Fowler 分别发现的模式。在所有情况下,我们都会首先查阅 Erich Gamma 编写的图书《 设计模式:可复用面向对象软件的基础》,然后我们注意到了 Façade 模式。Facade 模式的用途是将大型系统的非结构化接口封装到一个更加结构化的接口中,以减少随意性。换句话说,它旨在减少系统的 接口横截面。我们开发的 Session Facade 方法对分布式系统应用了这种模式,识别整个子系统中关键的粗粒度接口,仅公开用于分散化的接口。

我们使用 Enterprise JavaBeans (EJBs) 实现了第一个 Session Facade,尽管仅在 Java 中使用时很有效,但它很复杂,难以调试,而且无法与其他语言或其他供应商产品互操作。缺乏互操作性直接导致我们在 2000 年代初期到中期开展了下一项工作:该工作成果后来以面向服务的架构 (SOA) 而闻名。但是,SOA 最初没有采用这个高端 大气的术语。它最初始于一次“以最简单方式实现目标”的尝试,获得的成果就是 Microsoft 最初在 1999 年发布的简单对象访问协议 (SOAP)。

在 SOAP 的核心中,SOAP 只不过是一种通过 HTTP 调用对象方法的方式。它利用了 2000 年代初的计算领域的两个特征: 企业网络中对 HTTP 的支持越来越多,以及事实上此支持包含登录和调试基于文本的网络调用的机制。

围绕 SOAP 进行的初期工作很有帮助,这一点很快得到证明,人们可以轻松地合并使用许多不同语言和在许多不同平台上实 现的系统。但 SOA 在整体上的败笔是,它脱离了简单的初衷,开始添加一层又一层脱离了简单方法调用的一些附加概念:添加了异常处理、 事务支持、安全性和数字签名,人们感觉 SOA 已经变成了一个复杂协议。这就引出了下一个重要观察结论:

尝试让分布式调用的行为像本地调 用,这最终带来一些苦果。

整个行业已慢慢转向抛弃 SOAP 和 WS-* 标准中固有的过程化、分层概念。人们开始更普遍地采用具象状态传输 (REST), 此概念可追溯到 Roy Fielding 在 2000 年发表的哲学博士论文。REST 的基本原理非常简单:将 HTTP 作为 HTTP 对待。不采用基于 HTTP 的分层过程调用语义,REST 对待 HTTP 动词的方式是,按照创建、读取、删除和更新语义的形式指定它们。它还列出了通过网络上的另一种被接受的原则指定唯 一实体名称的方式:URI。

与此同时,Java Platform, Enterprise Edition (JEE) 和 SOA 领域的另一个传统(大型的应用服务器场)也逐渐被行业抛弃。自 1999 年推出 Enterprise Java(奇怪的是版本为 1.2)以来,应用程序所有者与应用程序管理员之间的关系就一直很紧张。

在推出 JEE 时,许多企业已经转而采用使用应用服务器托管许多不同应用程序的概念,因为它类似于来自大型机领域的现 有 IT 模型。一个操作小组控制、监视和维护来自 Oracle 或 IBM 的相同应用服务器的“农场”,并在这个“农场” 上部署不同的部门级应用程序。这种标准化和一致性对操作团队很有用,而且降低了总体操作成本。但这与应用程序开发 人员产生了冲突,因为开发和测试环境很大,很难创建,而且需要操作团队干预。这通常意味着新环境可能需要花几个月才能完成创建,这 延缓了项目进度并增加了开发成本。此外,因为这些环境不受该团队的控制,所以不同环境的应用服务器版本、补丁级别、应用程序数据和 软件安装常常不一致。

开发人员更喜欢更小的、轻量级的应用程序平台 — 通常是一些开源的应用服务器,比如 Tomcat 或 Glassfish。同时,随着控制反转和依赖注入等技术得到普及,人们避开了 JEE 的复杂性,而喜欢上了 Spring 平台所提供的简单性。这么做的收获是,开发团队发现,他们能够自行在彼此尽可能接近的开发、测试和生产环境中 一致地构建和部署应用程序,不仅速度更快,而且出错率更低,因为源于环境不一致性的所有错误都被消除了。这引出了下一个观察结论:

您的程序和它们的运行时环境应尽可能完全独立。

这 3 个观察结论是 Fowler 描述的微服务的核心。Fowler 的微服务设计原则之一是,微服务是“围绕业务能力进行组织的”。该原则直接源于一种发现:您能够分散某项功能,并不意味着您就应该分散它。Façade 模式在其各种表现形式中的整体概念是,为系统或子系统定义一个特定的外部 API。言外之意是,这个 API 是业务驱动的 。Fowler 直接道出了这一言外之意。

通常,一些开发团队很难理解这句话 — 他们不习惯设计业务接口,于是他们可能很快将重点转到技术接口上(比如登录或日志记录)。在这些情况下,许多团队 发现 Eric Evans 的图书《 领域驱动设计》中介绍的一些模式很适用。具体来讲,他的 Entity 和 Aggregate 模式对识别与微服务直接对应的具体业务概念很有用。类似地,对于没有对应的单一实体或集合的操作,他的 Services 模式提供了一种方法来将它们映射到构建微服务所需的基于实体的方法。

同样,Fowler 的采用“智慧端点和哑管道”的原则源于以下经验:使用 EJB、SOAP 和其他复杂分发技术的团队最终发现,尝试让分布式系统看起来像本地系统最终会带来苦果。最后,Fowler 围绕分散化治理和分散化数据管理的规定源于一项来之不易的发现:您的程序和运行时环境应自给自足。

这给我们带来什么启发?

Fowler、Adrian Cockcroft 和其他人现在创建了一个有说服力的案例,以解释为什么开发团队应采用微服务。但是,如果分析所有这些造成微服务架 构教训的原因,我们得出的结论可能与刚才介绍的以开发人员为中心的案例稍有不同。具体来讲,您需要认识到,应该让微服务在充满已有 应用程序的企业世界中发挥其作用,您还需要认识到,微服务架构更加注重 DevOps 的操作端。

生活在企业世界里

在 Netflix、Gilt.com 和 Amazon 等公司发布大量成功案例后,微服务架构开始引起关注。但是,所有这些公司和其他许多成功的微服务案例都有一个共同 点 — 他们都是 诞生于网络 的公司,这些公司在不断开发新的应用程序,或者没有庞大的遗留代码库要替换。当一家传统企业采用微服务时,它们在 选择第一批绿场应用程序来试水微服务后遇到一个问题:在必须重构一个大型整体式应用程序时,很难应用微服务架构的一些信条(特别是“分散化数据管理”和“分散化治理”原则)。

但幸运的是,该问题的解决方法多年前就已提出(以一种模式形式,该模式是 Martin Fowler 最初在 2004 年提出的,他在多年后才开始研究微服务)。他的概念被称为“Strangler Application 模式”,旨在解决您几乎从未实 际生活在 green field 的事实。最需要微服务的程序是网络上最大和最烦人的程序,但是同样地,利用网络的架构可为我们带来一 种管理所需重构的策略。

MicroservicesTV 第 14 集:微服务的演化(第 2 部分)

点击查看视频演示

Strangler Application 是一个简单概念,此概念源于一种藤蔓植物,该植物会勒死所缠绕的大树。此概念的思路是使用 Web 应用程序的结构(事实上它是通过在功能上与某个业务域的不同方面相对应的各个 URI 来构建的),将应用程序拆分为不同的功能域,并一次一个域地将它们替换为基于微服务的新实现。这两个方面形成了在 同一个 URI 空间中并列共存的不同应用程序。随着时间的推移,重构的新应用程序会毁灭或取代原始应用程序,最终,您能够关闭旧 的整体式应用程序。

但要让微服务方法在企业世界中发挥作用,这并不是我们发现的唯一有用模式。另一个重要方面是,在许多情况下,开发团 队无法对其数据进行分散化控制。这也是我们称为 Adapter Microservice 的模式诞生的原因,它是 Erich Gamma 和其他人合编的 设计模式 中的原始 Adapter 模式的一种扩展。

在 Adapter Microservice 中,您需要适应两个不同的 API。第一个 API 是一个面向业务的 API,它是使用 RESTful 或轻量型消息技术构建的,并使用与传统微服务相同的领域驱动技术进行设计。您需要适应的第二个 API 是一个现有的遗 留 API 或基于 WS-* 的传统 SOAP 服务。纯化论者可能反对采用此方法,并试图坚持以下观点:如果不采用分散化数据,那么您就没有使用微服务。但是, 企业数据的存在是有其原因的,而且往往有比已下定论的组织惰性更好的原因。可能有大量遗留应用程序仍需要访问当前形式的数据,这些 数据无法轻松地适应新 API,或者可能数据量(常常达到数百 TB 或数 PB)使它无法转变为归单个服务所有的新形式。

将 Ops 放回 DevOps 中

微服务的另一个重要方面,微服务涉及到称为 DevOps 的一组实践的操作端。这个方面源于最初为传统应用程序管理而开发 的许多模式。Fowler 在其最初的微服务论文中强调了这方面的重要性,他指出有必要在基于持续交付和持续集成原则构建的 DevOps 流程中适应基础架构的自动化。但是,对开始小规模采用微服务的团队而言,是否需要这么做始终不明朗。问题是,尽管 使用微服务使快速更改和部署单一服务变得更容易,但它也使管理和维护一组服务所需的总工作量比相应的整体式应用程序中所需的工作量 要大。

正因如此,许多常见的框架(比如用于微服务的 Netflix 框架和 Amalgam8)都在适应 Service Registry 模式:通过避免将特定的微服务端点硬编码到您的代码中,不仅可以更改下游微服务的实现,还可以在 DevOps 管道的不同阶段中选择不同的服务位置。如果没有 Service Registry,随着对代码的更改开始沿一个微服务调用链向上传播,您的应用程序很快将会陷入困境。

这种实现更高的隔离水平同时使微服务更容易调试的想法,是我们发现的一些 DevOps 模式的核心,特别是 Correlation ID 和 Log Aggregator。Correlation ID 模式在 Gregor Hohpe 编写的图书《 企业集成模式》中确定并描述为一种具体的形式,但我们现在看到的是在 OpenTracing 等项目中的一般化概念,它允许通过使用多种不同语言编写的多个微服务来传播跟踪轨迹。Log Aggregator 是许多开源和 商业产品(比如 Cloud Foundry 和开源的 ELK 堆栈)中实现的一种新模式;它为 Correlation ID 提供了补充,允许将来自许多不同微服务的日志聚合到一个可搜索的存储库中。结合使用这些模式,有助于更高效、更容 易理解地调试微服务,无论有多少个服务或每个调用堆栈有多深。

最后,将这两种模式相结合的另一个关键的 DevOps 方面是 Fowler 在他的文章中所呼吁的:为失败而设计的重要性。具体 来讲,由于 Netflix 的 Hystrix 框架所实现的 Circuit Breaker 模式,该框架已成为许多微服务实现的重要方面。Circuit Breaker 最初记录在 Michael Nygard 于 2007 年发表的图书《 Release It!》中。借助 Circuit Breaker,如果您知道下游已发生故障,您可以避免浪费时间来处理它们,而且您可以在上游服务调用中放入一个 Circuit Breaker 代码段来处理此问题,这个代码段可以检测下游服务何时发生故障并避免尝试调用它。这么做的好处是,每个调用都“快速失败”,您可以为用户提供更好的总体体验,避免在您知道下游调用注定失败时对线程和连接池等资源管理不善。

这种资源管理过去曾是 DevOps 的操作端所独有的工作,但微服务架构将两端更有效地结合在了一起,因为它们都致力于让结果应用程序更可靠、高性能 和容易恢复。

结束语

在本文和配套视频中,我们探讨了微服务的历史先例,分析了微服务架构的诞生过程,还讨论了您需要采用哪些模式才能在 企业世界中成功应用微服务,以及您在应用微服务架构时可能会遇到哪些挑战。

本文翻译自: Beyond buzzwords: A brief history of microservices patterns(2018-10-10)