微服务
在过去几年中,“微服务架构”这一术语如雨后春笋般涌现出来,它描述了一种将软件应用程序设计为一组可独立部署的服务的特定方式。虽然这种架构风格没有明确的定义,但在组织、业务能力上有一些共同的特征:自动化部署,端点智能化,语言和数据的去中心化控制。
“微服务” - 软件架构拥挤大街上的有一个新术语。虽然我们自然的倾向是轻蔑的一瞥将它一带而过,然而我们发现这一术语描述了一种越来越吸引人的软件系统风格。我们已看到,在过去的几年中有许多项目使用了这种风格,并且到目前为止结果都还不错,以致于这已变成了我们同事在构建企业级应用程序时默认使用的架构风格。然而,遗憾的是并没有太多的信息来概述什么是微服务风格以及怎样用这种风格。
简单来说,微服务架构风格是一种将一个单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中,服务间通信采用轻量级通信机制(通常用HTTP资源API)。这些服务围绕业务能力构建并且可通过全自动部署机制独立部署。这些服务共用一个最小型的集中式的管理,服务可用不同的语言开发,使用不同的数据存储技术。
与单体风格作对比有助于开始解释微服务风格:单体应用程序被构建为单一单元。企业级应用程序通常由三部分组成:客户端侧用户接口(由运行于开发机上的浏览器里的HTML页面和Javascript组成),数据库(由插入到通用关系型数据库管理系统中的许多数据表格组成),服务端应用程序。服务端应用程序处理HTTP请求,执行领域逻辑,从数据库中检索、更新数据,选择、填充将要发送到浏览器的HTTP视图。服务端应用程序是一个单一的逻辑可执行单体。系统的任何改变都将牵涉到重新构建和部署服务端的一个新版本。
这样的单体服务器是构建这样一个系统最自然的方式。处理请求的所有逻辑都运行在一个单一进程中,允许你使用编程语言的基本特性将应用程序划分类、函数和命名空间。你认真的在开发机上运行测试应用程序,并使用部署管道来保证变更已被正确地测试并部署到生产环境中。该单体的水平扩展可以通过在负载均衡器后面运行多个实例来实现。
单体应用程序可以是成功的,但人们日益对他们感到挫败,尤其是随着更多的应用程序被部署在云上。变更周期被捆绑在一起 —— 即使只变更应用程序的一部分,也需要重新构建并部署整个单体。长此以往,通常将很难保持一个良好的模块架构,这使得很难变更只发生在需要变更的模块内。程序扩展要求进行整个应用程序的扩展而不是需要更多资源的应用程序部分的扩展。
图1 整理架构与微服务架构这些挫败导向了微服务架构风格:构建应用程序为服务套件。除了服务是可独立部署、可独立扩展的之外,每个服务都提供一个固定的模块边界。甚至允许不同的服务用不同的的语言开发,由不同的团队管理。
我们不会声称微服务风格是新颖的、创新的,其本质至少可以回溯到Unix的设计哲学。但我们的确认为没有足够的人仔细考虑微服务架构,并且如果使用它很多软件实现将会更好。
微服务架构的特性
我们无法给出微服务架构风格的一个正式定义,但我们可以尝试去描述我们看到的符合该架构的一些共性。就概述共性的任何定义来说,并非所有的微服务架构风格都有这些共性,但我们期望大多数微服务架构风格展现出大多数特性。虽然本文作者一直是这个相当松散的社区的活跃用户,我们的目的是试图描述我们工作中和我们知道的一些团队的相似努力中的所见所闻。特别是我们不会制定一些可遵守的定义。
组件化(Componentization )与服务(Services)
自从我们开始软件行业以来,一直希望由组件构建系统,如同我们看到的现实世界中事物的构造方式一样。在最近的二十年中,我们看到作为大多数语言平台一部分的公共库的大量汇编工作取得了很大的进展。
当我们谈论组件时,可能会陷入一个困境——什么是组件。我们的定义是,组件(component)是一个可独立替换和升级的软件单元。
微服务架构将使用库,但组件化软件的主要方式是分解成服务。我们把库定义为链接到程序并使用内存函数调用来调用的组件,而服务是一种进程外的组件,它通过web服务请求或rpc(远程过程调用)机制通信(这和很多面向对象程序中的服务对象的概念是不同的。)
使用服务作为组件而不是使用库的一个主要原因是服务是可独立部署的。如果你有一个应用程序是由单一进程里的多个库组成,任何一个组件的更改都导致必须重新部署整个应用程序。但如果应用程序可分解成多个服务,那么单个服务的变更只需要重新部署该服务即可。当然这也不是绝对的,一些变更将会改变服务接口导致一些协作,但一个好的微服务架构的目的是通过内聚服务边界和按合约演进机制来最小化这些协作。
使用服务作为组件的另一个结果是一个更加明确的组件接口。大多数开发语言都没有一个良好的机制来定义一个发布的接口
(Published Interface)。发布的接口是指一个类向外公开的成员,比如 Java 中的声明为 Public 的成员,C# 中声明为非 Internal 的成员。通常只有文档和规则来预防客户端打破组件的封装,这导致组件间过于紧耦合。服务通过明确的远程调用机制可以很容易的避免这些。
像这样使用服务也有不足之处。远程调用比进制内调用更消耗资源,因此远程 API 需要粗粒度(coarser-grained),但这会比较难使用。如果你需要调整组件间的职责分配,当跨越进程边界时,这样的行为动作更难达成。
一个可能是,我们看到,服务可以映射到运行时进程(runtime processes)上,但也只是一个可能。服务可以由多个进程组成,它们会同时开发和部署,例如一个应用程序进程和一个只能由这个服务使用的数据库。
围绕业务功能的组织
当寻找把一个大的应用程序拆分成小的部分时,通常管理都会集中在技术层面,UI团队、服务端业务逻辑团队和数据库团队。当使用这种标准对团队进行划分时,即使是简单的更改也会导致跨团队的时间和预算审批。一个聪明的团队将围绕这些优化,两害取其轻 - 只把业务逻辑强制放在它们会访问的应用程序中。换句话说,逻辑无处不在。这是Conway法则在起作用的一个例子。
任何设计系统(广泛定义的)的组织将产生一种设计,他的结构就是该组织的通信结构。——Melvyn Conway, 1967
Melvyn Conway 的意思是,像下图所展示的,设计一个系统时,将人员划分为 UI 团队,中间件团队,DBA 团队,那么相应地,软件系统也就会自然地被划分为 UI 界面,中间件系统,数据库。
图2 实践中的Conway's Law
微服务采用不同的分割方法,划分成围绕业务能力组织的服务。这些服务采取该业务领域软件的宽栈实现,包括用户接口、持久化存储和任何外部协作。因此,团队都是跨职能的,包括开发需要的全方位技能:用户体验、数据库、项目管理。
图3 通过团队边界强调服务边界
www.comparethemarket.com是按这种方式组织的一个公司。跨职能团队负责创建和运营产品,产品被划分成若干个体服务,这些服务通过消息总线通信。
大型的整体应用程序(monolithic applications)也可以按照业务功能进行模块化(modularized),尽管这样情况不常见。当然,我们可以敦促一个构建整体应用程序(monolithic application)的大型团队,按业务线来分割自己。我们已经看到的主要问题是,这种组件形式会导致很多的依赖。如果整体应用程序(monolithic applications)跨越很多模块边界(modular boundaries),那么对于团队的每个成员短期内修复它们是很困难的。此外,我们发现,模块化需要大量的强制规范。服务组件所要求的必需的更明确的分离使得保持团队边界清晰更加容易。
产品不是项目
我们看到大多数应用程序开发工作使用一个项目模式:目标是交付将要完成的一些软件。完成后的软件被交接给维护组织,然后它的构建团队就解散了。
微服务支持者倾向于避免这种模式,而是认为一个团队应该负责产品的整个生命周期。对此一个共同的启示是亚马逊的理念“你构建,你运维(you build, you run it)”,开发团队负责软件的整个产品周期。这使开发者经常接触他们的软件在生产环境如何工作,并增加与他们的用户联系,因为他们必须承担至少部分的支持工作。
产品思想与业务能力紧紧联系在一起。要持续关注软件如何帮助用户提升业务能力,而不是把软件看成是将要完成的一组功能。
没有理由说为什么同样的方法不能用在单体应用程序上,但服务的粒度更小,使得它更容易在服务开发者和用户之间建立个人关系。
智能端点和哑管道
当构建不同的进程间通信机制的时候,我们发现有许多的产品和方法能够把更加有效方法强加入的通信机制中。比如企业服务总线(ESB),这样的产品提供更有效的方式改进通信过程中的路由、编码、传输、以及业务处理规则。
微服务社区主张另一种方法:智能端点和哑管道。基于微服务构建的应用程序的目标是尽可能的解耦和尽可能的内聚 - 他们拥有自己的领域逻辑,他们的行为更像经典UNIX理念中的过滤器 - 接收请求,应用适当的逻辑并产生响应。使用简单的REST风格的协议来编排他们,而不是使用像WS-Choreography或者BPEL或者通过中心工具编制(orchestration)等复杂的协议。
最常用的两种协议是使用资源API的HTTP请求-响应和轻量级消息传送。对第一种协议最好的表述是
本身就是web,而不是隐藏在web的后面。(Be of the web, not behind the web)。——Ian Robinson
微服务团队使用的规则和协议,正是构建万维网的规则和协议(在更大程度上,是UNIX的)。从开发者和运营人员的角度讲,通常使用的资源可以很容易的缓存。
第二种常用方法是在轻量级消息总线上传递消息。选择的基础设施是典型的哑的(哑在这里只充当消息路由器) - 像RabbitMQ或ZeroMQ这样简单的实现仅仅提供一个可靠的异步交换结构 - 在服务里,智能仍旧存活于端点中,生产和消费消息。
单体应用中,组件都在同一进程内执行,它们之间通过方法调用或函数调用通信。把单体变成微服务最大的问题在于通信模式的改变。一种幼稚的转换是从内存方法调用转变成RPC,这导致频繁通信且性能不好。相反,你需要用粗粒度通信代替细粒度通信。
分散治理/去中心化治理
集中治理的一种好处是在单一平台上进行标准化。经验表明这种趋势的好处在缩小,因为并不是所有的问题都相同,而且解决方案并不是万能的。我们更加倾向于采用适当的工具解决适当的问题,整体式的应用在一定程度上比多语言环境更有优势,但不适合所有的情况。
把单体的组件分裂成服务,在构建这些服务时可以有自己的选择。你想使用Node.js开发一个简单的报告页面?去吧。用C++实现一个特别粗糙的近乎实时的组件?好极了。你想换用一个更适合组件读操作数据的不同风格的数据库?我们有技术来重建它。
当然,仅仅因为你可以做些什么,而不意味着你应该这样做 - 但用这种方式划分系统意味着你可以选择。
团队在构建微服务时也更喜欢用不同的方法来达标。他们更喜欢生产有用的工具这种想法,而不是写在纸上的标准,这样其他开发者可以用这些工具解决他们所面临的相似的问题。有时,这些工具通常在实施中收获并与更广泛的群体共享,但不完全使用一个内部开源模型。现在git和github已经成为事实上的版本控制系统的选择,在内部开放源代码的实践也正变得越来越常见。
Netflix是遵守这一理念的很好的例子。尤其是,以库的形式分享有用的且经过市场检验的代码,这激励其他开发者用类似的方式解决相似的问题,同时还为采用不同方法敞开了大门。共享库倾向于聚焦在数据存储、进程间通信和我们接下来要深入讨论的基础设施自动化的共性问题。
对为服务社区来说,开销特别缺乏吸引力。这并不是说社区不重视服务合约。恰恰相反,因为他们有更多的合约。只是他们正在寻找不同的方式来管理这些合约。如Tolearant Reader和Consumer-Driven Contracts这样的设计模式就经常被微服务使用。
这些模式解决了独立服务在交互过程中的消耗问题。使用Consumer-Driven Contracts增加了你的信心,并实现了快速的反馈机制。事实上,我们知道澳大利亚的一个团队致力使用Consumer-Drvien Contracts开发新的服务。他们使用简单的工程,帮助他们定义服务的接口。使得在新服务的代码开始编写之前,这些接口就成为自动化构建的一个部分。构建出来的服务,只需要指出这些接口适用的范围,一个优雅的方法避免了新软件中的'YAGNI '困境。这些技术和工具在使用过程中完善,通过减少服务间的耦合,限制了集中式管理的需求。
也许去中心化治理的最高境界就是亚马逊广为流传的build it/run it理念。团队要对他们构建的软件的各方面负责,包括7*24小时的运营。这一级别的责任下放绝对是不规范的,但我们看到越来越多的公司让开发团队负起更多责任。Netflix是采用这一理念的另一家公司。每天凌晨3点被传呼机叫醒无疑是一个强有力的激励,使你在写代码时关注质量。这是关于尽可能远离传统的集中治理模式的一些想法。
分散数据管理/去中心化数据管理
数据管理的去中心化有许多不同的呈现方式。在最抽象的层面上,这意味着使系统间存在差异的世界概念模型。在整合一个大型企业时,客户的销售视图将不同于支持视图,这是一个常见的问题。客户的销售视图中的一些事情可能不会出现在支持视图中。它们确实可能有不同的属性和(更坏的)共同属性,这些共同属性在语义上有微妙的不同。
这个问题常见于应用程序之间,但也可能发生在应用程序内部,尤其当应用程序被划分成分离的组件时。一个有用的思维方式是有界上下文Bounded Context的领域驱动设计(Domain-Driven Design, DDD)。DDD把复杂的领域拆分成不同上下文边界以及它们之间的关系。这个过程对单体架构和微服务架构都是有用的,但在服务和上下文边界间有天然的相关性,边界有助于澄清和加强分离,就像业务能力部分描述的那样。
和概念模型的去中心化决策一样,微服务也去中心化数据存储决策。虽然单体应用程序更喜欢单一的逻辑数据库做持久化存储,但企业往往倾向于一系列应用程序共用一个单一的数据库 - 这些决定是供应商授权许可的商业模式驱动的。微服务更倾向于让每个服务管理自己的数据库,或者同一数据库技术的不同实例,或完全不同的数据库系统 - 这就是所谓的混合持久化Polyglot Persistence。你可以把这种方法用在单体应用程序中,但是它更常见于微服务架构中。
对跨微服务的数据来说,去中心化责任对管理升级有影响。处理更新的常用方法是在更新多个资源时使用事务来保证一致性。这个方法通常用在单体中。
像这样使用事务有助于一致性,但会产生显著地临时耦合,这在横跨多个服务时是有问题的。分布式事务是出了名的难以实现,因此微服务架构强调服务间的无事务协作,对一致性可能只是最后一致性和通过补偿操作处理问题有明确的认知。
对很多开发团队来说,选择用这样的方式管理不一致性是一个新的挑战,但这通常与业务实践相匹配。通常业务处理一定程度的不一致,以快速响应需求,同时有某些类型的逆转过程来处理错误。这种权衡是值得的,只要修复错误的代价小于更大一致性下损失业务的代价。
基础设施自动化
在过去的几年中,基础设施自动化已经发生了巨大的变化,特别是云和AWS的演化已经降低了构建、部署和运维微服务的操作复杂度。
许多使用微服务架构的产品或者系统,它们的团队拥有丰富的持集部署以及它的前任持续集成的经验。团队使用这种方式构建软件致使更广泛的依赖基础设施自动化技术。下图说明这种构建的流程:
因为这不是一篇关于持续交付的文章,我们这里将之光住几个关键特性。我们希望我们的软件应该这样方便的工作,因此我们需要更多的自动化测试。促进科工作软件沿管道线“向上”意味着我们自动化部署到每个新的环境中。
一个单体应用程序可以十分愉快地通过这些环境被构建、测试和推送。事实证明,一旦你为单体投入了自动化生产之路,那么部署更多的应用程序似乎也不会更可怕。请记住,持续部署的目标之一是使部署枯燥,所以无论是一个或三个应用程序,只要它的部署仍然枯燥就没关系。
我们看到团队使用大量的基础设施自动化的另一个领域是在生产环境中管理微服务时。与我们上面的断言(只要部署是枯燥的)相比,单体和微服务没有太大的差别,各运营场景可以明显不同。
图6 模块化部署的区别
容错性设计
使用服务作为组件的一个结果在于应用需要有能容忍服务的故障的设计。任务服务可能因为供应商的不可靠而故障,客户端需要尽可能的优化这种场景的响应。跟整体构架相比,这是一个缺点,因为它带来的额外的复杂性。这将让微服务团队时刻的想到服务故障的情况下用户的体验。Netflix 的Simian Army可以为每个应用的服务及数据中心提供日常故障检测和恢复。
这种产品中的自动化测试可以让大部分的运维团队正常的上下班。这并不意味着整体构架的应用没有这么精巧的监控配置,只是在我们的经验中它并不常见。
由于服务可以随时故障,快速故障检测,乃至,自动恢复变更非常重要。微服务应用把实时的监控放在应用的各个阶段中,检测构架元素(每秒数据库的接收的请求数)和业务相关的指标(把分钟接收的定单数)。监控系统可以提供一种早期故障告警系统,让开发团队跟进并调查。
对于微服务框架来说,这相当重要,因为微服务相互的通信可能导致紧急意外行为。许多专家车称赞这种紧急事件的价值,但事实是这种紧急行为有时是灾难。监控是至关重要的,它能快速发现这种紧急不良行为,让我们迅速修复它。
整体架构,跟微服务一样,在构建时是通明的,实情上,它们就是这样子的。它们不同之处在于,你需要清楚的认识到不同进程间运行的服务是不相关的。库对于同一进程是透明的,也因此不那么重要了。
微服务团队期望清楚的监控和记录每个服务的配置,比如使用仪表盘显示上/下线状态、各种运维和业务相关的指标。对断路器(circuit breaker)状态、目前的吞吐量和时延细节,我们也会经常遇到。
设计改进
微服务实践者,通常有不断改进设计的背景,他们把服务分解成进一步的工具。这些工具可以让应用开发者在不改变速度情况下,控制都他们的应用的需求变更。变更控制不意味首减少变更,而是使用适当的方式和工具,让它更加频繁,至少,很好让它变得可控。
不论如何,当你试图软件系统拆分成组件时,你将面临着如何拆分的问题。那么我们的决定拆分我们应用的原则是什么呢?首要的因素,组件可以被独立替换和更新的,这意味着我们寻找的关键在于,我们要想象着重写一个组件而不影响它们之前的协作关系。事实上,许多的微服务小组给它进一步的预期:服务应该能够报废的,而不是要长久的发展的。
Guardian网站就是这方面的一个优秀的例子,它初期被设计和构建成一个整体架构,但它已经向微服务的发展了。整体构架仍然是它网站的核心,但是他们使用微服务来增加那些使用整体架构API的新特性。这种方法增加这些临时的特性非常方便,比如运动新闻的特稿。这样站点的一个部分可以使用快速的开发语言迅速整合起来,当它过时后可以一次性移除。我们发现一家金融机构用相似的方法增加新的市场营销活动,数周或者几个月后把它撤销。
可代替是模块化开发中的一个特例,它是用模块来应对需要变更的。你希望让变更是相同模块,相同周期中进行变化而已。系统的某些很小做变更部分,也应该放在不同的服务中,这样它们更容易让它们消亡。如果你发现两个服务一直重复的变更时,这就是一个要合并它们的信号了。
把组件改成服务,增加了细化发布计划的一个机会。整体构架的任务变更需要整个应用的完整的构建和发布。然而,使用微服务,你只需要发布你要修改的服务就可以了。这将简化和加速你的发布周期。缺点是你需要为一个变更服务发布可能中断用户的体验而担心。传统的集成方法是使用版本来处理这些问题,但是微服务版本仅是最后的通告手段。我们需要在设计服务时尽可能的容忍供应商的变更,以避免提供多个版本。
微服务是未来吗?
我们写这篇文章的主要目的在于解释微服务的主要思想和原则。但是发现做这事的时候,我们清醒的认识到微服务构架风格是一个非常重要的想法:一个值得企业应用中认真考虑的东西。我们最近使用这种风格构建了几个系统,认识那些也使用和喜欢这种方法的爱好者。
我们认识的使用这种方式的先行者,包含亚马逊、Netflix、The Guardian、The UK Government Digital Service、realestate.com.au、Forward和comparethemarket.com。2013看的巡回会议充满了向正在想成为微服务一分子的公司,包含Travis CI。此外,大量的组件正在从事我们认为是微服务的事,只是没有使用微服务的名字而已。(通常,它们被打上SOA的标签,尽管,我们认为SOA有许多不同的地方。)
尽管有这些积极的经验,然后,我们也不急于确认微服务是未来软件架构方向。至今为止,我们的经验与整体风格的应该中相比出来的是有优势的,但是我们意识知这样的事实,我们并没有足够的时间来证明我们的论证。
你所使用的架构通常是你开发出来后,使用的几年的实际成果。我们看到这些工程是在一个优秀的团队,带着对模块化的强烈追求,使用在过去几年中已经衰退的整体架构构建出来的。许多人相信,这种衰退不太可能与微服务有关,因为服务边界是清晰的并且很难再完善的。然而,当我们还没看到足够多的系统运行足够长时间时,我们不能肯定微服务构架是成熟的。
当然,还有原因就是,有人期望微服务构架不够成熟。在组件化方面的任何努力,其成功都依赖于软件如何拆分成适合的组件。指出组件化的准确边界应该在那,这是非常困难的。改良设计要承认边界的权益困境和因此带来的易于重构的重要性。但是当你的组件是被远程通信的服务时,重构比进程内的库又要困难的多。服务边界上的代码迁移是困难的,任务接口的变更需要参与者的共同协作,向后兼容的层次需要被增加,测试也变更更加复杂。
另一个问题在于,如果组件并没有清晰的划分,你的工作的复杂性将从组件内部转向组件间的关系。做这事不仅要围绕着复杂,它也要面对着不清晰和更难控制的地方。很容易想到,当你在一个小的、简单的组件内找东西,总比在没有关系的混乱的服务间要容易。
最后,团队技能也是重要的因素。新的技术倾向于被掌握更多的技能的团队使用。但是掌握多技能的团队中使用的技巧在较少技能的团队中并不是必需的。我们发现大量的少技能的团队构建混乱的整合构架,但是它要花时间去证明使用微服务在这种情况下会发生什么。一个糟糕的团队通常开发糟糕的系统:很难说,微服务在这种情况下是否能帮助它们,还是破坏它们。
一个理性的争议在于,我们听说,你不应该从微服务构架开始做。最好从整体构架开发,做模块化开发,然后当整体构架出现问题是再把模块化拆分成服务。(尽管这种建议不是好主意,因为一个好的进程内接口并不是一个好的服务接口。)
因此我们持这种谨慎的乐观。到目前为止,我们还没有足够认识,关于微构架能否被大范围的推广。我们不能肯定的说,我们要终结什么,但是软件开发的挑战在于你只能在不完整的信息中决定你目前要处理的问题。
其它
微服务系统多大
虽然,“微服务”已成为这种架构风格的代称,这个名字确实会导致不幸的聚焦于服务的大小,并为“微”由什么组成争论不休。在与微服务实践者的对话中,我们发现有各种大小的服务。最大的服务报道遵循亚马逊两匹萨团队(也就是,整个团队吃两个披萨就吃饱了)的理念,这意味着团队不超过12个人。在更小的规模大小上,我们看到这样的安排,6人团队将支持6个服务。
这导致这样一个问题,在服务每12个人和服务每1个人的大小范围内,是否有足够打的不同使他们不能被集中在同一微服务标签下。目前,我们认为最好把它们组合在一起。但随着深入探索这种风格,我们一定有可能改变我们的看法。
微服务与SOA
当我们谈论微服务时,一个常见问题是它是否仅仅是十年前我们看到的面向服务的架构(SOA)。这一点是有可取之处的,因为微服务风格和SOA赞同的某些主张十分相似。尽管如此,问题在于SOA意味的太多不同的东西了,而大多数时候,我们遇到的所谓的SOA和这里我们描述的风格明显不同,这种不同通常由于SOA专注于用于集成单体应用的ESB。
特别是我们已看到太多的搞砸的服务导向的实现,从趋向于隐藏ESB中的复杂性,到花费数百万并不产生任何价值的失败的多年举措,到积极抑制变化的集中治理模型,这有时很难看到过去的这些问题。
可以肯定的时,微服务社区中使用的许多的技术都开发者是从大型机构的整合服务经验中发展来的。Tolerant Reader模式就是这样的一个例子。由于互联网的发展,利用简单的协议这种方法,让它从这些经验传达的出来。这是从已经很复杂的集中式标准中的一种反模式,坦白的说,真让人惊叹。(无论何时,当你需要用一个服务来管理你的所有的服务,你就知道这很麻烦。)
SOA的这种常见表现使得一些微服务倡导者完全拒绝SOA标签,尽管其他人认为微服务是SOA的一种形式,也许服务导向做得对。无论哪种方式,事实上,SOA意味着如此不同的事情,这意味着有一个术语来更清晰地定义这种架构风格是有价值的。
多语言,多选择
JVM作为平台的成长就是在一个共同平台内混合语言的最新例子。几十年来,破壳到高级语言利用高层次抽象的优势已成为一种普遍的做法。如同下拉到机器硬件,用低层次语言写性能敏感的代码一样。然而,很多单体不需要这个级别的性能优化和常见的更高层次的抽象,也不是DSL的。相反,单体通常是单一语言的并趋向于限制使用的技术的数量
实践标准和强制标准
它有点尴尬,微服务团队倾向于避免这种通常由企业架构队伍定制的僵硬的强制标准,但是它们却非常乐于甚至推广这些开放的标准,如HTTP、ATOM、其它微规范。
关键的区别是如何定制标准和如何执行。由诸如IETF等组织管理的标准仅当在世界范围内有几个有用的实现时才变成标准,这往往会从成功的开源项目成长起来。
这些标准是远离企业世界的标准。往往被一个几乎没有近期编程经验的或受供应商过度影响的组织开发的。
让做对事更容易
我们发现,作为持续交付和持续部署的一个后果,增加自动化的一个副作用是创造有用的工具,以帮助开发人员和运营人员。用于创造人工制品、管理代码库、起立(standing up)简单服务或添加标准监控和日志记录的工具现在都是很常见的。web上最好的例子可能是Netflix's的开源工具,但是包含Dropwizard在内的其它工具也被广泛的使用着。
断路器(circuit breaker)和产品中现有的代码
断路器(circuit breaker)出现在《Realease It!》一书中,与Bulkhead和Timeout这样的模式放在一起。实施起来,这些模式用于构建通信应用时相当的重要。Netflix的博客在解释它们的应用时,做了大量的工作
同步是有害的
任务时候,你在服务间的调用使用同步的方法,都会遇到宕机时间的乘积效应。简单的说,你的系统宕机时间是你系统的单独组件的宕机时间的乘积。你面临的选择使用异步或者管理宕机时间。在www.guardian.co.uk中,它们在新平台中使用一种简单的规则来实现它:在Netflix中每次用户请求的同步调用,他们重新设计的平台API都会把它构建成异步的API来执行。
网友评论