微服务特点

简单地说,微服务架构是一种以一些微服务来替代开发单个的大而全的应用的方法,每一个小服务都运行在自己的进程里,并以轻量级的机制(通常是 HTTP RESTful API)来通信。微服务强调 “小快灵”,任何一个相对独立的功能服务不再是一个模块,而是一个独立的服务。

举个例子,就是将以前的大兵团全功能的部队拆分成一个个专业化的小分队,各司其职,各自为战,彼此之间用清晰的接口通信。

类似于真实世界,以前推崇金字塔结构:从上到下,分层管理,都在一个大的系统(进程)里以内部事件或函数调用的方法进行分工协作。而当前更倾向于扁平化管理,分成若干个独立运作的事业部或小组,各自为战,却又以 API/RPC 的方式紧密合作,为一个或一些用户提供所需的产品和服务。

有一利就有一弊,以往一个程序有几十个组件,现在可能就变成了几十个微服务。那么这么多微服务该如何管理呢?

类似于真实世界,若干个小分队联合作战得由总参谋部协调,彼此之间职责明确、分工协作。在软件世界中就可以前端应用及 API gateway 来调用和协调所依赖的微服务,再加上服务注册(service registry)、服务发现(service discovery)等服务治理功能,依靠强大的度量和监控将多个微服务整合在一起。

就如 《人月神话》 的作者布鲁克斯所提到的 “没有银弹”,从来就没有包治百病的灵丹妙药,如果有人声称有,那他一定是个骗子。微服务的问题也不少,小分队多了,沟通成本就增加了,性能也可能会有所下降。

微服务架构的特点

Martin Fowler 在他的文章中总结了微服务的特点:

  • 围绕业务功能进行组织(organized around business capability),不再是以前的纵向切分,而改为按业务功能横向划分,一个微服务最好由一个小团队针对一个业务单元来构建。
  • 做产品而非做项目(product not project),不再是做完一个个项目,交付后就完工了,而是做产品,从设计编码到产品运维,做到全过程掌控和负责,即自己构建,自己运维(you build it,you run it)。
  • 智能终端加简单通道(smart endpoints and dumb pipe),使用基于资源的API,将大量逻辑放在客户端,而服务器端则着重于提供资源,推荐基于 Web 而不是在Web之后做复杂逻辑(be of the Web,not behind the Web)。
  • 去中心化管理(decentralized governance),自行其是,自我管理,不必在局限在一个系统里,不必围绕着一个中心。
  • 去中心化数据管理(decentralized data management),只管理和维护自己的数据,相互之间互不直接访问彼此的数据,只通过 API 来存取数据。
  • 基础设施自动化(infrastructure automation),每个微服务应该关注于自己的业务功能实现,基础设施应该尽量自动化——构建自动化、测试自动化、部署自动化、监控自动化。
  • 为应对失败而设计(design for failure),设计之初就要考虑高可靠性(high reliability)和灾难恢复(disaster recover),并考虑如何着手进行错误监测和错误诊断。
  • 演进式设计(evolutionary design),没有完美的架构,唯一不变的是变化。要善于应对变化,容易改变其设计和实现,因为其小,故而易变。

以上即为微服务的主要特点,除此之外,其他的一些非特征化的特点不再赘述。

微服务架构的特征

一个微服务的架构应该具有以下特征:

  • 容易被替换和升级。比如以前用 Ruby 快速开发的原型可以由用 Java 实现的微服务代替,因为服务接口没变,所以也没有什么影响。
  • 职责独立完整。按功能单元组织服务,职责最好相对独立和完整,以避免对其他服务有过多的依赖和交互。
  • 可选择最适合自己的技术方案。服务性质不同会影响技术选型,比如账户的注册和登录完全可以由 Ruby on Rails、 Python Django 这些脚本框架来实现。但是,对于音/视频流的编解码和处理,最好用 C/C++ 甚至汇编语言来写。其他的诸如数据库的选型、ORM 或 MVC 框架的选择,都可以随机应变,按照业务和技术的具体需求,根据团队的技术栈和人员现状选择最适合的方案。
  • 架构由层次化转向扁平化。服务内部可以进行适当的分层,服务之间尽量扁平化,不要引入过多的层次。

微服务架构的风格

微服务可以采用多种风格,但是一个 “生态系统” 内存最好遵从统一的风格和要求。微服务基本上都具有以下风格:

  • 短小精悍、独立自治:只做一个业务并专注地做好它。
  • 自动化部署和测试:相比大而全的单个服务,微服务会有更多的进程,更多的服务接口,更多不同的配置,如果不能将部署和测试自动化,微服务所带来的好处将会大大逊色。
  • 尽量减少运维的负担:微服务的增多可能会导致运维成本增加,监控和诊断故障也可能更困难,所以要未雨绸缪,在一开始的设计阶段,就要充分考虑如何及时地发现问题和解决问题。
  • 拥抱失效与故障:微服务的高可靠性设计和防错性设计是与生俱来的,分布在不同的机器、地域上的服务所用到的硬件和网络等随时可能出问题,而这些问题要对服务质量没有任何影响。

每个服务都是灵活易变、可伸缩、可扩展、可组合的:微服务为应对变化提供了更多的可能,就像乐高积木,可以随意增减组合,拼出不同的产品。

为什么需要微服务

逻辑清晰

这个特点是由微服务的单一职责的要求所带来的。一个仅负责一项很明确业务的微服务,在逻辑上肯定比一个复杂的系统更容易让人理解。

逻辑清晰带来的是微服务的可维护性,在我们对一个微服务进行修改时,能够更容易分析到这个修改到底会产生什么影响,从而通过完备的测试保证修改质量。

简化部署

在一个单块系统中,只要修改了一行代码,就需要对整个系统进行重新的构建、测试,然后将整个系统进行部署。而微服务则可以对一个微服务进行部署。

这样带来的一个好处是,我们可以更频繁的去更改我们的软件,通过很低的集成成本,快速的发布新的功能。

可扩展

应对系统业务增长的方法通常采用横向(Scale out)或纵向(Scale up)的方向进行扩展。分布式系统中通常要采用Scale out的方式进行扩展。因为不同的功能会面对不同的负荷变化,因此采用微服务的系统相对单块系统具备更好的可扩展性。

灵活组合

在微服务架构中,可以通过组合已有的微服务以达到功能重用的目的。

比如在示例中,如果我们要新增一个 Booking Service,在预订时可以直接重用 Account Service 和 Inventory Service 检查用户权限和库存情况。

技术异构

在一个大型系统中,不同的功能具有不同的特点,并且不同的团队可能具备不同的技术能力。因为微服务间松耦合,不同的微服务可以选择不同的技术栈进行开发。

同时,在应用新技术时,可以仅针对一个微服务进行快速改造,而不会影响系统中的其它微服务,有利于系统的演进。

比如在示例中,如果因为库存系统数据量变大,我们需要数据由当前的 sqlite 数据库修改为 MySQL,可以仅修改 Inventory Service,而不需要要求整个系统的数据库全部替换。

高可靠

微服务间独立部署,一个微服务的异常不会导致其它微服务同时异常。通过隔离、融断等技术可以避免极大的提升微服务的可靠性。

微服务的缺点

复杂度高

微服务间通过 REST、RPC 等形式交互,相对于 Monolithic 模式下的 API 形式,需要考虑被调用方故障、过载、消息丢失等各种异常情况,代码逻辑更加复杂。

对于微服务间的事务性操作,因为不同的微服务采用了不同的数据库,将无法利用数据库本身的事务机制保证一致性,需要引入二阶段提交等技术。

同时,在微服务间存在少部分共用功能但又无法提取成微服务时,各个微服务对于这部分功能通常需要重复开发,或至少要做代码复制,以避免微服务间的耦合,增加了开发成本。

运维复杂

在采用微服务架构时,系统由多个独立运行的微服务构成,需要一个设计良好的监控系统对各个微服务的运行状态进行监控。运维人员需要对系统有细致的了解才对够更好的运维系统。

影响性能

相对于 Monolithic 架构,微服务的间通过 REST、RPC 等形式进行交互,通信的时延会受到较大的影响。