微服务是近几年比较流行的概念,我在自己负责的项目里也用上了,改造成微服务模式后,我遇到了很多问题。下面我的一些经验分享,如果你对使用微服务还在犹豫中,也许会有帮助。总之,三思而后行,一定要适度。
微服务带来的最严重问题就是网络延迟了,调用链超复杂延迟就越高。马斯克吐槽 Twitter 微服务过多延迟过高的事情相信大家都了解,在更早之前亚马逊 Prime Video 团队也从微服务转为单体架构。
要改善这个问题,先从根本上入手,尽可能的少拆分,像 twitter 这样拆分出上千个服务的真的恐怖。我负责的项目虽然规模不算很大但是已经有几十个服务了,这给管理维护带来了很大的困难。
减少微服务得从一开始设计的时候就做好,如果已经很多了,重构的代价可能是很大的。调用链不能改变,那就尽可能减少网络延迟吧,让微服务都在一个局域网中相互请求。实在做不到的,也尽可能让服务器在一个地区。
微服务一旦复杂起来就非常麻烦,最头疼的就是调试了。由于网络依赖较多,出了错程序的堆栈信息只能看到服务内的情况,前面的调用链就不知道了。假如支付服务出错了,那么哪个服务调用的支付服务呢,如果是订单,订单又是哪个服务调用的,从哪里下单的?甚至于两个服务相互调用,造成死循环都有可能,排查起来可比单体构架难多了。
现在已经有不少的解决方案了,原理是在消息头中都带入上下文信息,有些 RPC 框架自带了追踪功能。这些跟踪方案都是有代价的,就是性能,微服务一多本来延迟就大,跟踪又增加了网络开销。
其实我也没有好办法,只能说尽可能少拆分,保持较少的服务数,调用链尽可能简单,服务间的依赖要尽可能的少。规模一小,跟踪就容易多了,使用排除法就很容易找到问题。
事务应该是最难搞的了,虽然有很多分布式事务方案,但是很多时候并不一定能用的上。像我负责的项目,后端编程语言有 JAVA、php、Nodejs,数据库也有 MySQL 和 MongoDB 等,想要在复杂的服务调用中让各个服务保持一致性还真不容易。
最好是各个服务都统一技术栈和数据库,至少这样搞分布式事务能容易一些。你可能很奇怪为什么我把项目搞成这个样子,最初的想法也是要团结一切可团结的力量,大家遵守一定的规范就行了,不强制要求。我现在的做法是,不依赖于事务,事务只存在于服务内即可,至于服务协作的情况则有一套较为复杂的验证机制,总之就是不断的检查和重复操作。
服务注册,负载均衡,熔断与恢复这些功能,如果使用了 k8s 集群,我建议交给 k8s 就好。如果程序中去开服务,开发和管理成本真的太高了。当然像熔断可能有些需要细致的操作,容器编排是不能自动帮你完成的。
通过服务拆分,可以实现业务的单独更新,比如排行榜是个单独的服务,那么排行榜如果需要改动,就可以单独更新而不影响其它的功能,不必整个业务被重启或临时中断。同样的,扩展也比较方便,新的服务开发好就可以更新上去,不影响已有功能,不必修改现有的代码。当前,这都是理想情况,实际上还要看业务需要,如果服务间的依赖关系很复杂就难说了。
服务拆分带来的另一个好处是团队管理,尤其是规模较大的团队,可以分组或让每个开发人员来单独负责一个服务,不必所有人都在同一个项目下改代码。这样就可以互不干扰的完成工作,减少了文件冲突,更好的协作。还可以一定程度实现保密效果,每个小组成员只能看到自己负责的服务的代码,不能拥有项目完整的代码,一定程度防止代码泄露。
不管是否微服务架构,统计都是非常让人头疼的,微服务架构只会更麻烦。要跨多个服务采集数据,就需要各个服务都提供查询的接口,然后统计服务将数据汇总,相比单体架构直接使用 orm 查询要麻烦的多。
我之前还遇到过要统计图库中的图片在哪些地方使用过,涉及的服务太广泛了,每个服务也有多个业务在使用富文本,后来只好拒绝掉这个需求。
Saas 平台做复制你可能觉得太扯了,但是我就遇到了,将一个企业的数据复制,然后生成一个新的企业。这个即便是单体架构,也是非常麻烦的,微服务就更不要说了。
做微服务最怕的就是一个服务与所有其它的服务都有关联,这意味着,一旦别的服务有改动,这个服务就有可能需要改动,这个服务改动,别的服务也有可能受影响。关联太复杂,就实现不了上面说的单独管理和单独部署了,如果不同的服务由不同的开发人员来负责,沟通协调成本也很好,服务的对接比单体架构麻烦多了,要写接口和文档,要编写接口请求逻辑。
硬件成本就不用说了,一大堆服务,每个服务都开多副本的话,成本肯定不低。很多公司可能对硬件的成本不是在乎,但是管理成本是必须要关注的。在首次使用时,可能要设置安全组,要设置自动续费。但是后续的管理也不简单,集群中的服务分布不均衡,还要设置亲和策略来均衡。服务器配置不够,升级配置重启也会带来很大的影响,被升级的服务器上的服务会转移到别的服务器,然后再迁回。
不管怎么说,现在有 k8s 这样的容器集群管理工具还是很方便的,再加上云服务的便利,小规模的公司服务器管理技术主管一个人就可以搞定。
上了微服务后,就要面对很多随之而来的新问题,成本的增长是方方面面的。能不上肯定不上的好,规模不是非常巨大的项目,能够支持集群开多副本就可以了。如果必须得上,还是尽可能保持克制,减少拆分。