[转]微服务概念解析


微服务概念解析(上)



探讨这一全新架构术语的确切定义

“微服务架构”概念的提出已经有非常长一段时间了,但在近期几年却開始频繁地出现。微服务架构是一种特定的软件应用程序设计方式——将大型软件拆分为多个独立可部署服务组合而成的套件方案。尽管这样的架构风格的确切定义还存在争议。但并最好还是碍其在众多企业的实际应用中被实践,并体现出了具备通用特征的业务功能、自己主动化部署、端点智能化以及对语言与数据的离散化控制能力。


Docker
作为一种开源的应用容器引擎,帮助开发者将他们的应用以及依赖打包到一个可移植的容器中,便于应用的部署和扩展。而随之产生的微容器概念和微服务正好相辅相成。通过
Docker 封装的应用可以轻松执行在以扩容能力见长的云计算平台上。

数人云作为专业的数据中心管理系统。提供了基于 Mesos 和
Docker 技术的企业级容器云生产环境。通过一键部署、横向扩展、持续集成等特性。助力微服务架构在企业应用环境的实践。

由于篇幅问题。本文将分上下两篇,下篇将于明天放送给大家。

“微服务”——眼下可谓早已人满为患的软件架构领域的新兴名词。

尽管我们对于这样的新生事物往往带着一种先入为主的蔑视与忽略态度,但经过几年的历练。我们发现这样的软件构建风格正变得越来越具有吸引力。过去几年中已经有诸多企业将其引入实际项目,而至今其结果仍然相当积极,这甚至促使非常多同业人士開始将微服务架构作为企业级应用程序的默认开发途径。

但遗憾的是,眼下仍然缺乏一套系统的概念定义,告诉我们微服务究竟是怎样实现这些成效的。

简而言之,微服务架构风格[1]是一类将单一应用程序作为由众多小型服务构成之套件加以开发的方式,其中各项服务都拥有自己的进程并利用轻量化机制(通常为HTTP源API)实现通信。

这些服务环绕业务功能建立而成,且凭借自己主动化部署机制实现独立部署。这些服务匹配一套最低限度的中央式管理机制,且各服务可通过不同编程语言编写而成并使用不同的数据存储技术。

1.jpg


要解释微服务风格,那么首先应当将其与总体风格进行比較:总体应用程序作为单一单元进行构建。企业级应用程序通常包含三个组成部分:一套client用户界面(由执行在用户设备上的浏览器中的HTML页面以及JavaScript代码构成)、一套后端数据库(将大量插入至数据库管理系统的大量表构成。通常採用关系数据库)以及一款server端应用程序。该server端应用程序将负责处理HTTP请求、执行域逻辑、对来自数据库的数据进行检索与更新。同一时候选定HTML视图并将其发送至浏览器端。此server端应用程序通常为单一的逻辑可执行文件[2]。不论什么针对该系统的变更都须要对该server端应用程序进行新版本号构建与部署。

这样的总体server机制在构建此类系统中可谓不可或缺。我们用于处理请求的所有逻辑都执行在单一进程其中,同意大家使用语言中的基本功能以将该应用程序拆分为类、函数以及命名空间。通过这样的方式,我们可以在开发者的笔记本设备上执行并測试应用程序,同一时候利用一整套部署流程以确保所有变更都经过妥善測试而后被部署在生产环境其中。

大家可以将大量实例执行在一套负载均衡方案之后,从而实现横向扩展能力。

这类总体应用程序当然可以切实起效,但人们却逐渐发现其中存在着诸多弊端——特别是在将大量应用程序部署在云环境其中的情况下。由于变更周期被大量集中于一处——即使仅仅指向应用程序中的一小部分,单一变更亦要求我们相应用程序总体进行重构与又一次部署。

随着时间推移,我们往往非常难保证理想的模块化结构。这意味着本应仅仅影响单一模块的变更往往会扩散至该模块之外。规模伸缩亦要求我们对总体应用程序进行规模调整,而非单纯为其中必要的部分进行资源扩容。

2.jpg


图一:总体型应用程序与微服务架构应用程序

正是这些弊端造就了如今的微服务架构风格:即以服务套件的形式构建应用程序。除了各服务可以单独进行部署与规模伸缩之外。每项服务还具备坚固的模块边界,甚至同意我们在不同的服务其中使用不同的编程语言进行代码编写。另外,各服务亦可由不同团队负责管理。

我们觉得微服务风格并不算什么新奇事物或者创新成果。其历史至少可以追溯至Unix设计时代。但我们同一时候亦坚信。微服务架构一直未能受到足够的重视。而其确实可以帮助大家更好地完毕软件开发工作。

微服务架构之特性

我们无法给微服务架构风格出具一条确切的定义,但我们却可以依据该架构表现出的各类共同特性对其加以描写叙述。正如各类依据共同特性做出的定义一样,并非所有微服务架构都符合这些特性,但可以肯定的是具备这些特性的微服务架构占领大部分比例。尽管我们各部分内容的作者仅仅是相关技术社区中的活跃成员,但制作这份文档是为了对採用微服务架构的工作流程及成果做出总结,并且其中仍有相当一部分表述并非严格定义——仅仅应作为常见情况考量。

通过服务实现组件化

长久以来,我们一直參与软件行业之内并意识到人们对利用组件整合方式构建系统的渴望——这样的思路与我们在物理世界中採取的构建机制非常相似。而在过去几十年其中,我们发现已经有大量公共库渗透到多数语言平台其中并成为其坚实的组成部分。



在谈到我们所使用的组件时。大家可能会发现不同群体对组件的定义也有所差别。

我们对组件做出的定义是,其属于软件中的一类单元。且具备可更替性与可升级性。

微服务架构会使用这些库,但其实现组件化的主要手段则是将软件拆分成多个服务。我们将“库”定义为与程序相对接且可通过内存内函数调用发挥作用的组件。而“服务”则为进程之外的组件,其可通过Web服务请求或者远程程序调用等方式实现通信。

(这里的服务概念与多数OO程序中的服务对象概念有所差别[3])。



将服务作为组件加以使用(而非库)的一大原因在于。服务具备独立可部署能力。

假设大家的应用程序[4]由单一进程中的多个库构成,那么指向不论什么单一组件的变更都会致使该应用程序必须进行又一次部署。

但假设该应用程序被拆分成多项服务,那么单一服务变更将仅仅会致使该服务进行又一次部署。尽管这并非绝对,比如某些变更会导致服务接口受到影响,但一套优秀的微服务架构旨在尽可能少地对服务协议中的服务边界及演进机制产生干扰。

将服务作为组件的还有一个理由在于实现更为明白的组件接口。大多数编程语言并不具备用于定义明白公布接口的良好机制。

一般来讲,其仅仅会提供说明文档及规则以防止用户打破组件封装,但这同一时候亦会导致不同组件之间的耦合程度过高。利用明白的远程调用机制,服务可以轻松避免此类难题。



但以这样的方式使用服务亦存在一定弊端。远程调用在资源需求方面往往远高于进程内调用,因此远程API须要採取粗粒度设计,但这亦会添加API的使用难度。

假设大家须要更改不同组件间的职能分配,那么这类需求在跨越进程边界时往往不易实现。



通过粗略观察,我们往往会发现这些服务会与各执行时进程相映射——但这仅仅仅仅是第一印象。

一项服务可能由多个进程构成,且各进程始终共同进行开发与部署——这方面实例包含仅仅由单一服务所使用的应用程序进程以及数据库。

环绕业务功能构建组织

当着眼于将单一大型应用程序拆分成多个组成部分时,管理人员通常更重视技术层。其中详细包含UI团队、server端逻辑团队以及数据库团队。

当这些团队据此进行拆分时,即使是最简单的变更也将给项目造成跨团队协作负担。并因此导致时间与预算的双重支出。睿智的团队会对此进行优化。同一时候採取两害相权取其轻的办法——即强制要求逻辑存在于一切与之相对接的应用程序其中。

换言之,也就是实现逻辑的普遍存在性。这正是所谓康威法则[5]的一种实际表现形式。

不论什么组织在设计一套系统(广义层面的系统)时。其设计成果都会直接体现该组织所使用的沟通结构。

 --梅尔文·康威,1967年

3.jpg


图二:康威定律的实际体现

微服务方案对于各部门而言是一种不同于以往,且以业务功能为核心的服务拆分及组织途径。此类服务採用软件方案在业务层面中的广泛实现堆栈,详细包含用户界面、持久性存储以及不论什么外部协作机制。因此,各团队将拥有跨职能特性。包含开发过程其中要求的所有技能组合:用户体验、数据库以及项目管理等等。

4.jpg


图三:由团队边界决定的服务边界

微服务架构有多“微”?
尽管“微服务”早已成为一种极具人气的架构类型。但这一名称却并不能准确反映服务的实际规模——换言之,“微”服务并不一定微。在与众多微服务从业者的交流其中,我们发现服务的详细规模可谓多种多样。其中规模最大的成果源自Amazon公司旗下的“两块披萨”团队(即整个团队仅仅需两块披萨就可以填饱肚子),这意味着其总人数在十位左右。而规模较小的团队则由六人组成。负责支持六项服务。

那么这就带来了新的问题:这样的十二人对单项服务的机制同一人对单项服务之间存在着怎样的差别?二者或许不可一概而论。就眼下而言。我们姑且觉得两方属于同类团队结构。但随着对微服务认识的持续深入,或许我们未来将抱持新的观点。

採取此类组织方式的企业实例可參见www.comparethemarket.com。其各职能团队共同负责构建并运营每款产品。而每款产品则被拆分为一系列独立的服务——且各服务间通过一套消息收发总线实现通信。

 

大型总体应用程序亦可以始终环绕业务功能实际模块化,只是这样的状况并不常见。诚然。我们都听说过由大型团队构建的单一总体应用程序依据自身业务线进行设计与划分。然而在这类情况下。最大的问题在于总体应用程序在组织其中须要考虑太多背景信息。假设其总体范畴其中包含太多模块边界,那么团队中的单一成员将非常难通过短期记忆对其进行管理。

除此之外。我们发现这样的模块化业务线的维护工作还要求相关人员具备极高的专业技能水平。相比之下,服务组件可以令拆分方式更为明白,从而大大简化团队边界的设定与认知。



产品而非项目

大部分应用程序开发工作都会遵循项目模式:其目标在于交付软件方案中的特定部分。并拥有直观的完毕指标。

在软件开发工作完毕后,其会被传递至运维部门,这时负责构建该软件的团队也将即刻解散。



微服务的支持者们则觉得这样的模式并不可取——他们的主张是相关团队应该伴随产品走过整个生命周期。这方面最典型的样例应该是Amazon公司提出的“谁构建,谁执行”原则。其中开发团队须要对生产环境下的软件成果承担所有责任。这就要求开发者在日常工作中全程关注其软件的生产执行情况,同一时候掌握来自用户的反馈意见,意味着他们须要在一定程度上为用户提供技术支持服务。

产品的定位应始终与业务功能相协调。

相较于以往将软件视为一整套已经完毕的功能集的心态,微服务架构要求我们全程与之保持关联,并思考该软件可以怎样协助用户加强业务功能。

当然,我们全然可以将相同的思路引入总体应用程序其中。只是大量小型服务集合可以显著简化服务开发者与及用户之间的个人联系。

智能化端点与傻瓜式流程

在跨越不同进程构建通信结构时,我们发现非常多产品及方案会直接把智能化机制塞进通信机制本体其中。这方面的典型实例就是企业服务总线(简称ESB)。ESB产品其中通常包含复杂度极高的消息跌幅、编排、转换以及业务规则应用等机制。

微服务社区则倾向于使用还有一种实现方式:智能化端点与傻瓜式流程。採用微服务架构的应用程序旨在尽可能实现解耦化与关联性——它们各自拥有自己的域逻辑,并且在经典Unix场景下的运作方式更像是过滤器机制——接收请求、应用合适的逻辑并生成响应。这一切都通过简单的REST类协议实现编排,而非经由WS-Choreography或者BPEL等复杂协议以及中央编排工具实现。



眼下最常常使用的两类协议为配合源API的HTTP请求-响应与轻量化消息收发协议[6]。对于前者,最简练而准确的说明是:

立足于Web。而非居于Web背后。

 -- Ian Robinson

微服务团队採用的正是万维网(在非常大程度上亦包含Unix在内)所遵循的原则与协议。

一般来讲。其使用的资源可以为开发者或者运维人员轻松实现缓存处理。

第二类作法则是立足于轻量化消息总线实现消息收发。这类基础设施选项通常具备傻瓜式特性(这样的傻瓜特性体如今实现操作上。即仅仅需匹配消息路由机制,再无其他)——以RabbitMQ或者ZeroMQ为代表的简单实现方案仅仅须要提供一套可靠的异步结构。而服务的所有智能化元素仍然存在于端点其中并负责消息的生成与消费。



在总体应用程序其中。各组件在进程内执行并通过方法调用或者函数调用的方式实现彼此通信。将总体应用程序转化为微服务形式的最大难题在于改变这样的通信模式。由内存内方法调用指向PC通信机制的简单转换往往无法良好起效。相反。大家须要利用粗粒度方式代替原本的细粒度通信机制。



脚注
1: “微服务”一词最早被威尼斯附近的一个软件架构师小组于2011年5月首次提及。当时他们用这个词汇来描写叙述自己近期研究项目其中所涉及的通用性架构机制。

2012年5月,该小组作出终于决议。觉得“微服务”是最适合的架构名称。2012年3月,James在《微服务-Java以及Unix方式》其中就此发表了一篇案例研究报告,而Fred George也差点儿在同一时间进行了相同的工作。Netflix公司的Adrian Cockcroft将微服务架构称为“细化SOA”,并觉得这是一套在Web规模下具备开创意义的架构类型。

Joe Walnes、Dan North、Evan Botcher以及Graham Tackley也分别在这篇文章中对此作出了评论。

2: 文章中所使用的“总体”一词长久以来一直被Unix业界所使用。其首次出如今《Unix编程艺术》一书中,用于描写叙述那些过于庞大的系统方案。

3: 非常多面向对象设计人员,也包含我们自己,都会在域驱动设计其中使用“服务对象”这一表述。专指那些并不具备实质性联系但却拥有重要作用的对象。

这与我们在本文中所使用的“服务”一词在表意上全然不同。遗憾的是。服务这个词汇同一时候具备两种含义,而我们对这样的多义词也没有更好的处理办法。

4: 我们将一款应用程序视为一套社会性体系,其中融合了代码库、函数组以及供应主体。

5: 大家可以查看梅尔文 康韦站点上的原文论述。

6: 对于规模极为庞大的应用体系,企业一般会採用二进制协议——比如protobufs。使用二进制协议的系统仍然符合智能化端点与傻瓜式通道的特性——并为了规模化而在透明度方面作出妥协。只是大多数Web方案与绝大多数企业不须要在这方面考虑太多——一般来讲。透明度越高、效果就越好。



来源:http://dockone.io/article/1006


微服务概念解析(下)

在上篇中我们讲到了微服务的几个架构特性。包含通过服务实现组件化、以业务功能为核心进行组织、产品而非项目、智能化端点与傻瓜式流程,在今天的微服务概念解析下篇中。我们将继续讲述微服务的特性,详细分析它的离散化治理、离散化数据管理、基础设施自己主动化、故障应对设计以及演进设计。并理性思考微服务作为一项新兴的技术成果,是否可以代表未来。

上篇传送门

离散化治理

聚合型治理的一大影响在于使得单一技术平台上出现标准化趋势。

经验表明这类方案具备收缩特性——意味着各个实际问题并不可以轻松与解决方式相应起来。

我们更倾向于使用正确的工具执行正确的任务。并且尽管部分总体应用程序可以发挥不同编程语言的独特优势,但这样的情况并不常见。



微服务与SOA
当我们探讨微服务时,常常出现的问题就是其究竟是不是我们十年前就听说过的面向服务架构(简称SOA)的还有一种表现形式?二者之间确实存在一定联系,由于微服务风格拥有与SOA相似的逻辑主张。

然而问题在于,SOA的实际含义太过广泛,并且当我们提到所谓“SOA”时。实际所指的对象往往跟这里提到的微服务概念差之千里——详细来讲,其通常代表那些专注于利用ESB实现的集成化总体应用程序。

值得强调的是,我们也见证了大量表现糟糕的面向服务实现手段——从将复杂性隐藏在ESB其中[7]的作法。到投入多年以及数百万资金却毫无成效的尝试,再到以聚合型治理模式抑制变更,我们差点儿看不到面向服务架构可以带来什么显著的积极影响。

诚然。微服务社区其中使用的不少技术成果都源自开发者在大型企业其中积累到的集成化服务成果。Tolerant Reader模式正是其中的典型代表。

对Web的运用确实带来可观回报,而使用简单协议正是经验积累的直接产物——这显然是为了解决标准汇聚所导致的高复杂性难题(不管何时,假设大家须要利用一种实体来管理其他实体,那么就意味着各位已经面临着大麻烦)。

SOA的这些弊端导致一部分微服务布道者非常讨厌人们把SOA的标签加在微服务头上——尽管也有一些人觉得微服务正是SOA的一种实现方式[8],或者说我们可以将微服务称为“面向服务的正确实现”。不管怎样,其实SOA含义的宽泛性意味着其更适合作为一种用于定义架构风格的术语,而非详细解决方式。


通过将总体应用程序的各组件拆分成服务,我们可以对各服务进行分别构建。各位可能希望利用Node.js建立一套简单报告页面?照此办理就可以。

打算利用C++构建特定的近实时组件?没问题。打算利用不同类型的数据库以匹配单一组件的读取行为?眼下的技术方案已经可以实现这样的独立重构需求。

当然,我们可以实现以上目标,并不代表我们必须这么做——但对系统进行拆分意味着大家可以拥有很多其他备用选项。

採用微服务架构的团队倾向于以不同的方式实现所谓标准。相较于以往编写一整套定义标准集的作法。他们更乐于开发有用工具并交付给其他开发者,从而利用其解决自身面临的相似问题。这些工具通常可以在更为广泛的层面得到实现与共享,但同一时候又不至于转化为排他性内部开源模式。

如今git与github都已经成为客观层面的版本号控制系统选项,而开源实践也越来越多地成为内部环境中的常见组成部分。



Netflix公司就是个非常好的样例,他们遵循的正是这样一种理念。将具备有用性且经过严格考验的代码作为库。并鼓舞其他开发者利用其以相似的方式解决的相似的问题,这就为各团队成员在必要时选择其他工具保留了空间。共享式库专注于数据存储、进程间通信以及我们在后文中将要探讨的基础设施自己主动化等问题的解决。

对于微服务社区而言,资源成本显然是种不受欢迎的因素。这并非说该社区不承认服务协议的价值。恰恰相反,这是由于他们希望构建起大量服务协议。他们希望可以採用多种全然不同的方式对这些协议进行管理。

像Tolerant Reader以及Consumer-Driven Contacts这样的模式在微服务架构中非常常见。

这些服务协议也各自以独立方式不断演进。

将消费者驱动型协议作为构建工作组成部分的作法可以显著增强參与者信心,同一时候高速获取服务功能是否能确切实现的反馈意见。其实,澳大利亚的某个团队就在积极利用消费者驱动型协议进行新服务构建。他们使用的简单工具确保其可以针对单一服务实现协议定义。其甚至在面向新服务的代码被编写出来之前就已经成为自己主动化构建流程中的一部分。

这意味着服务仅仅有在切实满足该协议要求的前提下才可以实现构建——这就有效攻克了构建新软件时常常出现的“YAGNI”[9]难题。这些技术与工具成果环绕协议而生。并通过减少不同服务间的耦合性限制了其对中央协议管理机制的依赖。

多种语言。多种选项
JVM作为平台的高速发展已经成为多种语言混成于单一通用平台内的最新明证。这样的作法已经成为一类常见实践。旨在充分发挥高级语言在过去数十年中发展所实现的种种高级抽象优势。

其甚至以涓滴效应影响到裸机以及通过低级语言编写的性能敏感型代码。然而,众多总体应用程序并不须要这样的级别的性能优化效果,亦非常见的DSL与高级别抽象开发成果。相反。总体应用程序往往使用单一语言,这也严重限制了其可以使用的技术手段。[10]
或许离散化治理的人气正是源自Amazon方面提出的“谁构建。谁执行”原则。各团队须要为其构建的软件的各个方面承担责任。包含为软件提供24/7全天候运维支持。

这样的程度的责任下放当然还没有成为常态。只是我们已经看到越来越多的企业開始将责任交付至开发团队。Netflix公司亦是还有一家採取这样的理念[11]的企业。为了不至于在凌晨三点被紧急来电叫醒,开发者们当然会全力以赴提升所编写代码的质量水平。这些思路与传统的集中化治理模式明显相去甚远。

离散化数据管理

数据管理离散化拥有多种不同的表现形式。

从最为抽象的级别来看,这意味着全局概念模型将在不同系统之间有所差别。这样的问题常见于解决方式在大型企业其中的部署,毕竟销售团队对于客户概念的理解方式必须不同于技术支持团队的理解方式。

被销售人员视为客户的对象或许根本不会出现的技术支持团队的视野其中。不同属性甚至是相同属性的不同理解方式都可能在语义层面产生细微的差异。

实践性规范与执行标准
这样的态度实际有点二分法的意味:微服务团队倾向于回避由企业架构部门制定的硬性执行标准。但却乐于使用甚至积极推广HTTP、ATOM以及其他微格式开放标准。



二者之间的本质差别在于标准的开发方式以及执行方式。由IETF等组织管理的标准仅仅会在得到广泛採用之后才干真正成为业界规范,并且其往往脱胎自成功的开源项目。

这些标准拥有与商业世界全然不同的立场与定位——其实,商业标准的制定工作往往由那些差点儿不具备编程经验的团队所负责,或者受到详细厂商的过度影响。
这一问题通常出如今不同应用程序之间甚至是应用程序之内,特别是在将应用程序拆分为多个独立组件的情况下。

解决这个问题的一类可行思路在于基于背景边界化的区域驱动型设计(简称DDD)方案。DDD机制将一个复杂的区域拆分成多个具备边界的背景单元,并对各单元之间的关系加以映射。

这样的方式同一时候适用于总体与微服务架构,但服务与背景边界间的自然关联性有助于声明我们曾在业务功能章节中提到过的区分效果。

除了对概念模式进行离散化处理。微服务同一时候也可以拆分数据存储决策。

尽管总体性应用程序倾向于使用单一逻辑数据库保存持久性数据。但企业通常更乐于利用单一数据库涵盖一系列应用程序——并且大多数此类决策立足于详细供应商提供的授权商业模式。微服务机制则选择由每项服务管理其自身数据库的方式,而非不同实例基于同一数据库技术或者全然使用多种不同数据库系统——这样的方式亦被称为混合持久化。大家可以利用混合持久化方案打理总体应用程序,但其在微服务架构中的亮相频率明显更高一些。

1111.jpg


对微服务架构内数据责任关系的离散化处理也影响到了更新管理工作。常见的更新处理方案是在更新多种资源时,利用事务处理机制来保证其一致性。

这样的方式通常被用于总体性应用程序汉中。

这样的事务处理使用方式确实有助于保障一致性。但却会带来显著的暂时性耦合效果,而这在跨越多项服务时会带来新的难题。

分布式事务处理非常难以实现。因此微服务架构更强调服务之间的事务处理协调性,同一时候明白强调仅仅需保障终于一致性并通过补偿运算解决其中的冲突问题。

利用这样的方式管理一致性问题已经成为众多开发团队的新困境,但其却可以切实匹配业务实践。一般来讲,企业须要保留一定程度的不一致性以实现某种程度的逆转能力,从而利用高速响应处理错误状况。这样的权衡有其必要性,仅仅要确定失误成本要低于高一致性条件下可能造成的业务损失成本就可以。



基础设施自己主动化

基础设施自己主动化技术在过去几年中得到了长足发展——而云与AWS的演进则显著减少了构建、部署及运维微服务架构所带来的复杂性水平。

大部分利用微服务机制构建的产品或者系统都是由具备丰富的持续交付及其前者——持续集成——经验的团队所完毕。通过这样的方式构建软件的团队可以充分发挥基础设施自己主动化技术成果的潜在能力。

我们可以将整个流程整理成下面图表:

222.jpg


图五:基本构建流程

让正确决定更易于执行

作为一项连带效应,我们发现实现持续交付与部署可以帮助开发者及运维人员创造出高有用性工具。这类工具可以创建artifact、管理代码库、建立简单服务或者实现标准监控与记录等常见功能。这方面最典型的实例当数Netflix公司公布的一系列开源工具。险些之外Dropwizard等方案亦得到广泛使用。


总体应用程序的构建、測试与推送流程可以在此类环境下顺利完毕。事实证明,一旦大家利用自己主动化流程进行总体应用开发,那么部署很多其他应用程序也将成为顺理成章的轻松任务。

请记住,持续交付的目标之中的一个就是令部署变得无脑化,这意味着不管是一款应用还是三款,其实际部署流程都不会有什么差别[12]。

我们还发现,不少团队在利用这样的广泛的基础设施自己主动化能力管理生产环境下的微服务架构。

相较于前面提到的总体与微服务应用在部署层面并没有太大差别,实际运维环境下的详细条件则存在着巨大差异。

333.jpg


图六:模块部署的详细方式往往差别巨大

故障应对设计

将服务作为组件加以使用的结果之中的一个在于,应用程序须要经过针对性设计以确保其具备服务故障容错能力。

不论什么服务调用都有可能由于供应程序不可用而发生故障。在这样的情况下。client必须要尽可能做出适当的回应。相较于总体应用程序来说,服务即组件机制会添加额外的处理复杂性,这也是微服务架构的一大弊端。

在这样的情况下,微服务团队须要不断审视服务故障对用户体验造成的影响。

Netflix公司的“猴子军团”项目就专门负责在正常运营期间对服务进行破坏,甚至利用数据中心故障来測试应用程序的弹性及监控能力。

断路器与可交代生产环境之代码

断路器模式出如今Amazon的Release It!其中,其中提到的其他模式还包含隔板模式与超时模式等。

在加以结合之后,这些模式将在构建通信应用方面发挥巨大作用。Netflix公司公布的一系列博文就非常好地解释了他们对这些模式选项的详细使用方式。
这类自己主动化測试机制往往会令正等待周末下班的运维团队们感到不寒而慄。这并非说总体架构风格就无法使用高复杂性监控机制——仅仅只是这样的情况确实不太常见。



由于服务随时可能发生故障。因此最重要的就是保持对故障的高速检測能力。并在可能的情况下对其进行自己主动恢复。微服务应用程序高度强调相应用程序的实时监控能力,同一时候不断对架构元素(数据库每秒钟接收到的请求数量)以及业务相关指标(比如每分钟收到的订单数量)进行记录。语义监控可以通过早期预警系统抢先一步做出警示。并引导开发团队对问题加以跟进与调查。



这一点对于微服务架构尤为重要,由于微服务更倾向于採用由编排及事件协作实现的应急处理方式。

尽管非常多专家都相应急处理方案偶尔带来的收益表示认同,但其实际上往往也是让事情变糟的罪魁祸首。为了及时阻断糟糕的应急处理并确保其拥有可恢复性,监控系统就变得极为重要。

同步调用殊不可取

不管何时时,一旦在不同服务之间进行多次同步调用。那么可能引发宕机的概率也会以乘法形式增长。简单来讲,系统的总体宕机时间为各单个部件宕机时间的乘积。

这时我们就面临着详细选择,究竟是以异步方式进行调用,还是以计划方式管理由同步调用带来的宕机时间。英国《卫报》站点在其全新平台上执行了一项简单的规则——每一个用户请求相应一次同步调用,而Netflix公司所使用的API则经历又一次设计,确保其结构内採用异步调用机制。


总体应用程序的构建方式可与微服务架构相同透明——其实也本应如此。二者的差别在于,在面对总体应用时我们须要在确切了解其执行在不同进程中的服务何时发生断开。考虑到同一进程其中可能包含多套库,这样的透明度水平实际上非常难实现。

微服务团队须要利用复杂的监控与记录机制处理各项服务,比如通过仪表板显示上线/下线状态以及一系列运营与业务相关指标。另外,我们还须要面对断路器状态、当前数据吞吐量以及延迟等其他常见的衡量数据。

演进设计 

微服务从业者通常都具备演进设计工作背景。并将服务拆分视为一种深入型工具,旨在帮助应用程序开发者在无需拖慢变更速度的前提下实现面向应用程序的变更控制。变更控制并不一定意味着变更数量削减——配合正确的态度与工具,大家全然可以帮助软件提供高速、频繁且经过良好控制的变更。



当尝试将一套软件系统拆分为多个组件时,我们往往面临着与详细拆分工作相关的决策任务——即我们应该遵循怎样的方针相应用程序进行拆分?而组件中的关键属性则在于其独立替换与可升级特性[13]——这意味着我们要找到确切的平衡点,保证自身可以在不影响其他协作对象的前提下对单一组件进行重写。

其实,非常多微服务团队会更进一步,直接清退某些服务而非对其进行长期升级。

英国《卫报》站点就是个非常好的样例,其应用程序在设计与构建方面作为总体应用存在,但却在逐步面向微服务架构演进。

该站点的核心部分仍然属于总体性项目,但他们更倾向于通过构建微服务利用总体API实现新功能加入。这套方案对于暂时性功能的实现非常重要,比如加设专题页面以显示体育赛事报道。

站点中的这类组成部分可以通过高速开发语言在短时间内编写完毕。并在相应事件结束后马上下线。我们还发现其他一些金融机构亦採取相似的方式公布突发性市场波动,并在数周或者数月之后将其下线。

这也强调了可替换性在模块化设计中的重要地位,其主旨正在于将模块机制贯彻整个变更模式[14]。大家希望仅仅变更其中必须变更的部分,而其他模块则继续保持原样。

系统其中那些差点儿非常少变动的部分应该立足于不同于高变更频率组件的服务。假设大家发现自己常常须要同一时候对两项服务做出变更,那么明显应该将二者加以合并。

将组件纳入服务也让我们可以以更高的细粒度水平进行规划制定。在总体应用程序其中,不论什么一项变更都须要相应用总体进行重构与又一次部署。但在微服务架构方面,我们仅仅须要又一次部署包含相应变更的服务。这可以显著简化并加快公布流程。

只是其弊端在于,我们必须考虑针对单一服务的变更是否会影响到其他服务。

传统的总体性方案可以通过版本号控制解决这类难题,但微服务领域则倾向于将版本号控制作为最后一种应急办法。我们可以通过设计保证服务拥有强大的容错能力。从而应对其供应程序中出现的各类代码改动。

微服务是否代表着未来?
我们撰写这篇文章的主要目的在于解释微服务架构的基本思路与原则。

而在撰写过程其中。我们明白意识到微服务架构风格确实是一项值得重视的关键成果——企业级应用程序开发者应当对其加以了解。

我们近期利用该架构构建了多套系统,并且了解到亦有其他多家企业将其纳入业务体系。

我们了解到的微服务架构先驱企业包含Amazon、Netflix、英国《卫报》、英国政府数字化服务局、realestate.com.au、Forward以及comparethemarket.com等等。2013年召开的相关会议则公布了很多其他參与其中的重要厂商。除此之外,另有相当一部分企业一直在使用相似的实现思路——但却并没有使用‘微服务’这样的称谓。(其通常将其冠以SOA标签——只是正如我们之前提到,SOA是一类存在大量矛盾取向的概念组合。[15])

尽管拥有这些积极的经验,但我们仍然无法全然肯定微服务架构就代表着软件未来的发展方向。尽管我们的实际经历证明微服务架构截至眼下仍拥有优于总体性应用程序的积极优势,但必须承认仅仅有充分的时间积累才干帮助我们做出真正完整则准确的推断结论。



4444.jpg


我们的同事Sam Newman曾于2014年倾尽心力撰写出这本关于我们怎样构建微服务架构类应用的论著。

假设大家希望进一步探讨这个议题。请千万不要错过。

通常来说,架构决策的实际影响可能须要几年之后才干逐步显现出来。我们已经看到不少优秀的团队带着巨大的热情与愿景而投入工作,但终于却构建起一套陈旧不堪的总体性架构。非常多人觉得相同的情况不太可能发生在微服务架构身上。由于其服务边界非常明白因此不太可能发生相互影响。

但由于时间尚短且系统程度不足。我们眼下还无法真正评估微服务架构的成熟度水平。

人们对微服务成熟度抱持的怀疑态度也有其理由。在不论什么组件化尝试工作其中。终于结果的成功与否都取决于该软件与拆分后组件的契合效果。我们眼下仍然非常难说明组件边界的选择原则。

演进设计导致边界划分变得非常困难,因此最重要的是保证其重构的简易性。但一旦将组件作为服务处理以实现远程通信。那么其重构难度将远远高于进程内库。在不同服务边界之间进行代码移动难度极大,而不论什么接口变更都须要在不同相关服务间实现。同一时候加入层的向下兼容能力,这无疑会令測试工作更加复杂。

还有一大问题在于,假设相关组件间的关系不够简洁,那么我们就相当于把组件内部的复杂性转移到了不同组件间的连接其中。这样做不仅会导致复杂性扩散。同一时候亦会导致其明白性缺失且难以控制。

立足于小型、简单组件审视问题总是更为直观。而在不同服务间进行纵览则往往会错失关注点。



最后,团队的技能水平也将起到决定性作用。

新型技术成果往往要求高水平技术团队加以实施。只是高水平团队可以顺畅利用的技术方案并不一定可以在低水平人员手中发挥作用。

我们已经见证了众多低水平团队构建起的如一团乱麻般的总体架构。但仍须要时间来了解微服务架构是否会在相同的情况下引发相同的状况。诚然。糟糕的团队创建出的始终仅仅能是糟糕的系统——但我们不知道微服务架构究竟是会缓解这样的状况。还是令状况更中慘不忍睹。



眼下有一种较为理性的论调,觉得我们不应将微服务架构作为起步方案。相反。大家可以从总体性开发风格出发,保证其结合模块化机制,并在总体性特征引发实际问题后逐步将其拆分为微服务形式。(只是这样的建议并非全然理想,由于良好的进程内接口往往并不能成为良好的服务接口。)

因此我们对此抱持慎重的乐观态度。

到眼下为止。我们已经了解到关于微服务架构的方方面面,并且其应该可以成为一种极具价值的开发手段。尽管还不能做出终于推断。但软件开发工作的固有挑战之中的一个,正是我们仅仅能依据眼下掌握的远称不上完美的信息做出决策。

脚注
7: 尽管无关紧要。但Jim Webber以前将ESB解释成“Egregious Spaghetti Box”,也就是“恐怖意面盒”。

8: Netflix公司近期将其架构类型称为“细化SOA”。



9: “YAGNI”的全称是“You Aren’t Going To Need It(你根本不须要它)”。这是一项经典的用户体验原则,即不要自作聪明地加入非必要性功能。

10: 我们所宣称的总体型应用仅仅支持单一语言确实有些不尽不实——在当下的Web系统构建过程中,大家可能须要掌握JavaScript、XHTML以及CSS,而在server端的语言选项则包含SQL以及某种ORM(即对象关系映射)衍生语言。没错,单一语言肯定玩不转,但我相信大家明白我想要强调的意思。

11: Adrian Cockcroft在2013年11月的Flowcon大会上作出了精彩演讲。并特别提到了“开发者自助服务”与“开发者应亲自执行所编写代码”的观点。

12: 我们在这里的说法并不准确。

非常明显。在更为复杂的拓扑结构中部署大量服务肯定要比在单一总体型架构内进行部署困难得多。幸运的是,各类模式可以显著减少这样的复杂性——当然。在工具方面的投入仍然不可或缺。

13: 其实,Dan North将这样的类型称为“可替代式组件架构”而非微服务架构。由于其强调内容属于微服务架构的一类子集。所以我们更倾向于使用后一种表达方式。

14: Kent Beck将此作为其《实施模式》一文中的设计原则之中的一个。

15: SOA差点儿是此类架构的历史起源。我记得当SOA一词在本世纪初刚刚出现时。非常多人表示“我们几年前就已经将其引入日常工作了”。

也有意见觉得这样的架构类型似乎最早出现于早期企业计算其中,COBOL程序通过数据文件实现通信的处理机制。而在还有一方面。也有人觉得微服务架构与Erlang编程模型其实是同一回事。只是后者仅仅被应用在企业应用程序其中。


来源:http://dockone.io/article/1007




posted @ 2017-08-18 08:05  yangykaifa  阅读(559)  评论(0编辑  收藏  举报