我 和 微服务架构

我算是完整的经历了服务端架构发展的整个历程。

09年进入阿里巴巴的时候,那时候整个阿里巴巴就是一个典型的单体应用,整个国际站业务,部署上就三个巨大的单体应用:

  • MyAlibaba:供应商发布编辑管理商品的地方
  • BOPS: 运营人员审核商品(机器审核+人工审核的一条工作流)、管理类目和属性的运营管理后台。
  • Aisn: 海外买家浏览搜索商品的地方

数据层面也是杂糅在一起,一主一从的Oracle数据库 + EMC小型机支撑着几亿级别的数据量。

现在看起来当时的业务架构还是数据架构都是庞大而古老的。确实也是低效的,记得当时的发布真是设计部门最多并且容易出错的日常工作了。你仅仅是修改了一点点代码,也要跟所有当天一起发布的人合并验证完成才能上线,假设因为别人的问题回滚了,大部分情况下,你的代码也要回滚。所以有时候一个小小的修改要发布一两周才上线。另外,修改代码也特别害怕影响到其他人的代码或者线上的服务,毕竟大家都在这一套代码一个应用上开发。

但是阿里巴巴确实是国内最早提出服务化和去IOE的大型互联网公司,并且落地执行也是最坚决的。

如果我没有记错的话,应该早在2011年初平台部门就已经在大力推广dubbo,然后会员是最早实践的组,随后就是我们商品组。到2012年的时候基本上服务化迁移改造完毕,并且所有的新项目都是以服务化的方式提供了。

而数据层面,也是在2011年开始提出去IOE,开始引入MySQL和普通PC。开始分库分表,首先是垂直拆分,会员表,商品表都单独部署。然后是垂直拆分,商品作为最大量级的表首当其冲需要改造。作为商品的核心成员,有幸(其实也挺不幸,这种迁移工作其实容易出错也没有带来直接的业务收益)完完全全的参与了这种迁移过程。使用了Cobar作为数据库分库分表中间件。

当时阿里巴巴的平台部还是人才辈出的,而且有国际站业务这么好好的一个落脚点。现在很多框架都已经开源,像前面提到的dubbo和cabar。

完成了服务化和去IOE的使命之后,我在12年年中离开了阿里巴巴加入了腾讯电商。腾讯电商因为是新成立没多久的新业务线,所以没有阿里巴巴的包袱,那时候服务化和MySQL分库分表已经开始普及。腾讯电商整体架构一开始就是典型的SOA架构了。有很明确的分组,如商品组、用户组、订单组、物流组等,每个小组管理自己的业务,提供明确的服务接口。使用的是电商平台自己研发的一套RPC框架。实现上有点挫,特别是序列化方面。但是跟dubbo基本是一样的,就是典型的 注册中心 + 服务提供者 + 服务消费者 三角模式,只是采用了 IDL + autogen 的机制,支持多种语言。数据存储方面,也是各自管理自己的数据,并不会放在一起。对外提供的是服务接口,而不是数据。

之后来到百度,当然百度也是有自己的RPC框架,而且非常多,最好用性能最高评价最好的当属于baidu-rpc,作者戈君是一个非常技术型的牛人。baidu-rpc现在也开源了(brpc),没过多久戈君也离职了。brpc最大的特点其实是性能,引入了独特的bthread,性能确实是杠杠滴。另外一个是引入bvar计算器机制,可以方便记录和查看用户程序中的各类数值。同时它的Builtin Services也内建了一些status、vars、flags、cpu profiler、heap profiler和contention profiler,方便用户观察应用的运行状况。这点非常类似于SpringBoot的actuator。另外,跟腾讯一样,baidu-rpc也是IDL+autogen的方式,但是它的IDL格式采用的是protobuf。所以是支持多种语言,并且在序列化方式上也是非常高效的。但是baidu-rpc官方的client只有C++的,其他语言支持并不好。不过总体来说确实是一个非常优秀的框架,令人印象深刻。

尽管外面微服务架构已经风风火火,但是其实BAT内部都没有声称自己是微服务架构,框架上其实还是典型的RPC框架。

我自己也看了不少介绍微服务架构的文章,实在没有看出跟现在我们大量使用的SOA架构有什么本质上的区别。所有的介绍微服务架构的文章都会跟一个东西做对比 —— 单体应用,而不是跟SOA对比。其实这有什么好对比呢,单体的不足在切换SOA架构的时候大家都已经明明白白了,还需要提吗?


微服务(Microservices) vs 单体架构(Monolithic)

单体架构的不足

1、庞大而复杂,可维护性差。

一个简单的应用会随着时间推移逐渐变大,在每次迭代开发中,不断增加许多新代码。几年后,这个小而简单的应用会变成了一个巨大的怪物。一旦你的应用变成一个又大又复杂的怪物,那开发团队肯定很痛苦。敏捷开发和部署举步维艰,其中最主要问题就是这个应用太复杂,以至于任何单个开发者都不可能搞懂它。因此,修正bug和正确的添加新功能变的非常困难,并且很耗时。另外,团队士气也会走下坡路。如果代码难于理解,就不可能被正确的修改。最终会走向巨大的、不可理解的泥潭。

2、编译、启动时间太长

大量的时间浪费在无价值的等待中了。

3、不利于资源分配,按需部署。

例如一个模块主要是CPU敏感逻辑,应该部署在AWS EC2 Compute Optimized instances,而另外一个内存数据库模块更合适于EC2 Memory-optimized instances。然而,由于这些模块部署在一起,因此不得不在硬件选择上做一个妥协。

4、不利于资源和风险隔离

因为所有模块都运行在一个进程中,任何一个模块中的一个bug,比如内存泄露,将会有可能弄垮整个进程。除此之外,因为所有应用实例都是唯一的,这个bug将会影响到整个应用的可靠性。

5、依赖复杂,升级发布非常麻烦

所有的依赖通过jar包本地依赖,容易造成版本冲突,同时升级版本也需要同时升级相关的使用方。发布也不能独立发布,需要所有的依赖方验证通过。

6、不利于架构升级或者引入新的框架新的语言

单体式应用使得采用新架构和语言非常困难。比如,设想你有两百万行采用XYZ框架写的代码。如果想改成ABC框架,无论是时间还是成本都是非常昂贵的,即使ABC框架更好。因此,这是一个无法逾越的鸿沟。你不得不在最初选择面前低头。

微服务架构的不足

1、分布式系统带来的性能开销和排查问题的复杂性

性能开销其实还好,但是排查问题确实变得麻烦一些。好在RPC框架已经有很多分布式调用链路跟踪的组件可以很方便查看调用链路的情况。

2、分布式事务

分布式环境下的事务处理从来不是一件简单事情。

3、测试接口需要mock

本地依赖变成远程依赖,为了可测性,需要对这些远程接口进行mock。

4、部署复杂性

拆分的越细,部署起来就越麻烦。应用相对于单体一下子多了很多。不过结合docker和kubernetes,这方面应该是可以得到解决的。

参考文章

  1. 微服务实战(一):微服务架构的优势与不足