本文是读微服务(翻译链接)的笔记。

微服务与单块应用的对比

单块应用:一个单块应用系统是以一个单个单元的方式来构建的。企业应用系统经常包含三个主要部分:客户端用户界面、数据库和服务端应用系统。客户端用户界面包括HTML页面和运行在用户机器的浏览器中的JavaScript。数据库中包括许多表,这些表被插入一个公共的且通常为关系型的数据库管理系统中。这个服务端的应用系统就是一个单块应用——一个单个可执行的逻辑程序。对于该系统的任何改变,都会涉及构建和部署上述服务端应用系统的一个新版本。

微服务:以构建一组小型服务的方式来构建应用系统。除了这些服务能被独立地部署和扩展,每一个服务还能提供一个稳固的模块边界,甚至能允许使用不同的编程语言来编写不同的服务。这些服务也能被不同的团队来管理。

6401

微服务架构的九大特性

微服务风格还未被正式的定义,但是也总结了微服务架构的共性。这些共性并不是所有的微服务架构都完全具备,但期望大多数微服务架构都具备这些共性中的大多数特性。

特性一:“组件化”与“多服务”

组件化,就是将一堆组件结合在一起就可以构建成一个系统。

什么是组件?我们的定义是,一个组件就是一个可以独立更换和升级的软件单元。

我们将软件库(libraries)定义为这样的组件,即它能被链接到一段程序,且能通过内存中的函数来进行调用。然而,服务(services)是进程外的组件,它们通过诸如web service请求或远程过程调用这样的机制来进行通信。

由于服务可以独立部署,所以使用服务的方式来实现组件化。

如果一个应用系统由在单个进程中的多个软件库所组成,那么对任一组件做一处修改,都不得不重新部署整个应用系统。但是如果该应用系统被分解为多个服务,那么对于一个服务的多处修改,仅需要重新部署这一个服务。

通过多服务的方式来构建系统也有不足之处,比起进程内调用,远程调用更加昂贵。所以远程调用API接口必须是粗粒度的,而这往往更加难以使用。如果需要修改组件间的职责分配,那么当跨越进程边界时,这种组件行为的改动会更加难以实现。

特性二:围绕“业务功能”组织团队

任何设计(广义上的)系统的组织,都会产生这样一个设计,即该设计的结构与该组织的沟通结构相一致。

——梅尔文•康威(Melvyn Conway), 1967年

根据康威定律,当面对一个大型的应用系统时,管理层会根据目前的组织架构来分解系统:前端团队负责用户界面,后端团队负责后端服务,数据库团队负责数据库运维,一个根据组织架构而产生的设计架构应运而生——又一个单体怪物的雏形开始孕育。

微服务使用不同的方法来分解系统,即根据业务功能(business capability)来将系统分解为若干服务。这些服务针对该业务领域提供多层次广泛的软件实现,包括用户界面、持久性存储以及任何对外的协作性操作。因此,团队是跨职能的,它拥有软件开发所需的全方位的技能:用户体验、数据库和项目管理。

特性三:“做产品”而不是“做项目”

传统 开发模式是项目模式:目标是交付某一块软件,之后就认为完工了。一旦完工后,软件就被移交给维护团队,接着那个构建该软件的项目团队就会被解散。

微服务的支持者们倾向于避免使用上述模型,而宁愿采纳“一个团队在一个产品的整个生命周期中都应该保持对其拥有”这样的理念。通常认为这一点源自亚马逊的“谁构建,谁运行”的理念,即一个开发团队对一个在生产环境下运行的软件负全责。这会使开发人员每天都会关注软件是如何在生产环境下运行的,并且增进他们与用户的联系,因为他们必须承担某些支持工作。

特性四:“智能端点”与“傻瓜管道”

微服务需要在不同的进程间建立通信,一般采用智能端点(smart endpoints)和傻瓜管道(dumb pipes)。

微服务构建的应用都尽可能的实现一个目标:高内聚和低耦合。微服务内部拥有独立而完整的业务逻辑,微服务之间像管道(Pipe)那样传递消息流。这种模式就像经典的Unix系统上过滤器(filter)的工作机制,接收请求,按照业务逻辑进行处理,最后产生响应消息。

智能端点就是指拥有独立而完整的业务逻辑的微服务,它们从管道上获取消息,进行智能处理,然后产生处理后的消息,放回管道。

傻瓜管道就是指连接微服务进行消息传递的通信机制,它们只负责消息流的传送,不承载更多的关于业务逻辑上的分析和处理。

将一个单块系统改造为若干微服务的最大问题,在于对通信模式的改变。仅仅将内存中的方法调用转换为RPC调用这样天真的做法,会导致微服务之间产生繁琐的通信,使得系统表现变糟。取而代之的是,需要用更粗粒度的协议来替代细粒度的服务间通信。

特性五:“去中心化”地治理技术

使用中心化的方式对开发进行治理,其中一个后果,就是趋向于在单一技术平台上制定标准。不同的问题有不同的解决方案。

如果能将单块应用的那些组件拆分成多个服务,那么在构建每个服务时,就可以有选择不同技术栈的机会。

特性六:“去中心化”地管理数据

传统的应用系统使用一个中心的数据库来管理数据,这样方便事务操作,可以保证数据的一致性。

微服务主张去中心化的来部署数据库,也就是让每一个服务来管理自己的数据库。但这样部署数据库的话,对一致性将是一个很大的挑战,通常情况下,为了快速响应需求,只能一定程度上让数据“非一致性”,来通过做某种反向过程进行错误处理。只要修复错误的成本,与在保持更大的数据一致性却导致丢了生意所产生的成本相比,前者更低,那么这种“非一致性”地管理数据的权衡就是值得的。

641

特性七:“基础设施”自动化

微服务与自动化技术密不可分,云的演进,特别是AWS的发展,已经降低了构建、部署和运维微服务的操作复杂性。

采用微服务的架构,意味着可能有几十上百的服务被划分出来,相对于之前的单体应用来说,微服务系统在构建、部署和运维上要复杂的多,单靠人工操作,将会很麻烦。

自动化部署的流水线:

642

特性八:“容错”设计

使用各个微服务来替代组件,其结果是各个应用程序需要设计成能够容忍这些服务所出现的故障。如果服务提供方不可用,那么任何对该服务的调用都会出现故障。

因为各个服务可以在任何时候发生故障,所以下面两件事就变得很重要,即能够快速地检测出故障,而且在可能的情况下能够自动恢复服务。

那当服务提供方不可用时,客户端如何优雅的应对这种情况?

具体的应对措施有以下几种:

  1. 网络超时:当等待响应时,不要无限期的阻塞,而是采用超时策略。使用超时策略可以确保资源不会无限期的占用。
  2. 限制请求的次数:可以为客户端对某特定服务的请求设置一个访问上限。如果请求已达上限,就要立刻终止请求服务。
  3. 断路器模式:记录成功和失败请求的数量。如果失效率超过一个阈值,触发断路器使得后续的请求立刻失败。如果大量的请求失败,就可能是这个服务不可用,再发请求也无意义。在一个失效期后,客户端可以再试,如果成功,关闭此断路器。
  4. 提供回滚:当一个请求失败后可以进行回滚逻辑。例如,返回缓存数据或者一个系统默认值。

特性九:“演进式”设计

那些微服务的从业者们,通常具有演进式设计的背景,而且通常将服务的分解,视作一个额外的工具,来让应用开发人员能够控制应用系统中的变化,而无须减少变化的发生。

从一个单块系统作为起点,保持其模块化,当这个单块系统达到一定的规模,开始出现问题后,再将其拆分成微服务,是一个不错的开始。

当然,在系统演化的过程中,我们要考虑模块化和组件化,这是走向微服务之路的必要保证。一个组件的关键属性,是具有独立更换和升级的特点,想象一下,能够在一个点上重写该组件,而无须影响该组件的其它合作组件,是一个考虑组件是否独立更换和升级的好方法。