1.2 拆分服务

微服务是在单体服务发展壮大后提出来的,要提供微服务,遇到的首要问题便是如何拆分服务。

1.2.1 分而治之以降低复杂性

软件行业一直致力于降低复杂性。人们想出来的方法大致都是分而治之,分的方法要么纵向切(分层),要么横向切(分块)。

1.分层

分层方法最有名的例子就是OSI的网络协议,它有效地分离了复杂性,下层为上层服务,上层调用下层的接口,开发者只需关注所在层的细节。应用程序中最典型的分层如表1-1所示。

表1-1 应用程序分层

微服务在整个应用中可能位于不同层次,但它自己是自成一体的,其内部会有一些层次划分。

2.分块

分层的好处显而易见,坏处则在于随着层次的增多,层次之间的通信成本也会加大,复杂性贯穿于各层之间,依赖性层层传递,有一层出了问题,整个服务就会受到影响。因此出现了分块的方法。

在现实生活中,有的公司在做大做强之后,原有的组织架构不堪重负,纷纷建立了相对独立的事业部或分公司,彼此之间通过简单的契约或合同进行协作,层的概念依然存在,只是范围更小,层次也更少。例如,一家贸易公司从事服装生意,刚开始有4个职能部门,足以应付日常工作,如图1-1所示。

图1-1 服装贸易公司分块前的组织架构

在公司生意做大(例如服务范围扩展到销售箱包和体育用品)之后,有必要进行组织架构升级,保留财务部,再划分3个事业部,对3块业务分别进行相对独立的管理,如图1-2所示。

图1-2 服装贸易公司分块后的组织架构

分块的好处显然易见,每一块只聚焦于自己的业务,分散了风险,提高了效率。可是各个事业部之间的沟通以及各职能部门之间的协作渠道增多,沟通成本增加,可能会出现问题,所以要建立明确、简单的沟通渠道。

软件服务在分块时要注重以下两点。

(1)划分好服务边界

一个服务本身应该相对独立,具有一定的自治性,实现一个相对完整的功能或者提供独特的数据,尽量避免对于其他服务的强依赖。例如,订单服务与库存服务,它们都可独立地提供服务,但是彼此也存在着联系:对于订单服务,必须考虑是否有足够的库存;对于库存服务,要根据订单的增减调整库存量。

(2)定义好服务接口

我们要定义好服务的接口。SOA(Service Oriented Architecture,面向服务的架构)的理念已经提出好多年了,一直不温不火,原因就在于其接口通信的SOAP、ESB等技术太复杂,并未得到广泛应用。但是它的思想和微服务一脉相承,那就是各个服务提供统一的接口,开放自己的服务,通过服务之间的相互调用、互连互通、共同协作,一起实现相应的业务功能。

1.2.2 分而用之以提高可重用性

共享和重用是软件行业得以壮大的秘诀之一,“罗马不是一天建成的”,今天的软件也不是每一行代码都是由一个开发者写的。

提高软件的可重用性需要适当地抽象、封装,提供简单的接口供多方调用。调用的方法无非是进程内调用和进程间调用,其中进程内的调用可以是函数调用或事件传递,进程间的调用取决于进程间的通信方式,如管道、信号、共享存储消息等。

微服务有利于可重用,它属于进程间的重用方式,与调用方既可以位于同一台服务器上,也可以位于不同地域。因其粒度微小,故可重用度高。它对外提供统一的API接口给调用方,相比单体系统中提供一个统一的接口和函数,重用的粒度更大,也更便于调用者使用自己喜欢的方式重用,这样更加灵活。

Web Service用得最多的是HTTP RESTful消息,消息格式多为JSON或XML。其他类型的微服务也以其他方式提供不同类型的服务,比如,基于TCP或UDP的SIP消息、XMPP消息,以及二进制的PDU(Protocol Data Unit,协议数据单元)。

1.2.3 分而做之以提高开发效率

现代的软件项目通常要由多人或多个团队协作完成,如果彼此之间互相依赖,联系过于紧密,牵一发而动全身,那么团队之间花在沟通、讨论和集成测试上的时间将难以估量。就如康威定律中提到的:“设计系统的架构受制于产生这些设计的组织的沟通结构”。如果把一个产品交由几个团队来做,那么应该把功能相对完整和独立的一个或一组服务交由一个团队来开发,团队之间定义好清晰的服务接口,然后各自进行开发和部署。只要服务的接口不改变,就完全可以做到独立实现、部署和升级。

所以我们强调服务要微小,并且相对独立自治,是一个比较完整的功能单元,服务内部高内聚,服务之间低耦合。