拯救之道——微服务架构(架构介绍,架构好处与弊端) Posted 2021-06-25 多栖技术控小董
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了拯救之道——微服务架构(架构介绍,架构好处与弊端)相关的知识,希望对你有一定的参考价值。
玛丽意识到, FTGO 应用程序必须迁移为
微服务架构 。
有趣的是,软件架构其实对功能性需求影响并不大。事实上,在任何架构甚至是一团糟
的架构之上,你都可以实现一组
用例
(应用的功能性需求)
。
因此,即使是成功的应用程序
(例如FTGO),其内部架构也往往是一个大泥球
。
架构的重要性在于它
影响了应用的非功能性需求 ,也称为
质量属性 或者
其他的能力
(-ilities) (软件的质量属性和能力通常由英文词根-ility构成的单词表示,比如availability 、reliability等)。随着FTGO 应用的增长,各种质量属性和问题都浮出水面,最显著的就是影响软件交付速度的可维护性、可扩展性和可测试性。
一方面,训练有素的团队可以
减缓项目 陷入单体地狱的速度。团队成员可以努力维护他
们的模块化应用。他们也可以编写全面的自动化测试。但是另一方面,他们无法避免大型团队在单体应用程序上协同工作的问题,也不能解决日益过时的技术栈问题。团队所能做的就是延缓项目陷入单体地狱的速度,但这是不可避免的。为了逃避单体地狱,他们必须迁移到新架构:
微服务架构
。
今天,针对大型复杂应用的开发,越来越多的共识趋向于考虑使用
微服务架构 。但微服
务到底是什么?不幸的是,微服务这个叫法本身暗示和强调了尺寸(
这也是Chris不建议使用微服务这个词来指代具体的服务实例的原因。微服务暗示了服务的大小,但实际上微服务架构对构成的服务实例并没有大小方面的要求
)。
针对微服务架构有多种定义
。有些仅仅是在字面意义上做了定义:服务应该是微小的不超过100 行代码,等等。另外有些定义要求服务的开发周期必须被限制在两周之内。曾在Netflix 工作的著名架构师Adrian Cockcroft 把微服务架构定义为面向服务的架构,它们由松耦合和具有边界上下文的元素组成。这个定义不错,但仍旧有些复杂难懂。我们来尝试一个更好的定义。
对微服务架构的定义受到了Martin Abbott 和Michael Fisher 的名著《The Art of Scalability >
的启发。这本书描述了一个非常有用的
三维可扩展模型
:扩展立方体,如下图所示。
这个模型描述了扩展一个应用程序的
三种维度
:X、Y和Z。
X 轴扩展是扩展单体应用程序的常用方法。上图展示了X 轴扩展的工作原理。在负载
均衡器之后运行应用程序的
多个实例
。负载均衡器在N 个相同的实例之间分配请求。这是提高应用程序
吞吐量和可用性
的好方法。
Z 轴扩展也需要运行单体应用程序的
多个实例 ,但不同于X轴扩展,每个实例
仅负责数据的一个子集
。
下图展示了Z 轴扩展的工作原理。置于前端的路由器使用请求中的特定属性将请求路由到适当的实例。例如,应用程序可能会使用请求中包含的userld 来路由请求。
在这个例子中,每个应用程序实例
负责一部分用户 。该路由器使用请求Authorization
头部指定的userld来从N个相同的应用程序实例中选择一个。
对于应用程序需要处理
增加的事务和数据量
时,Z轴扩展是一种很好的扩展方式。
X 轴和Z轴扩展有效地提升了应用的吞吐量和可用性,然而这两种方式都
没有解决 日益
增长的开发问题和应用复杂性。
为了解决这些问题,我们需要采用Y 轴扩展,也就是
功能性分解
。Y 轴扩展把一个单体应用分成了一组服务,如下图所示。
服务本质上是一个麻雀虽小但五脏俱全的
应用程序 ,它实现了一组相关的功能,例如订
单管理、客户管理等。服务可以在需要的时候借助X轴或Z轴方式进行扩展。例如,订单服务可以被部署为一组负载均衡的服务实例。
微服务架构的概括性定义是: 把应用程序功能性分解为一组服务的架构风格。请
注意这个定义中并没有包含任何与规模有关的内容。重要的是,每一个服务都是由一组专注的、内聚的功能职责组成。稍后会详细讨论。
目前而言,我们先来看看为什么微服务架构是模块化的一种形式。
模块化是开发
大型、复杂 应用程序的基础。类似FTGO这样的现代应用程序规模太大,
很难作为一个整体开发,也很难让一个人完全理解。为了让不同的人开发和理解,大型应用
需要拆分为模块
。在单体应用中,模块通常由一组编程语言所提供的结构(例如Java 的包),或者Java JAR 文件这样的构建制品(artifact)来定义。然而,正如FTGO开发者所认识到的,这类实践往往会出现问题,随着时间的推移和反复的开发迭代,单体应用往往会蜕变成一个大泥球。
微服务架构使用服务作为
模块化的单元 。服务的API为它自身构筑了一个不可逾越的边
界,你无法越过API去访问服务内部的类,这与采用Java包的单体应用完全不同。因此模块化的服务更容易随着时间推移而不断演化。微服务架构也带来其他的好处,例如服务可以
独立进行部署和扩展
。
微服务架构的一个关键特性是每一个服务之间都是松耦合的,它们仅通过
API 进行通信
。实现这种松耦合的方式之一,是每个服务都拥有自己的私有数据库。对于一个线上商店来说, Order Service拥有一个包括ORDERS表的数据库, Customer Service 服务拥有一个包含CUSTOMERS 表的数据库。在开发阶段,开发者可以修改自己服务的数据库模式,而不必同其他服务的开发者协调。在运行时,服务实现了
相互之间的独立
。服务不会因为其他的服务锁住了数据库而进入堵塞的状态。
别担心:松耦合不会让Larry Ellison挣更多钱
Larry Ellison是Oracle 公司的CEO, 开发者在实现微服务架构时往往倾向于采用开源和轻量级的软件,
因此
容易与Oracle 这样的重量
级数据库和中间件厂商形成对
立
。
每一个服务拥有它自己数据库的需求并不意味着每个服务都需要一个独立的数据库
服务器。
这也
就意味着
你不用花10倍或者更多的钱购买Oracle 数据库的许可
。
在后面【微服务的拆分策略】相关文章中
我们会深入探讨这个主题
。
现在我们已经给出了微服务架构的定义,并且描述了它的一些基本特性,让我们来看看
这些如何应用于FTGO 应用程序
。
但首先让我们快速了解将
Y轴扩展
应用于此应用程序的含义。如果我们将Y轴分解应用于FTGO应用程序,我们将获得如下图所示的架构。分解后的应用程序包含许多前端和后端服务。我们还将应用X 轴和可能的Z轴扩展,以便在运行时每个服务都有多个实例。
前端服务 包括API Gateway和餐馆的Web用户界面(Restaurant Web UI) 。API Gateway
扮演了一个对外的角色,它提供了供消费者和快递员的移动应用程序使用的REST API,在后面【对外API模式】相关文章中将详细介绍这部分内容。餐馆的网页界面实现了餐馆用来管理菜单和订单流程的Web 用户界面。
FTGO应用程序的业务逻辑由
众多后端服务 组成。每个后端服务都有一个REST API 和
它自己的私有数据库。后端服务包括以下内容:
Order Service:管理订单。
Delivery Service:管理从餐馆到客户之间的订单派送(送餐) 。
Restaurant Service:维护餐馆有关的信息。
Kitchen Service:管理订单的准备过程。
Accounting Service:处理账单和付款。
许多服务都与前一篇文章介绍的FTGO 单体应用中的模块一一对应。不同的是,每个服务
及其API 都有非常清晰的定义。每个都可以
独立开发、测试、部署和扩展
。此外,该架构在保持模块化方面做得很好。开发人员无法绕过服务的API 并访问其内部组件。我将在后面【微服务重构策略】相关文章中介绍如何将现有的单体应用程序转换为微服务架构。
某些针对微服务架构的批评声称它其实就是SOA,并没有新鲜的内容。在某些层面,它
们的确有
些相似
。
SOA 和微服务架构都是特定的架构风格,它们都以
一系
列服务的方式来
把
一个系统组织在一起
。
但如果深入研究,你就会发现微服务和SOA 之间巨大的差异,如下表
所
示
。
SOA
微服务
服务间通信
智能管道,例如Enterprise Service B us (ESB),往往采用重量级协议, 例如 SOAP 或其他 WS* 标 准
使用哑管道,例如消息代理,或者服务之间点对点通信,使用例如 REST 或 gRPC 类的轻量级协议
数据管理
全局数据模型并共享数据库
每个服务都有自己的数据模型和数据库
典型服务的规模
较大的单体应用
较小的服务
SOA 和微服务架构通常采用完全不同的技术栈。SOA 应用常常选用重量级的技术,例
如SOAP 和其他类似的WS *标准。SOA 常常使用ESB进行服务集成, ESB 是包含了业务和消息处理逻辑的
智能管道
。采用微服务架构设计的应用程序倾向于使用轻量级、开源的技术。服务之间往往采用
哑管道
(例如消息代理)进行通信,使用类似REST 或gRPC 这类轻量级协议。
SOA 和微服务架构在处理数据的方式上也不尽相同。SOA 应用一般都有一个全局的数
据模型,并且共享数据库。与之相反,如之前提到的,微服务架构中每个服务都有属于它自己的数据库。更进一步,我们在后面文章会提到,每一个服务一般都拥有属于它自己的
领域模型
。
SOA 和微服务架构之间的另一个重要区别,就是
服务的尺寸(规模)
。SOA 善于集成大型、复杂的单体应用程序。微服务架构中的服务虽然不是必须要做到很小,但是通常都比较小。因此SOA 应用通常包含和集成若千个大型的服务,微服务架构的应用则常常由数十甚至上百个更小的服务组成。
使大型的复杂应用程序可以持续交付和持续部署。
每个服务都相对较小并容易维护。
服务可以独立部署。
服务可以独立扩展。
微服务架构可以实现团队的自治。
更容易实验和采纳新的技术。
更好的容错性。
微服务架构最重要的好处是它可以实现大型的复杂应用程序的持续交付和持续部署。后面文章我们会介绍
,待续交付和持续部署是
DevOps的一部分
,DevOps是一套快速、频繁、可靠的软件交付实践。高效能的DevOps 组织通常在将软件部署到生产环境时面临更少的问题和故障。
微服务架构通过以下三种方式实现
持续交付和持续部署 :
它拥有持续交付和持续部署所需要的可测试性 。
自动化测试是持续交付和持续部署的一个重要环节。因为每一个服务都相对较小,编写和执行自动化测试变得很容易。因此,应用程序的bug 也就更少。
它拥有持续交付和持续部署所需要的可部署性 。
每个服务都可以独立于其他服务进行部署。如果负责服务的开发人员需要部署对该服务的更改,他们不需要与其他开发人员协调就可以进行。因此,将更改频繁部署到生产中要容易得多。
它使开发团队能够自主且松散耦合 。
你可以将工程组织构建为一个小型(例如,两个比萨。“两个比萨” 原则是指某个事情的参与人数不能多到两个比萨饼还不够他们吃饱的地步。亚马逊CEO 杰夫·贝索斯认为事实上并非参与人数越多越好,他认为人数过多不利千决策的形成, 并会提高沟通的成本,这被称为“两个比萨” 原则)团队的集合。每个团队全权负责一个或多个相关服务的开发和部署。如下图所示,每个团队可以独立于所有其他团队开发、部署和扩展他们的服务。结果,开发的速度变得更快。
因此,微服务架构已经成为任何依赖于软件技术的企业业务的重要基石。
微服务架构的另一个好处在于:相比之下
每个服务都比较小 。开发者更容易理解服务中
的代码。较小规模的代码库不会把IDE等开发工具拖慢,这样可以提升开发者的工作效率。服务的启动速度也比大型的单体应用快得多,千万别小看这一点,快速启动的服务会提高效率,加速研发(提高调试、部署等环节的效率) 。
服务可以
独立扩展 ,不论是采用X 轴扩展的实例克隆,还是Z 轴扩展的流量分区方式。
此外,每个服务都可以部署在适合它们需求的
硬件之上
。这跟使用单体架构的部署和硬件选择是迥然不同的:单体应用中组件对硬件的需求不同(例如有些组件是CPU运算密集型的,有些可能需要更多的内存空间),但是这些组件仍旧必须被部署在一起。
微服务架构也可以实现更好的
故障隔离 。例如,某个服务中的内存泄漏不会影响其他服
务。其他服务仍旧可以正常地响应请求。相比之下,单体架构中的一个故障组件往往会拖垮整个系统。
最后,微服务架构可以
消除 对某项技术栈的长期依赖。原则上, 当开发一个新的服务
时,开发者可以自由选择适用于这个服务的任何语言和框架。当然,很多公司对此往往有各种限制和规范, 但重要的是团队有了选择的权利,而不是被之前选定的技术绑架。
更进一步,因为服务都相对比较小,使用更好的编程语言和技术来重写一项服务变得有
可能
。
这也意味
着
,如果对
一
项新技术的尝试以
失
败而告终,我们可以
直
接丢弃这部分工作
而不至于给整个应用带来失败的风险
。
这跟单体架构是完全不同的,单体架构之下的技术选
型会严重限制后期新技术的尝试
。
当然,没有一项技术可以被称为
"银弹" (
银弹(Silver Bullet) , 指由纯银制作的子弹,往往被描绘成针对狼人等超自然怪物的特效武器)。微服务架构也存在一些
显著的弊端和问题
。不必被这些弊端和问题吓倒,我会在后面文章把它们逐一解决。
服务的拆分和定义是一项挑战。
分布式系统带来的各种复杂性,使开发、测试和部署变得更困难。
当部署跨越多个服务的功能时需要谨慎地协调更多开发团队。
开发者需要思考到底应该在应用的什么阶段使用微服务架构。
采用微服务架构首当其冲的问题,就是根本没有一个具体的、良好定义的算法可以完成
服务的
拆分工作
。
与软件开发一样,服务的拆分和定义更像是一门艺术。更糟糕的是,如果对系统的服务拆分出现了偏差,你很有可能会构建出一个分布式的单体应用:一个包含了一大堆互相之间紧耦合的服务,却又必须部署在一起的所谓分布式系统。这将会把单体架构和微服务架构两者的弊端集于一身。
使用微服务架构的另一个问题是开发人员必须处理创建分布式系统的
额外复杂性 。服务
必须使用进程间通信机制。这比简单的方法调用更复杂。此外,必须设计服务来处理局部故障, 并处理远程服务不可用或出现高延迟的各种情况。
实现跨多个服务的用例需要使用
不熟悉的技术 。每个服务都有自己的数据库,这使得实
现跨服务的事务和查询成为一项挑战。在后面【使用Saga管理事务】相关文章中会说到,基于微服务的应用程序必须使用所谓的Saga来维护服务之间的数据一致性。后面【在微服务架构中实现查询】相关文章中将解释基于微服务的应用程序无法使用简单查询从多个服务中检索数据。相反,它必须使用API 组合或CQRS视图实现查询。
IDE 等开发工具都是为单体应用设计的,它们并不具备开发分布式应用所需要的特定功
能支持。编写包含多项服务在内的
自动化测试
也是很令人头疼的工作。这些都是跟微服务架构直接相关的问题。因此,团队中的开发人员必须具备先进的软件开发和交付技能才能成功使用微服务。
微服务架构还引入了显著的
运维复杂性 。必须在生产环境中管理更多活动组件:不同类
型服务的多个实例。要成功部署微服务,需要高度自动化的基础设施,必须使用以下技术:
自动化部署工具,例如Netflix Spinnaker 。
产品化的PaaS 平台,例如Pivotal Cloud Foundry 或Red Hat OpenSh巾。
Docker 容器编排平台,例如Docker Swarm 或Kubernetes 。
我会在后面【部署微服务应用】相关文章中详细介绍这些部署相关的技术。
当部署跨越多个服务的功能时需要谨慎地协调更多开发团队
使用微服务架构的另外一项挑战在于当部署跨越多个服务的功能时需要谨慎地
协调更多
开发团队。必须制定一个发布计划,把服务按照依赖关系进行排序。这跟单体架构下批量部署多个组件的方式截然不同。
使用微服务架构的另一个问题是决定在应用程序生命周期的哪个阶段开始
使用这种架构
。在开发应用程序的第一个版本时,你通常不会遇到需要微服务架构才能解决的问题。此外,使用精心设计的分布式架构将减缓开发速度。这对初创公司来说可能是得不偿失的,其中最大的问题通常是在
快速发展业务模型和维护一个优雅的应用架构
之间的取舍。微服务架构使得项目开始阶段的快速迭代变得非常困难。初创公司几乎肯定应该从单体的应用程序开始(
特别是在开发MVP 场景时,初创公司的初版应用程序是用来获取市场或投资人的反馈、进行快速试错
的, 这个阶段不应花费太多时间在微服务架构这样的事情上)。
但是稍后,当问题变为如何处理复杂性时,那就是将应用程序功能性地分解为一组服务
的时候了
。
由于盘根错节的依赖关系,你会发现
重
构很困难
。后面【微服务架构的重构策略】相关文章中
讨论将单体应
用程序重构为微服务的策略
。
正如你所见,微服务是一把好处和弊端共存的双刃剑。正是因为这些困难,采用微服务
架构是一个需要认真思考的决策。然而,类似面向消费者的Web应用程序或者Saas类的复杂应用程序,微服务架构往往都是它们的正确选择。
著名的网站,
例如eBay(这个PPT 介绍了eBay 的架构转型历程:https://www. slideshare.net/RandyShoup/the-ebay-architecture-striking-a-balance-between-site-stability-feature-velocity-performance-and-cost)、Amazon.com、Groupon 和Gilt都是从单体应用逐步完成了向微服务架构的演化。
在使用微服务架构时, 一些问题无法回避,必须得到解决。每个问题都可能存在多种解
决办法,同时伴随
着
各种权衡和取舍
。
并没有一个完美的解决方案
。
为了帮助你更好地选型
和使用微服务架构,Chris创建了一套微服务架构的模式语言(Chris 维护的个人网站www.microservies .io介绍了这些模式的细节)
。后面文章将
反复提到这套模式语
言。下一篇文章
先来看看到底什么是模式语言,以及为什么
它这么有用
。