内容概要
技术支撑着业务高歌猛进,业务增长反过来又驱动着技术不断向前演化,这是每个互联网公司发展过程中不变的旋律。作为全国最大社交媒体网站的微博更是如此。
从 2009 年上线至今,微博架构经历了从最初的单体应用到后面的 RPC 服务化、容器化、混合云架构以及现在的跨语言服务化和 Service Mesh 等诸多阶段,架构演变支撑着微博业务的一次次华丽转身,也见证了微博的飞速成长。
那么,微博架构是如何从一开始的单体应用一步步成长为今天的庞大规模?作为国内最早落地 Service Mesh 的公司,微博为什么要选择做 Service Mesh,具体又是如何做的?这是本系列文章将试图回答的问题。
首先,我会结合微博架构演进的历程向你展示当前微博架构的整体概貌。在这之后,我将聚焦于微博在 Service Mesh 方面的具体落地实践,为你详细讲解微博自研的服务网格 WeiboMesh 从 0 到 1 的成长历程。当然,其中也会有我自己对架构演进的一些思考。
下面,我们进入正题。
在业务发展的每个阶段,面临的问题都不尽相同,而问题又有各种优先级,这就难免为了解决某些较为迫切的问题而引入一些当时不 Care 的问题,这也是日常架构演化过程中难以避免的魔咒。
鱼和熊掌不可兼得,所以架构演化的真谛就在于各种方案评估中的利弊权衡,在以业务为重的前提下进行正向演化。
那么,微博各个发展时期的架构又是如何演化的呢?
业务初期:单体架构
微博发展初期,用户规模高速增长,伴随而来的还有不断涌现的新业务,因为你不知道哪个今天还名不见经传的业务明天就会摇身一变成为备受瞩目的核心业务,大家就像在白纸上疯狂试错。这个时候,快速开发上线才是当务之急。
为了达成这个目标,我们对整个系统做了优良的模块化设计,每个业务作为一个独立的模块,保障业务能独立开发、发布并快速上线。
同时我们自研了容器框架 Cedrus,并在接入层实现了一些通用的逻辑,比如提供统一的认证、频次控制、黑白名单、降级开关、配置服务等功能。平台服务内部则通过 Jar 包的方式依赖调用,对外暴露 API 接口。
在部署方面,我们采用大服务池整体部署的方案,这样一来我们可以更合理地利用资源,避免为每个项目每个模块单独配置资源。
这种单体架构的好处在于资源利用更合理,通过 Jar 包应用来完成的本地服务调用不仅更直接,性能也更高,模块之间开发也相互独立,很多通用的前置逻辑被统一剥离出来后,业务的同学只需要关注自己的逻辑实现就可以了。
当然,单体架构的缺点也很突出,最主要的就是耦合。项目之间强耦合带来了一系列问题,比如升级困难,回归测试非常难做,以及随着业务模块的增多,模块之间的依赖解决困难等问题,此外还有各种 Jar 包冲突,越往后功能越加臃肿,业务变更十分吃力。这时候,就必须考虑做拆分了。
业务稳定期:服务化改造
要对当时规模已经十分庞大的微博平台做拆分是一件极具挑战的事情,好在当时微博业务的发展已进入稳定期。这就是我之前所说的,在每个发展阶段我们所面临的问题都不尽相同,如果说前期大规模的单体架构是为了解决当时业务的温饱问题,那么以系统拆分为出发点的服务化改造就是要做到不但要温饱,还要吃得好。
我们希望通过架构改造来达到保证服务高可用的同时实现业务解耦的目的,以便更好地支撑业务发展。如何做到这一点?
我们主要从业务模块拆分方面来考虑,基于我们之前模块化的单体应用架构,按业务模块拆分是最自然也最容易想到的方案。我们只需要把以往基于 Jar 包依赖的大一统平台按照业务模块做拆分然后独立部署,即可达到业务解耦的目的。
RPC 服务化
但是拆分之后服务之间依赖的问题如何解决?我们当时面临两种选择,一种是提供 HTTP 的 RESTful 接口,一种是使用 RPC 提供远端过程调用。
RESTful 接口的好处在于 HTTP 是明文协议,开发调试比较方便,RESTful 接口描述也足够简单。但缺点也很突出,HTTP 协议本身比较臃肿,我们内部服务的依赖主要解决数据可靠性传输的问题,并不需要那么多无用的请求头。