微服务是银弹吗
微服务是近些年特别火热的一种架构设计理念,在各大互联网公司盛行的一种系统架构设计方式。以至于很多老铁在项目开发实践中,会不加思考的采用微服务,总觉得实施了微服务就可以把什么问题都解决了,而一旦真正实施后才会发现掉进了微服务的坑里,我们都知道微服务架构设计理念主要强调:small,lightweight,automated。也就是每个服务设计的尽量小,服务更加轻量级和服务的自动化管理。然而在微服务实践过程中,仍然可能面临一些问题:
1.服务划分的过细,服务间关系复杂
服务划分的过细,单个服务的复杂度确实下降了,但整个系统的复杂度却上升了,可以想象,每个服务的功能越简单,实现同样的系统功能,需要的服务个数就会越多,服务间的交互也就变得越多。也就是说,微服务将系统内的复杂度转移为系统间的复杂度。
2.服务数量多,团队效率急剧下降
除此之外,很多时候,一个比较小的团队,却将一个系统拆分成几十个微服务,平均每个人多要维护5到10个微服务,这样做会给工作效率带来明显的影响,一个简单的需求开发就需要涉及多个微服务,光是微服务之间的接口就有6~7个,无论是设计,开发,测试,部署,都需要工程师在不同的服务之间切换。
3.服务调用链长,性能下降,问题定位困难
由于微服务之间通常采用http或者rpc的方式进行调用,每个调用都需要涉及到的网络开销,而且一次用户请求需要多个微服务系统处理,任意微服务故障都将导致整个业务失败。然而由于微服务数量较多,且故障存在扩散到现象,快速定位到底哪个微服务故障是一件十分复杂的事情。
4.没有自动化支撑,无法快速交付
如果没有相应的自动化系统支撑,都是靠人工操作,那么微服务不但达不到快速交付的目的,甚至还不如一个大而全的系统效率高。例如:没有自动化测试支撑,每次测试都需要测试大量接口。每次部署多个微服务,几十台机器,完全依靠手动部署,是十分繁琐,且容易出错的工作。
5.微服务多了,没有完善的服务治理 ,服务的管理变得十分混乱
对于服务的治理主要涉及三个方面:
服务路由:假设某个微服务60个节点,部署到20台机器上,那么依赖它的服务如何知道这个服务的部署情况呢,如何将调用传递到指定的节点上呢?
服务故障隔离:某个服务60个节点,其中5个节点发生了故障,依赖它的服务如何处理这种情况呢?
服务注册和发现:同样是上面的例子,现在如果决定将服务从60个节点扩容到80个节点,或者从60个节点缩减为40个节点,新增或者减少的节点,如何让依赖它的服务感知呢?
所以,如果以上的问题,没有对应的解决方案的话,那么微服务不但不是银弹,反而是焦油坑。
服务拆分的一些方法论
上面提到了微服务在落地实践的过程中可能存在的一些陷阱,简单来说就是:
微服务拆分的过细,过分强调small。
微服务基础设施不健全,忽略了automated。
对于微服务拆分过细导致的问题,最好按照团队规模进行拆分。对于每个团队规模的定义,业内有一个比较著名的理论:“两个披萨理论”,同时一个微服务最好三个人负责开发,例如团队规模6人,那么项目可以拆分成2个微服务,随着业务的不断发展,团队规模有原来的6人,变成了12人,那么微服务可以从2个,变成4个,相应的微服务的粒度也就更细一些。
目前业内有四种服务拆分方法:分别是基于业务逻辑拆分,基于可扩展性拆分,基于可靠性拆分和基于性能拆分。
基于业务逻辑拆分
这是一种最常见的服务拆分方法,将系统中的业务模块按照职责范围识别出来,每个单独的业务模块拆分成一个独立的服务。
虽然基于业务拆分看起来很直观,但是实践过程中最常见的一个问题就是团队成员对于服务“职责范围”的理解差异很大,经常会出现争论,很难达成一致意见。导致这个问题的主要原因在于,从业务角度来进行服务拆分的话,规模粗和规模细都没有问题,因为拆分的基础就是基于业务逻辑,而要判断拆分的粒度,就不能再从业务逻辑的角度了,要根据团队规模的客观情况,计算一下大概的额服务数量范围,然后再决定合适的“职责范围”,否则就有可能出现拆分过粗或者过细的情况,而且大部分情况下都会出现拆分过细的情况。
基于可扩展拆分
将系统中的业务模块按照稳定性分类,将已经成熟和改动不大的服务划分为稳定服务,将经常变化和迭代的服务划分成易变动服务,稳定的服务粒度可以粗一些,即使逻辑上没有强关联的服务,也可以放到同一个子系统中。而对于不稳定的服务可以细一些,但是也不要太细,要始终记住控制服务的总数量。
这种服务拆分策略,主要为了提升项目快速迭代的效率,避免开发过程中,不小心影响了已有的成熟功能,导致线上问题。
基于可靠性拆分
将系统中业务模块按照对可靠性要求高低进行排序,将可靠性要求比较高的核心服务和可靠性要求比价低的非核心服务进行拆分开。然后重点保证核心服务的高可用性,这种拆分策略有一下好处:
1.避免非核心服务故障影响核心服务
例如,日志上报一般都属于非核心服务,但是在某些场景下可能有大量的日志上报,如果系统没有拆分,那么日志上报可能导致核心服务故障;拆分后即使日志上报有问题,也不会影响核心服务。
2.核心服务高可用方案更加简单
核心服务的功能逻辑会变得简单,存储的数据可能更少,用到的组件也会更少,设计高可用方案的大部分情况下要比不拆分简单很多。
3.能够降低高可用的成本
将核心服务拆分出来之后,核心服务占用的机器,带宽等资源要比拆分之前少很多,因为对于核心服务做高可用方案,机器,带宽等成本比不拆分节省很多。
基于性能拆分
基于性能拆分和基于可靠性拆分类似,将性能要求高或者性能压力大的模块拆分出来,避免性能压力大的服务影响其他服务。常见的拆分策略和具体的性能瓶颈有关,可以拆分Web服务器,数据库,缓存等。
以上几种拆分方式不是多选一,可以根据实际情况自由排列组合。
基础设施建设
可能大部分开发者在微服务实践过程中,主要关注微服务的small和lightweight特性,但实际上真正决定微服务成败的,恰恰是那个被大部分人忽略的“automated”,为什么这样说呢?因为服务粒度即使划分的不合理,实际落地后如果团队遇到麻烦,自然会想到拆分服务或者合并服务;但是如果“automated”相关的额基础设施不健全的话,那么微服务就会变成焦油坑。
下面这张图是微服务建设过程中需要的基础设施建设:
看到上面这张图,你会发现微服务真的不是刚开始认为的那样简单又轻量级,要想做好微服务,这些基础设施是必不可少的,否则微服务有可能会变成焦油坑,让业务团队在里面不断挣扎,无法自拔。因此,微服务并没有减少复杂度,而是将复杂度转移到了基础设施上。
虽然微服务基础设施的建设一个非常庞大的工程,但是目前已经有很多开源的微服务基础设施全家桶了,比如像大名鼎鼎的spring cloud,其涵盖了服务发现,服务路由,网关,配置中心等功能,而且如果系统中服务数量不多的话,以上的基础设施也不都是必须的。通常情况下,可以根据优先级来搭建基础设施:
1.服务发现,服务路由,服务容错:这是最基本的微服务基础设施。
2.接口框架,API网关:主要为了提升开发效率,接口框架是为了提升内部服务开发效率,API网关是为了提升与外部服务对接的效率。
3.自动化部署、自动化测试、配置中心:主要是为了提升测试和运维效率。
4.服务监控、服务跟踪,服务安全:主要是为了进一步提升运维效率。
经过以上的阅读,服务是银弹还是焦油坑这个问题,想必你已经有答案了吧,其实微服务并不是银弹,而且搞不好还会称为焦油坑,之所以微服务比较流行,是因为随着容器化技术的发展,再加上互联网的业务场景比较适合使用微服务架构而已。