微服务的前身是 Peter Rodgers 博士在 2005 年度云端运算博览会上提出的微 Web 服务 (Micro-Web-Service) 。微软的 Juval Löwy 随后也提出了类似的想法,并提议将其作为微软下一阶段最主要的软件架构。
2014年,Martin Fowler 与 James Lewis 共同提出了微服务的概念,给出了微服务的具体定义:从本质上来说,微服务是一种架构模式。它是面向服务型架构(SOA)的一种变体,提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。每个服务运行在其独立的进程中,服务与服务之间采用轻量级的通信机制互相沟通(通常是基于 HTTP 的 RESTful API)。每个服务都围绕着具体业务进行构建,并且能够被独立地部署到生产环境、类生产环境等。另外,应尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具对其进行构建。
Martin Fowler 是国际著名的软件专家,敏捷开发方法的创始人之一,现为 ThoughtWorks 公司的首席科学家。在面向对象分析设计、UML、模式、软件开发方法学、XP、重构等方面,都扮演着举足轻重的开创者角色。早在20世纪80年代,Fowler 就是使用对象技术构建多层企业应用的倡导者,他著有几本经典书籍: 《企业应用架构模式》、《UML精粹》和《重构》等。
与微服务架构相对应,传统开发方式通常被称为单体式架构(Monolithic Architecture)。所有功能都打包在一起,基本没有外部依赖,其中包含了数据输入/输出、数据处理、业务实现、错误处理、前端显示等所有逻辑。
下图显示的一个典型的单体式架构示意图:
这种架构有其优点,包括:
但是,随着现代应用程序的日益复杂化,加上对于迭代速度的要求越来越高,这种架构的不足开始暴露出来:
如何解决这些问题?微服务架构逐渐浮出水面。从软件开发的组织上来说,它的核心理念是按照业务边界把整个系统划分为若干个“子系统”。每个子系统的开发团队之间,保持着合作(Inter-Operate)而不是整合(Intergrate)的关系。定义好每个子系统的边界和接口,在一个团队内自治。团队按照这样的方式组建,沟通的成本维持在系统内部,每个子系统就会更加内聚,彼此的依赖耦合能变弱,跨系统的沟通成本也就能降低。
这里不得不提及著名的“康威定律”(Conway's Law),这是微服务架构的一个核心理念。
Melvin Conway 在1967年提出了这个理念,原文是:“Organizations which design systems are constrained to produce designs which are copies of the communication structures of these organizations.”
用简单的话来说,就是组织形式等同于系统设计,组织的沟通方式会通过系统设计表现出来。下面这幅著名的软件企业组织图,与这些企业的产品架构有着异曲同工的对应关系。
再以上面提到的单体式 App 为例,通过用微服务架构方式对其进行改造,将会变成下面这种结构:
除了解决单体式架构的几个缺陷以外,微服务架构还具有下面这些优点:
当然也需要提到,微服务架构也存在着它的不足:
DevOps(Development 和 Operations 的组合词)是一种重视软件开发人员和 IT 运维技术人员之间沟通合作的文化、流程或者实践方式。透过完全自动的“软件交付”和“架构变更”流程,使得构建、测试、发布软件更加快捷、频繁和可靠。本课程将不单独介绍这方面的内容,以后可能会单独开课。
介绍完微服务架构以后,回到本课程的主题上来:对于测试人员而言,微服务架构到底有什么特点呢?我把它归结为以下几点:
1.每个服务承担一定的职责:“尽可能小,但是又达到必要的规模(as small as possible but as big as necessary)” 。
在问答网站 Quora 上,有一个著名的问题:什么是程序员觉得最浪费时间的事情?排名第一的回答中提到:“不必要的微服务。”
这句话揭示了开发团队在转向微服务架构时经常走入的误区。“微”固然重要,但是首要的是提供“服务”,这才构成“微服务”的价值。盲目地切分功能(Feature),却没有起到解耦合的作用,只是会增加维护、测试的成本。毕竟,多一项服务,就会多出一系列的流水线和测试要求。因此,测试、质量人员在面临团队计划采取微服务架构的决策时,必须要敢于质疑:是否有这样做的必要?目的是让决策人员意识到这种转型的潜在成本,避免花无用功。
2.微服务之间通常通过 Rest over HTTP 连接。
最常见的连接/交互方式,即通过 POST、GET、PUT、DELETE 这些命令操作 API,通过 JSON 传递参数。以下面这个典型的制造型企业的运营系统为例。在从单体式架构转为微服务之后,不同功能模块之间将通过 Rest 方式互相访问。
这种简易、明确的交互方式为契约测试(Contract Test)提供了基础,本课程的第七课《契约测试入门》将详细介绍这方面的内容。
3.每种服务不一定提供用户界面。
这意味着每种服务的测试,并不一定能够或者需要从 UI 完成。这对 API 级别的集成化测试提出了要求。本达人课的第四课《怎么针对微服务架构做集成测试?》将具体介绍如何进行集成化测试。
4.微服务通常还可以划分为更小的模块。
如下图所示,一个典型的微服务可以分为这几个模块:资源、业务逻辑、数据存储接口、外部通信接口等。
这意味着,在对微服务架构进行测试时,可以从不同的模块着手,进行相应的模块测试。本达人课的第五课《模块测试详解》将带您了解如何切分模块和执行相应的自动化测试。
简单总结一下本课程所学习的内容: