微服务架构发展到现在,其技术栈已经非常成熟,而且门槛越来越低,大家的接受度越来越高,掌握微服务开发,已经成了新生代工程师们的标配技能。但同时我们也要看到,很多公司在实施微服务时,仍然会出现各式各样的问题,纯技术问题这里不再讨论,更多的是理解和判断上的问题(当然,肯定都是Leader们的锅),我尝试从业务/技术、组织这两个方面来阐述下我的一些思考和浅见。
插播解释下,我为什么把【业务/技术】看成一类问题,原因就在于:产品微服务化的目的是为了业务的发展,技术本质上是业务倒逼才需要发展的,这应该成为大家的共识,否则微服务化的方向可能就错了。
我认为:微服务化的时机,取决于业务和组织的发展情况。
1. 业务发展到一定规模,会给系统带来更大的压力,从而持续影响性能、稳定性、资源利用、平台化、产品迭代速度等问题。下面先从这几个问题开始说起,大家会看到,拆分时机不在于“是否影响”,而在于“如何影响”及“影响程度”,不要被几个简单的词汇蒙蔽了,凡是都有正方面,最终要靠大家自己判断。
性能方面,主要是指单体本身由于资源受限而产生的性能瓶颈,垂直拆分+水平扩展可以将压力分散出去,这个是拆分驱动力之一。我们同时也要知道,在单体资源不受限的情况下,实际上性能可能会更好,因为它省去了进程间通信的开销。并且,很多性能问题不是出现在代码层,而是数据层,比如单表太膨胀、(多表)查询太疯狂等等,这个是使用单纯的微服务框架解决不了的,此时应该首先引入对数据层的重构,比如分库分表。当然,这也是不容易的。依我看来,分库这个动作本身就包含了对服务拆分的思考,因为在微服务的定义里面,其重要特征之一就是数据独立自治,所以在分库设计阶段,其实就已经要开始做微服务的规划了。无论怎样,在单体中先做数据层的拆分优化,总比直接上全套微服务方案要稳妥很多。而一旦系统承载突破了单体本身的能力极限,再去实施微服务化,会简单很多。
稳定性方面,单体的问题在于当一个实例挂了之后,没有后续实例补上,而且一旦挂了,整个服务都不可用。而微服务刚好可以解决这个问题。但是,微服务的稳定性很多时候也会出问题,比如说当依赖层次过多,中途一旦有故障产生,或者网络有明显抖动,整个服务的稳定性也会大打折扣。
资源利用方面,这一块容易让人忽略。在系统中,有的功能是耗内存,有的耗硬盘,有的耗CPU,假如放在一个大单体里面,即使能做到一定的水平扩展,也不能个性化定制服务器环境,造成资源浪费。假如这些服务能够拆开,那么可以分别使用内存型、高性能磁盘型(比如SSD)、高性能多核型机器,各尽其用。总体来讲,拆分是能带来资源利用上的收益的,只不过,假如仅仅为了这点收益就要做拆分,很明显也是不合理。
平台化方面,在业务早期并不是个问题(虽然大家都号称平台),但是假如产品持续发展,它就会开始有对外输出、赋能的能力及动力,比如说,有一天某外部合作方希望能借助你的某API做数据或流量上的合作,此时你能否快速提供安全可靠的OpenAPI?这个是单体系统无法(而且不能)提供的,其实可以作为拆分的重要依据之一。
产品迭代速度方面,在很长一段时间内,单体的开发速度肯定高于微服务的开发速度,只不过当产品变得越来越大了之后,再继续堆新功能就会比较麻烦,原因有二:工程代码的臃肿、开发人员的增多,这会导致项目管理很难进行,牵一发而动全身,产品迭代速度自然跟不上(Bug也会更多)。而拆分成微服务,理想情况下,每个服务都有维护更新者,大家增减功能或者bugfix时都不用战战兢兢如履薄冰了。不过,事情都有两面性,微服务架构必然伴随着组织架构的调整,每个微服务都最好有独立团队,这在实际操作中会利弊都会存在,下面会提到。
2. 团队(组织)发展到一定规模,人效管理模式会产生变化,需要解决协作效率的问题。
首先要明确的是,当一个产品不断发展时,我们一般会假设研发人员的数量也会有相应增长,当一个大团队面对一个大产品时,肯定会有很多分工,否则管理起来会比较麻烦,协作效率也会变低。一般情况下,我们仍然会按照职能子部门的方式来划分团队,比如产品部、运维部、测试部、架构部,分的再细一点,可能还有前端组、APP组等等,然后再划分一个跨职能的项目开发组。假如只有一个产品,这种职能型组织是可以良好运行的,每个工程师做双向汇报:职能Leader和项目组Leader,考核由职能Leader来做。但假如涉及到多个产品线的,职能Leader的管理复杂度就会很大了(跨多个项目),此时管理权、考核权交给项目组Leader会更好点,那前者要架空吗?依我看来,前者完全可以作为某专业方向的考核官,甚至是学学现在很多公司在做的“技术委员会”,负责专业方向的职级晋升,为了体现“技术服务于产品业务”的理念,它们的考评需要依赖项目组Leader的意见。
说了这么多,和微服务的拆分时机有什么关系呢?原因是微服务架构带来的组织架构,也有上面的问题,一个项目组或者产品线团队,某种程度上和一个微服务小团队并没有太大的不同。
大部分时候,我们拆分微服务的时机以系统/技术为主,重点解决系统本身的问题,但实际上【团队(组织)的管理模式能否进行有效调整】也是非常重要的。人员/组织结构跟不上,微服务化之后的管理也会显得力不从心。一个合理的微服务团队应该是包括开发、测试、运维为一体的综合性小团队(两个披萨原则),假如微服务过多,要考虑人员是否足够应付每个服务的管理工作。而且由于大家习惯了职能部门的管理方式(比如研发、测试、运维属于研发线子部门),可能一时半会儿不一定能转型到微服务小团队上来。
上面列出了团队(组织)在产品发展过程中,可能会遇到的一些问题,此时我们要拷问下自己:团队是否已经到达了转型的节点,目前是否有能力迅速完成转型?
所以综合来讲,业务发展的带来的系统/技术问题,以及组织发展带来的管理问题,是我们是否应该真正马上推进微服务化的重要参考依据(时机)。这里要说明的是:上面任何一个单独的【问题】,都不能完全构成实施微服务化的依据,笔者在这里只是罗列出了大家需要参考的点,也同时指明了某些问题背后,事情存在的两面性,最终需要大家自己斟酌。很多时候,你认为是技术问题,实际上并不一定是!
最后,来点真诚的劝告:新系统最好从单体开始,不过可以预先做点微服务的准备工作。
对于大部分中小系统来讲,单体仍然是第一选择,原因在于:新系统在业务逻辑上往往存在很多不确定性,过早的讨论服务的拆分不利于系统的快速上线,假如在业务逻辑没有完全清晰的情况下贸然拆分,甚至会带来很多不必要的麻烦,比如业务逻辑变化导致功能重构。而假如趟过了一遍单体并成功上线后,你会对如何进行拆分有了更好的判断,剩下的,就看你对这个遗留单体系统的改造信心了(笑)。
当然,做事情不能全凭信心,即使我们在最初选择单体架构,也仍然可以做很多微服务的准备工作。比如说,在涉及到应用内的共享变量时,优先使用独立的缓存系统,而不是用静态变量,在涉及到对公共资源的锁机制时,优先使用分布式锁,而不是代码级别的synchronized/lock。这样,该单体可以在一定程度上进行水平扩展。当需要真的的进行服务拆分时,这些业务逻辑也可以尽可能的复用代码(比如拷贝它们进入它该存在的服务里面)。