微服务一直以来是服务治理的基本盘之一,落地到云原生上,往往是每个 K8s pods 部署一个服务,独立迭代、独立运维。
但是在快速部署的时候,有时候,我们可能需要一些宏服务的优势。有没有一种方法,能够 “既要又要” 呢?本文基于 tRPC-Go 服务,提出并最终实践了一种经验证可行的方法。
一、微服务的优劣
微服务是云原生的大潮流,它的优势非常明显:
-
微服务大大降低了模块间的耦合。当某个模块 / 微服务需要变更时,只需要调整这个微服务即可,其他服务无感知;
-
微服务化使得模块的更新能够平滑过渡,避免了停机更新的问题,也适合大型团队或多个团队间合作构建;
-
微服务模块的输入 / 输出定义很明确,非常适合融合 DDD 理念进行设计;
-
问题排查时,能够快速定位出现问题的模块,对运维也很友好。
然而微服务也存在劣势:
-
当系统趋向复杂时,随着微服务的拆分、功能的繁杂和细化,微服务越来越多,一窥系统全貌的难度越来越大;
-
模块间通信通过 RPC 实现,RPC 带来了时间和网络流量的开销;
-
依赖于完备的服务治理体系,对小团队而言,部署成本较高;
-
多租户隔离部署时,运维难度也成倍增加。
二、遇到的问题
我们是心悦俱乐部首页 Feeds 流推荐系统的开发团队。但我们推荐系统也接入了其他业务,比如我们在接入游戏知几项目的一个功能后,全量发布前的压测中发现 CPU 开销大到难以接受。
1.分析
我们的系统是简单按照 “业务 → 分流 → 重排 → 精排 → 召回” 的推荐系统微服务化部署,没有做编排化:
观察压测数据,我们会发现,在分流层前后的服务,网络开销非常大:
分流服务是推荐系统的总入口,它没有很强的业务属性,而是在整个推荐系统的前面、在业务数据的基础上,加入 A/B Test 参数,供整个推荐系统使用。所以它对于业务负载基本是透传的。
很明显,业务服务发给推荐系统的数据流量非常大,而作为透明传输业务数据的分流服务,入参需要反序列化,出参需要重新序列化,这些都是无谓的算力消耗。
三、解决方案
从代码上看,占流量大头的数据结构,在整个调用链路上都是一致的,我们自然想到&#x