微服务(Microservices)【翻译】

服务(Microservices)【翻译】
1微服务
“微服务架构(Microservice Architecture)”⼀词在过去⼏年⾥⼴泛的传播,它⽤于描述⼀种设计应⽤程序的特别⽅式,作为⼀套独⽴可部署的服务。⽬前,这种架构⽅式还没有准确的定义,但是在围绕业务能⼒的组织、⾃动部署(automated deployment)、端智能(intelligence in the endpoints)、语⾔和数据的分散控制发⾯,却有着某些共同的特征。
“微服务(Microservices)”——只不过是在满⼤街充斥的软件架构中的⼀个新名词⽽已。尽管我们⾮常鄙视这样的东西,但是这玩意所描述的软件风格,越来越引起我们的注意。在过去⼏年⾥,我们发现越来越多的项⽬开始使⽤这种风格,以⾄于我们⾝边的同事在构建企业级应⽤时,把它理所当然的认为这是⼀种默认的开发形式。然⽽,很不幸,微服务风格是什么,应该怎么开发,关于这样的理论描述却很难到。
简⽽⾔之,微服务架构风格,就像是把⼀个单独的应⽤程序开发为⼀套⼩服务,每个⼩服务运⾏在⾃⼰的进程中,并使⽤轻量级机制通信,通常是 HTTP API。这些服务围绕业务能⼒来构建,并通过完全⾃动化部署机制来独⽴部署。这些服务使⽤不同的编程语⾔编写,以及不同的数据存储技术,并保持最低限度的集中式管理。
在开始介绍微服务风格(microservice style)前,⽐较⼀下整体风格(monolithic style)是很有帮助的:⼀个单体应⽤程序(monolithic application)构建成⼀个单独的单元。企业级应⽤通常被构建成三个主要部分:客户端⽤户界⾯(由运⾏在客户机器上的浏览器的 HTML 页⾯、Javascript 组成)、数据库(由许多的表构成⼀个通⽤的、相互关联的数据管理系统)、服务端应⽤。服务端应⽤处理 HTTP 请求,执⾏领域逻辑(domain logic),检索并更新数据库中的数据,使⽤适当的 HTML 视图发送给浏览器。服务端应⽤是完整的 ,是⼀个单独的的逻辑执⾏。任何对系统的改变都涉及到重新构建和部署⼀个新版本的服务端应⽤程序。
这样的整体服务(monolithic server)是⼀种构建系统很⾃然的⽅式。虽然你可以利⽤开发语基础特性把应⽤程序划分成类、函数、命名空间,但所有你处理请求的逻辑都运⾏在⼀个单独的进程中。在某些场景中,开发者可以在的笔计本上开发、测试应⽤,然后利⽤部署通道来保证经过正常测试的变更,发布到产品中。你也可以使⽤横向扩展,通过负载均衡将多个应⽤部署到多台服务器上。
单体应⽤程序(Monolithic applications)相当成功,但是越来越多的⼈感觉到有点不妥,特别是在云中部署时。变更发布周期被绑定了——只是变更了应⽤程序的⼀⼩部分,却要求整个应⽤重新构建和部署。随着时间的推移,很难再保持⼀个好的模块化结构,使得⼀个模块的变更很难不影响到其它模块。扩展就需要整个应⽤程序的扩展,⽽不能进⾏部分扩展。
图 1 整理架构与微服务架构
这导致了微服务架构风格(microservice architectural style)的出现:把应⽤程序构建为⼀套服务。事实是,服务可以独⽴部署和扩展,每个服务提供了⼀个坚实的模块边界,甚⾄不同的服务可以⽤不同的编程语⾔编写。它们可以被不同的团队管理。
我们必须说,微服务风格不是什么新东西,它⾄少可以追溯到 Unix 的设计原则。但是并没有太多⼈考虑微服务架构,如果他们⽤了,那么很多软件都会更好。
微服务风格的特性
微服务风格并没有⼀个正式的定义,但我们可以尝试描述⼀下微服务风格所具有的共同特点。并不是所有的微服务风格都要具有所有的特性,但我们期望常见的微服务都应该有这些特性。我们的意图是尝试描述我们⼯作中或者在其它我们了解的组件中所理解的微服务。特别是,我们不依赖于那些已经明确过的定义。
组件化(Componentization )与服务(Services)
⾃从我们开始软件⾏业以来,⼀直希望由组件构建系统,就像我们在物理世界所看到的⼀样。在过去的⼏⼗年⾥,我们已经看到了公共库的⼤量简编取得了相当的进步,这些库是⼤部分语⾔平台的⼀部分。
当我们谈论组件时,可能会陷⼊⼀个困境——什么是组件。我们的定义是,组件(component)是⼀个可独⽴替换和升级的软件单元。
微服务架构(Microservice architectures)会使⽤库(libraries),但组件化软件的主要⽅式是把它拆
分成服务。我们把库(libraries)定义为组件,这些组件被链接到程序,并通过内存中函数调⽤(in-memory function calls)来调⽤,⽽服务(services )是进程外组件(out-of-process components),他们利⽤某个机制通信,⽐如 WebService 请求,或远程过程调⽤(remote procedure call)。组件和服务在很多⾯向对象编程中是不同的概念。
把服务当成组件(⽽不是组件库)的⼀个主要原因是,服务可以独⽴部署。如果你的应⽤程序是由⼀个单独进程中的很多库组成,那么对任何⼀个组件的改变都将导致必须重新部署整个应⽤程序。但是如果你把应⽤程序拆分成很多服务,那你只需要重新部署那个改变的服务。当然,这也不是绝对的,有些服务会改变导致协调的服务接⼝,但是⼀个好的微服务架构的⽬标就是通过在服务契约(service contracts)中解耦服务的边界和进化机制来避免这些。
另⼀个考虑是,把服务当组件将拥有更清晰的组件接⼝。⼤多数开发语⾔都没有⼀个良好的机制来定义⼀个发布的接⼝(Published Interface)。发布的接⼝是指⼀个类向外公开的成员,⽐如 Java 中的声明为 Public 的成员,C# 中声明为⾮ Internal 的成员。通常只有在⽂档和规范中会说明,这是为了避免客户端破坏组件的封装性,阻⽌组件间紧耦合。服务通过使⽤公开远程调⽤机制可以很容易避免这些。
像这样使⽤服务也有不⾜之处。远程调⽤⽐进制内调⽤更消耗资源,因此远程 API 需要粗粒度(coar
ser-grained),但这会⽐较难使⽤。如果你需要调整组件间的职责分配,当跨越进程边界时,这样做将会很难。
⼀个可能是,我们看到,服务可以映射到运⾏时进程(runtime processes)上,但也只是⼀个可能。服务可以由多个进程组成,它们会同时开发和部署,例如⼀个应⽤程序进程和⼀个只能由这个服务使⽤的数据库。
围绕业务功能的组织
当寻把⼀个⼤的应⽤程序拆分成⼩的部分时,通常管理都会集中在技术层⾯,UI团队、服务端业务逻辑团队和数据库团队。当使⽤这种标准对团队进⾏划分时,甚⾄⼩⼩的更变都将导致跨团队项⽬协作,从⽽消耗时间和预算审批。⼀个⾼效的团队会针对这种情况进⾏改善,两权相害取其轻。业务逻辑⽆处不在。实践中,这就是 Conway's Law 的⼀个例⼦。
设计⼀个系统的任何组织(⼴义上)都会产⽣这样⼀种设计,其结构是组织交流结构的复制。
——Melvyn Conway, 1967
Melvyn Conway 的意识是,像下图所展⽰的,设计⼀个系统时,将⼈员划分为 UI 团队,中间件团队,DBA 团队,那么相应地,软件系统也就会⾃然地被划分为 UI 界⾯,中间件系统,数据库。
图 2  实践中的 Conway's Law
微服务(microservice )的划分⽅法不同,它倾向围绕业务功能的组织来分割服务。这些服务实现商业领域的软件,包括⽤户界⾯,持久化存储,任何的外部协作。因此,团队是跨职能的(cross-functional),包含开发过程所要求的所有技能:⽤户体验(user-experience)、数据库(database)和项⽬管理(project management)。
图 3 通过团队边界强调服务边界
wwwparethemarket就是采⽤这种组织形式。跨职能的团队同时负责构建和运营每个产品,每个产品被分割成许多单个的服务,这些服务通过消息总线(Message Bus)通信。
⼤型的整体应⽤程序(monolithic applications)也可以按照业务功能进⾏模块化(modularized),尽管这种情况不常见。当然,我们可以敦促⼀个构建整体应⽤程序(monolithic application )的⼤型团队,按业务线来分割⾃⼰。我们已经看到的主要问题是,这种组件形式会导致很多的依赖。如果整体
应⽤程序(monolithic applications)跨越很多模块边界(modular boundaries ),那么对于团队的每个成员短期内修复它们是很困难的。此外,我们发现,模块化需要⼤量的强制规范。服务组件所要求的必需的更明确的分离使得保持团队边界清晰更加容易。
产品不是项⽬
⼤部分的软件开发者都使⽤这样的项⽬模式:致⼒于提供⼀些被认为是完整的软件。交付⼀个他们认为完成的软件。软件移交给运维组织,然后,解散构建软件的团队。
微服务(Microservice )的⽀持者认为这种做法是不可取的,并提议团队应该负责产品的整个⽣命周期。Amazon 理念是“你构建,你运维(you build, you run it)”,要求开发团队对软件产品的整个⽣命周期负责。这要求开发者每天都关注他们的软件运⾏如何,增加跟⽤户的联系,同时承担⼀些售后⽀持。
产品的理念,跟业务能⼒联系起来。不是着眼于完成⼀套功能的软件,⽽是有⼀个持续的关系,是如何能够帮助软件及其⽤户提升业务能⼒。
b型钢为什么相同的⽅法不能⽤在整体应⽤程序(monolithic applications),但更⼩的服务粒度能够使创建服务的开发者与使⽤者之间的个⼈联系更容易。
双生筷
强化终端及弱化通道
当构建不同的进程间通信机制的时候,我们发现有许多的产品和⽅法能够把更加有效的⽅法强加⼊通信机制中。⽐如企业服务总线(ESB),这样的产品提供更有效的⽅式改进通信过程中的路由、编码、传输、以及业务处理规则。
微服务倾向于做如下的选择:强化终端及弱化通道。微服务的应⽤致⼒松耦合和⾼内聚:采⽤单独的业务逻辑,表现的更像经典Unix意义上的过滤器⼀样,接受请求、处理业务逻辑、返回响应。它们更喜欢简单的REST风格,⽽不是复杂的协议,如WS或者BPEL或者集中式框架。
沙滩棒球有两种协议最经常被使⽤到:包含资源API的HTTP的请求-响应和轻量级消息通信协议。最为重要的建议为:
善于利⽤⽹络,⽽不是限制(Be of the web, not behind the web)。
——Ian Robinson
微服务团队采⽤这样的原则和规范:基于互联⽹(⼴义上,包含Unix系统)构建系统。这样经常使⽤的资源⼏乎不⽤什么代价就可以被开发者或者运⾏商缓存。
第⼆种做法是通过轻量级消息总线来发布消息。这种通信协议⾮常的单⼀(单⼀到只负责消息路由),像RabbitMQ或者ZeroMQ这样的简单实现甚⾄像可靠的异步机制都没提供,以⾄于需要依赖产⽣或者消费消息的终端或者服务来处理这类问题。
在整体式风格中,组件在进程内执⾏,进程间的消息通信通常通过调⽤⽅法或者回调函数。从整体式风格到微服务框架最⼤的问题在于通信⽅式的变更。从内存内部原始的调⽤变成远程调⽤,产⽣了⼤量的不可靠通信。因此,你需要把粗粒度的⽅法变成更加细粒度的通信。
高增益天线分散治理
集中治理的⼀种好处是在单⼀平台上进⾏标准化。经验表明这种趋势的好处在缩⼩,因为并不是所有的问题都相同,⽽且解决⽅案并不是万能的。我们更加倾向于采⽤适当的⼯具解决适当的问题,整体式的应⽤在⼀定程度上⽐多语⾔环境更有优势,但也不适合所有的情况。
把整体式框架中的组件,拆分成不同的服务,我们在构建它们时有更多的选择。你想⽤Node.js去开发报表页⾯吗?做吧。⽤C++来构建对实时性要求⾼的组件?很好。你想以在不同类型的数据库中切换,来提⾼组件的读取性能?我们现在有技术⼿段来实现它了。
当然,你可以做更多的选择,但也不意味你就可以这样做,因为你的系统使⽤这种⽅式进⾏侵害着你已经有的决定。
采⽤微服务的团队更喜欢不同的标准。他们不会把这些标准写在纸上,⽽是喜欢这样的思想:开发有⽤的⼯具来解决开发者遇到的相似的问题。这些⼯具通常从实现中成长起来,并进⾏了⼴泛范围内分享,当然,它们有时,并不⼀定,会采⽤开源模式。现在开源的做法也变得越来越普遍,git或者github成为了它们事实上的版本控制系统。
Netfix就是这样的⼀个组织,它是⾮常好的⼀个例⼦。分享有⽤的、尤其是经过实践的代码库激励着其它的开发者也使⽤相似的⽅式来解决相似的问题,当然,也保留着根据需要使⽤不同的⽅法的权⼒。共享库更关注于数据存储、进程内通信以及我们接下来讨论到的⾃动化等这些问题上。
微服务社区中,开销问题特别引⼈注意。这并不是说,社区不认为服务交互的价值。相反,正是因为发现到它的价值。这使得他们在寻各种⽅法来解决它们。如Tolearant Reader和Consumer-Driven Contracts这样的设计模式就经常被微服务使⽤。这些模式解决了独⽴服务在交互过程中的消耗问题。使⽤Consumer-Driven Contracts增加了你的信⼼,并实现了快速的反馈机制。事实上,我们知道澳⼤利亚的⼀个团队致⼒使⽤Consumer-Drvien Contracts开发新的服务。他们使⽤简单的⼯程,帮助他们定义服务的接⼝。使得在新服务的代码开始编写之前,这些接⼝就成为⾃动化构建的⼀个部分。构建出来的服务,只需要指出这些接⼝适⽤的范围,⼀个优雅的⽅法避免了新软件中的'YAGNI '困境。这些技术和⼯具在使⽤过程中完善,通过减少服务间的耦合,限制了集中式管理的需求。
也许分散治理普及于亚马逊“编译它,运维它”的理念。团队为他们开发的软件负全部责任,也包含7*24⼩时的运⾏。全责任的⽅式并不常见,但是我们确实发现越来越多的公司在他们的团队中推⼴。Netfix是另外⼀个接受这种理念的公司。每天凌晨3点被闹钟吵醒,因为你⾮常的关注写的代码质量。这在传统的集中式治理中是⼀件多么不可思议的事情呀。
分散数据管理
对数据的分散管理有多种不同的表现形式。最为抽象层次,它意味着不同系统中的通⽤概念是不同的。这带来的问题是⼤型的跨系统整合时,⽤户使⽤不同的售后⽀持将得到不同的促销信息。这种情况叫做并没有给⽤户显⽰所有的促销⼿段。不同的语法确实存在相同的词义或者(更差)相同的词义。
应⽤之间这个问题很普遍,但应⽤内部这个问题也存在,特别是当应⽤拆分成不同的组件时。对待这个问题⾮常有⽤的⽅式为Bounded Context的领域驱动设计。DDD把复杂的领域拆分成不同上下⽂边界以及它们之间的关系。这样的过程对于整体架构和微服务框架都很有⽤,但是服务间存在着明显的关系,帮助我们对上下⽂边界进⾏区分,同时也像我们在业务功能中谈到的,强⾏拆分。
当对概念模式下决⼼进⾏分散管理时,微服务也决定着分散数据管理。当整体式的应⽤使⽤单⼀逻辑数据库对数据持久化时,企业通常选择在应⽤的范围内使⽤⼀个数据库,这些决定也受⼚商的商业权
电弧螺柱焊机
限模式驱动。微服务让每个服务管理⾃⼰的数据库:⽆论是相同数据库的不同实例,或者是不同的数据库系统。这种⽅法叫Polyglot Persistence。你可以把这种⽅法⽤在整体架构中,但是它更常见于微服务架构中。
图 4 Polyglot Persistence
微服务由于分散数据,意味着管理数据更新。处理数据更新的常⽤⽅法是使⽤事务来保证不同的资源修改数据库的⼀致性。这种⽅法通常在整体架构中使⽤。
使⽤事务是因为它能够帮助处理⼀⾄性问题,但对时间的消耗是严重的,这给跨服务操作带来难题。分布式事务⾮常难以实施,因此微服务架构强调服务间事务的协调,并清楚的认识⼀致性只能是最终⼀致性以及通过补偿运算处理问题。
新风控制系统
选择处理不⼀致问题对于开发团队来说是新的挑战,但是也是⼀个常见的业务实践模式。通常业务上允许⼀定的不⼀致以满⾜快速响应的需求,但同时也采⽤⼀些恢复的进程来处理这种错误。当业务上处理强⼀致性消耗⽐处理错误的消耗少时,这种付出是值得的。
基础设施⾃动化
基础设施⾃动化技术在过去⼏年中得到了长⾜的发展:云计算,特别是AWS的发展,减少了构建、发布、运维微服务的复杂性。
许多使⽤微服务架构的产品或者系统,它们的团队拥有丰富的持续部署以及持续集成的经验。团队使⽤这种⽅式构建软件致使更⼴泛的依赖基础设施⾃动化技术。下图说明这种构建的流程:
图 5 基本的构建流程

本文发布于:2024-09-21 15:36:45,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/1/156704.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:服务   团队   组件
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议