1. 前言
1.1 微服务目的
有效地拆分应用,实现敏捷开发和部署,最终的目标是实现敏捷开发和部署,实现的方式是围绕业务能力*有效地拆分应用*。 微服务就是从各种角度,包括组织的、技术的等来阐释怎样有效地拆分应用,相对于其他拆分应用的方式,例如六边形架构、12-Factor以及《The art of scalability》涉及的方面更多。
1.2 微服务定义
微服务架构即是采用一组小服务来构建应用的方法。 每个服务运行在独立的进程中,不同服务通过一些轻量级交互机制来通信, 例如 RPC、HTTP 等。 服务围绕业务能力来构建,并依赖自动部署机制来独立部署。
虽然勾勒出了微服务的一些关键概念:小、独立进程、自动化,但是这样的定义还是太抽象,太务虚,很难落地。一解释以为懂了,一问还是不知道,一讨论就打架。换句话说,就是*道可道,非常道*。
从Martin作为ThoughtWorks公司的首席科学家的角度来看,他把微服务“炒”起来了,如果像12-Factor写得这样具体实在,那咨询业务还怎么开展呢。
相比于Martin的文章,Chris Richardson的文章microservices.io就要具体多了,它从更多角度来阐释了微服务。
1.3 微服务起源
早在 1994 年 Mike Gancarz 曾提出了 9 条著名原则,其中前 4 条和微服务架构理念特别接近。微服务就像把 UNIX 哲学应用到了分布式系统。
- Small is beautiful.
- Make each program do one thing well.
- Build a prototype as soon as possible.
- Choose portability over efficiency.
翻译成中文:
1. 小即是美:小的服务,代码少,bug 也少,易测试,易维护,也更容易不断迭代完善。
2. 一个程序只做好一件事:一个服务也只需要做好一件事。
3. 尽可能早地创建原型:尽可能早的提供服务 API,建立服务契约,达成服务间沟通的一致性约定,
至于实现和完善可以慢慢再做。
4. 可移植性比效率更重要:服务间的交互协议在效率和可移植性二者间,首要考虑移植性。
可见微服务其实不是凭空产生的,它自有其历史渊源。而在微服务之前的十年,大家经常谈论的是一个叫 SOA(面向服务)的架构模式,它和微服务又是什么关系?在 Sam Newman 的《Building Microservices》一书中,作者对 SOA 和 Micorservices 的区别给出了定义:
You should instead think of Microservices as a specific approach for SOA in the same way that XP or Scrum are specific approaches for Agile software development.
就像认为 XP 或者 Scrum 是敏捷软件开发的一种特定方法一样, 你也可以认为微服务架构是 SOA 的一种特定方法。
面向服务架构(SOA)的概念已有十多年,它提出了一种架构设计思想, 但没有给出标准的参考实现,而早期企业软件业界自己摸索了一套实践方式 —— 企业服务总线(ESB)。 但历史证明 ESB 的实现方案甚至在传统企业软件行业也未取得成功,Martin Fowler 在文中说正是因为 ESB 当年搞砸了很多项目, 投入几百万美金,产出几乎为零,因此 SOA 这个概念也蒙上了不详的标签,所以当微服务架构出现时, 其拥护者开始拒绝使用包裹着失败阴影的 SOA 这个标签,而直接称其为微服务架构(Microservices Architecture Style), 让人以为是一套全新的架构思想,但事实上它的本质依然是 SOA 的一种实践方式。
2. 特征
每个人对微服务都可以有自己的理解,不过大概的标准还是有一些的。
- 分布式服务组成系统
- 按照业务而不是技术来划分组织
- 做有生命的产品而不是项目
- 智能终端与哑管道
- 去中心化
- 自动化运维(DevOps)
- 容错
- 快速演化
微服务架构(MSA)带来一些复杂性,比如调用关系链以及网络调用隐含的性能问题。单个微服务不管从业务领域方面还是从性能方面来说都很简单,易于理解。但如果是一群微服务,就不是这么回事了。微服务架构的优点只有在一定条件下才能得以体现,比如每个微服务对它们的数据具有独占所有权,或者有属于自己的数据库存储。
这是一种 能不共享就不共享 的架构模式,非常强调有边界的上下文。
API层作为服务接入层。 在客户和服务之间放置一个API层通常是个不错的主意,因为这个组件实质上构造了一个抽象层,使得客户不需要知道服务端的确切位置。
2.1 分布式服务组成系统
传统实现组件的方式是通过库(library),库是和应用一起运行在进程中,库的局部变化意味着整个应用的重新部署。 通过服务来实现组件,意味着将应用拆散为一系列的服务运行在不同的进程中,那么单一服务的局部变化只需重新部署对应的服务进程。
2.2 按照业务而不是技术来划分组织
直接理解就是:服务提供的能力和业务功能对应。 比如:订单服务和数据访问服务,前者反应了真实的订单相关业务,后者是一种技术抽象服务不反应真实的业务。所以按微服务架构理念来划分服务时,是不应该存在数据访问服务这样一个服务的。
更深一层,Melvin Conway 在 1967 年观察到一个现象并总结出了一条著名的康威定律
Organizations which design systems are constrained to produce designs
which are copies of the communication structures of these organizations.设计系统的组织,其产生的设计等同于组织之内、组织之间的沟通结构。
通俗的说法就是:组织形式等同系统设计。 看看下面的图片(来自互联网),再想想Apple的产品、微软的产品设计,就能形象生动的理解这句话。
就像六边形架构是微服务的理论基础之一一样,康威定律也是微服务架构的理论基础之一。
传统开发方式中,我们将工程师按技能专长分层为前端层、中间层、数据层,前端对应的角色为 UI、页面构建师等,中间层对应的角色为后端业务开发工程师,数据层对应着 DBA 等角色。 事实上传统应用设计架构的分层结构正反应了不同角色的沟通结构。所以若要按微服务的方式来构建应用,也需要对应调整团队的组织架构。每个服务背后的小团队的组织是跨功能的,包含实现业务所需的全面的技能。
2.3 做有生命的产品而不是项目
传统的应用开发都是基于项目模式的,开发团队根据一堆功能列表开发出一个软件应用并交付给客户后,该软件应用就进入维护模式,由另一个维护团队负责,开发团队的职责结束。 而微服务架构建议避免采用这种项目模式,更倾向于让开发团队负责整个产品的全部生命周期。Amazon 对此提出了一个观点:
You build it, you run it.
开发团队对软件在生产环境的运行负全部责任,让服务的开发者与服务的使用者(客户)形成每日的交流反馈,来自直接客户的反馈有助于开发者提升服务的品质。
2.4 智能终端与哑管道
微服务架构抛弃了 ESB 过度复杂的业务规则编排、消息路由等。 服务作为智能终端,所有的业务智能逻辑在服务内部处理,而服务间的通信尽可能的轻量化,不添加任何额外的业务规则。所以这里的智能终端是指服务本身,而哑管道是通信机制,可以是同步的 RPC,也可以是异步的 MQ,它们只作为消息通道,在传输过程中不会附加额外的业务智能。
2.5 去中心化
去中心化包含两层意思:
- 技术栈的去中心化。
- 数据去中心化。
每个服务面临的业务场景不同,可以针对性的选择合适的技术解决方案。但也需要避免过度多样化,结合团队实际情况来选择取舍,要是每个服务都用不同的语言的技术栈来实现,想想维护成本真够高的。
每个服务独享自身的数据存储设施(缓存,数据库等),不像传统应用共享一个缓存和数据库,这样有利于服务的独立性,隔离相关干扰。
2.6 自动化运维
无自动化不微服务,自动化包括测试和部署。单一进程的传统应用被拆分为一系列的多进程服务后,意味着开发、调试、测试、监控和部署的复杂度都会相应增大,必须要有合适的自动化基础设施来支持微服务架构模式,否则开发、运维成本将大大增加。
2.7 容错
著名的 Design For Failure 思想,微服务架构采用粗粒度的进程间通信,引入了额外的复杂性和需要处理的新问题,如网络延迟、消息格式、负载均衡和容错,忽略其中任何一点都属于对“分布式计算的误解”。
2.8 快速演化
一旦采用了微服务架构模式,那么在服务需要变更时我们要特别小心,服务提供者的变更可能引发服务消费者的兼容性破坏,时刻谨记保持服务契约(接口)的兼容性。一条普适的健壮性原则,伯斯塔尔法则,给出了很好的建议:
Be conservative in what you send, be liberal in what you accept.
发送时要保守,接收时要开放。
通俗的说法就是:***宽进严出
3. 实施
实施微服务架构,可以从下面一些维度来做全面考量。
3.1 建模
微服务只是从软件实现的结果说事,没有提供一套方法论来对复杂系统进行分解,从而得到一个个微服务。 依照服务围绕业务能力来构建的方式,DDD(Domain Driven Design)中的*BoundedContext*,它是针对复杂系统设计的一套软件工程方法:把系统分割为一个个有边界的上下文,正好契合了微服务的这一需求。 BoundedContext,有一个比喻比较贴切:“细胞之所以会存在,是因为细胞膜定义了什么在细胞内,什么在细胞外,并且确定了什么物质可以通过细胞膜。”
3.2 协作
采用微服务架构模式后,开发和运维的协作模式都会发生变化。 按微服务的组织方式,不同人或小团队负责一个或一组微服务,服务之间可能存在相互调用关系,所以在服务之间也完全采用了面向外部开放的契约化开发模式。 每一个服务都提供了一份契约文档,发布到公开的内部 wiki,方便服务干系人可自由获取查看。契约文档要求至少对服务的几个基本方面作出说明,如下:
- API,具体接口的 API 接入技术说明。
- 能力,服务能力的描述。
- 契约,提供这些能力所约定的一些限制条件说明。
- 版本,支持的最新和历史的版本说明。
使用契约文档来减少多余且可能反复重复的口头沟通,降低协作成本。
采用微服务后一个业务功能的调用会涉及多个服务间的协同工作,由于服务间都是跨进程的调用通信,一个业务功能的完成涉及的服务调用链条可能较长,这就涉及到服务间需遵循一些规则来确保协作的可靠性和可用性。我们采用的原则是:长链条的内部服务之间的调用异步化。若一个调用链条中的个别服务变慢或阻塞可能导致整个链条产生雪崩效应,采用异步化来规避调用阻塞等待导致的雪崩情形。
3.3 测试
测试从不同的维度可以划分,如下四个象限,四个象限从不同维度视角对测试做了观察和判断,从中可以看出除了体验和探索性测试需要人工介入,其他维度的测试都可以通过自动化来实现,以降低测试人工成本和重复性工作。
而从测试所处的层次,又可以得到下面这样个一个测试金字塔:
而微服务的测试,服务开发和运营人员专注于做好服务实现层面的单元测试和服务契约层面的接口测试。而面向业务功能的端到端测试,更多是依赖自动化脚本完成。而为了维护好这些自动化测试脚本,也需要保持服务接口和契约的兼容性和稳定性,这些自动化测试脚本也属于服务的消费方之一。
3.4 监控
大量松耦合的微服务通过相互协作来完成业务功能的流程处理,在这样一个复杂的生产环境中,出现异常或错误是很难迅速定位的。 对监控进行分层,顶层的监控站在用户视角,底层的监控站在系统视角,形成更完善的反馈链路。
Microservice 微服务的理论模型和现实路径 - mindwind - 博客园
微服务(Microservice)那点事-阿里云开发者社区