直播中台搭建指南
文章目录
前言
自从头条搭上短视频这条快车道,做出了抖音这款风靡全世界的现象级产品。人们不禁都在想,他们到底用了什么技术?为什么头条能成功?其中不乏有神化创始人的,也有真的去探究背后的技术的。我身为所谓”竞争对手“公司的一份子,也不免常常被安利。其中听得最多的就是"中台"二字。
什么是中台
如果让我来回答这个问题,我觉得其实根本没有什么中台。所谓的中台概念,也只是软件开发过程中为了提速软件开发效率的产物之一,组件化,微服务等等概念,其目的都是为了减少软件开发过程中的重复劳动,降低试错成本。笔者大概在2013年的时候,就有接触过一篇很有意思的文章:Stevey’s Google Platforms Rant。作者喷了一大堆亚马逊的抉择是如何如何差,Google是如何如何好。到最后却反过来讲了亚马逊的平台做的如何好,以及杰夫贝佐斯竟然可以在软件领域也有先知卓见,搭建了亚马逊的平台。里面也有一些对微软,苹果的评价,相当有趣。
搭建直播中台
虽然我并不认同这个概念,不过大概从19年底开始,部门内部的研发就开始出现各种搭建中台的声音,到现在也是不绝于耳。无论是什么业务,不管能不能真正的复用,先命名为XX中台,占个坑位。彼时我刚好转型独立负责一个产品的客户端开发,所以我也不能免俗,决定从负责的直播业务着手,搭建一款直播中台。 直播中台的目标,主要有两个:
- 吃自己的狗粮
- 支撑多个产品线 下面我从将从我的实践与我的反思两个方面来总结这部分的工作。
直播中台实践 – 基础架构
首先放出整体的架构图:
为了整体的业务尽可能的达到可复用性,首先我将整体的业务划分为五层,每一层组件与上层组件之间呈现单项依赖关系,这样做的好处就是可以做到最大程度的解耦。
基础服务层
基础服务层分为两部分,与直播能力有关的如推拉流的SDK,美颜,伴奏处理等能力,可以抽象成跨平台的中间件,这部分的能力虽然与业务无关,但是最好还是在这上面封装一层抽象层。方便后续替换SDK。另外,在处理SDK的数据层面上,也最好使用原始数据。更理想一点,可以搭建一套自己的渲染流程。 这里需要注意的点,主要是需要处理好原始数据的兼容性。比如yuv数据在安卓机器上会存在按16位对其的问题。在对耳返的处理上,安卓也需要处理好硬件耳返与软件耳返的能力等。这些能力通常来说并不属于推拉流SDK,或者是美颜相关的业务。但是却可以做成基础能力。
业务服务层
业务服务层,是对直播间状态机的抽象。粗略划分有下面几类:
分类 | 服务 |
---|---|
基础服务 | 进房流程、心跳、推拉流、美颜、IM信令、最小化、生命周期 |
基础业务服务 | 连麦、PK、清晰度切换 等基础玩法 |
扩展业务服务 | 红包、官方房间 等业务玩法 |
直播业务的特点在于,相比于传统页面的CURD,直播业务的玩法往往有相当多的状态同步。业务服务层仅包含与业务后台状态同步相关的实现,记录业务状态的数据。原则上来说,这一层非常考验研发同学的抽象能力。举例来说,一个连麦业务与后台交互的状态可能有以下这些:
连麦状态
- 未连麦
- 等待队列中
- 正在麦上,状态正常
- 已同意上麦
- 静音
对于后台业务来说,这几个状态位就已经足够了,因为后台只处理纯数据的轮转。一种办法就是我们如实的去实现这五个接口,依赖于使用组件的同学来消化五个接口的意义,由于前端的业务往往与UI交互相关,那么这部分的工作就不可避免的与UI代码互相耦合了。业务服务层的意义,就是要消化这部分的状态轮转,并提供可读性好的接口。上面的五个状态,可以根据业务需求转化出用户的操作,与后台的响应两部分接口。在协议上可以分为:
Action:
// 用户
requestConnect();
cancelConnect();
stopConnect();
//主播
acceptConncetRequest();
refuseConncetRequest();
muteUser();
kickoutUser();
Listener:
// 处理状态同步与一些异常事件
onUserConnectStatusUpdate(Status status);
onConncetTimeOut();
...
这样的抽象的好处有很多,如从纯状态的流程变为业务流程,业务可读性更好。统一管理了相关状态,可以有效避免状态同步到多个内存导致UI界面混乱的问题等。
UI组件层
UI组件采用MVVM中的 ViewModel 与 View 的思想。其中View作为纯粹的UI组件,只处理UI元素的布局。而实际的业务逻辑代码,则是交给ViewModel来实现。需要注意的是,ViewModel将直接使用业务服务层的数据,并把状态同步后的数据同步给View展示。起到了承上启下的作用。为了实现到纯粹的UI组件,ViewModel跟View之间的数据更新可以采用反射的方式来实现。比如iOS中可以使用ReactCocoa, 而安卓则可以使用 DataBinding 等技术。这一层要求整个数据的流动必须是单向流动的,并且都由业务服务层提供的接口来驱动 如下图:
这样做有两点收益:
- 纯UI的View因为不含任何业务逻辑,所以具备最大的可复用性,方便拆卸。
- 可以针对相同UI实现不同的ViewModel来实现不同的业务逻辑,这样做的好处在于当有不同的房间类型的时候,方便替换数据源。
业务装配层
现在我们有了业务逻辑,有了UI,那么就可以针对不同的业务场景把直播房间搭建起来了。一种方式是你可以写重复的代码,但这显而易见不够灵活。另一个办法则是再实现一套业务装配层。这一层包含两个功能。一个是负责把UI组件层的 ViewModel 与业务服务层的服务接口事件绑定起来,另一个则是根据业务需求来做UI上的排版布局。
采用这种方式,不同的业务就可以按需加载自己的业务模块,实现到搭积木的效果了。但是实际上却不仅于此,如果我们考虑把业务模块与布局抽象成一个布局文件,类似于前端排版的css,那么我们甚至可以动态下发不同的直播间了。这个设想我们仅实现到搭建积木这一层,动态下发的能力因为后续我没有继续负责直播业务而没有继续推进。
房间玩法
通过不同的业务逻辑搭建的不同直播间,其实也具备一定的可复用性。不过这部分其实不属于直播中台组件搭建的能力了,复用的是整个产品与视觉的设计。在某一些业务的场景也可以用到,比如手机QQ空间分为独立的App与手机QQ的结合版。那么如果这里功能完全一样,其实是可以同步的更新的。
直播中台实践 – 通信机制与生命周期
通信机制
对业务做好分层隔离之后,下一个需要解决的是模块之间的协同问题。设想在业务服务层有模块A,想要与业务模块B通信。一种方式是通过上图的数据流动的方式,数据先向上流动,然后再由具体的业务ViewModel来消化。这样虽然可以解决业务模块之间纯粹的隔离,但是如果是IM模块,或者是进房事件这种关键模块,则不适用这种场景。因此可以设计一种事件总线的机制来做分发:
这样做的好处有下面几个:
- 每一个模块可以根据总线事件,自行选择加载或者不加载
- 模块之间互相没有依赖,在进房时可以并行加载,提前展示
- 增强代码可读性,统一认识
但是这个机制其实也存在一定的缺陷,比如在进房成功的场景,如果所有的模块都同时做CPU集中型任务的话,那不可避免的会造成拥塞。所以理想来说还需要事件总线的派发器能够做好调度。 另一种场景是模块A跟模块B之间有强依赖,比如直播PK玩法的场景,就需要先让两个主播连麦,之后再进行PK。这个时候一般来说有两个办法: 一个是可以让连麦模块作为纯粹的模块,PK模块作为连麦的子模块,这样从逻辑上也合理,同时PK模块对外实现的接口也掩蔽了连麦模块,接口更清晰。 另一种则是通过某种路由协议来通信,由连麦模块跟PK模块之间做协议上的沟通。不过这样也带来了接口的复杂性,以及管理接口相关的问题。 所以在这种场景下,我们最终选择的是第一种方法。
生命周期
生命周期也是直播间需要考虑的问题之一,例如在用户上下滑动直播间时,我们需要对部分的UI组件或者模块做复用,来减少内存损耗,提升加载速度。这样就必须要避免重用的组件复用了上一次的状态。所以最好通过统一的生命周期事件做好处理:
把所有模块统一加载,统一销毁。
直播中台实践 – 收益
很难说以上架构就是完美的架构,不过最终这一套架构满足了公司音视频直播的业务场景,支持了接近30个研发无障碍协同,快速迭代,接入到了公司多个前端App上。在房间模式上,通过上述架构我们快速支持了产品提出的不同直播间玩法,比如在疫情来到的2020年Club House模式爆火的时候,我们可以迅速通过这个架构搭建出一套UI完全不一样的直播间,在这一点上我还是比较满意的。于此同时,由于模块之间隔离做的不错,所以我跟团队的小伙伴们也积极探索了一些周边的优化,比如编译优化,单元测试,UI组件库,跨平台等等。
回顾一 – 我的反思与我学到了什么?
胆大心细
整个直播中台的搭建耗时接近一年,由于前期业务着急上线,每次大的重构都好像在给赛道上飞速跑的F1方程式赛车换轮胎一样,必须要胆大心细。但是我认为作为技术管理者,必须要有这样魄力,敢于改造,最后会发现整体的项目ROI是很高的。
改造人的认知是很困难的
统一的架构需要统一的实现方式,但是同样带来的问题确一定程度上束缚了开发人员的自主性。可以说在这个地方我像是一个代码暴君,推翻了一切不不符合中台架构的实现。在最开始组内的同学对这一套架构不够了解的时候,发动了一次次的站立会议,等于说强行统一认知,就算这样,整套架构中仍有部分代码不符合规范。所以,整个中台架构的推动可以说是非常艰难。 但是反过来说,如果没有一个这样暴君的角色,那么对应的执行者一定会执行不到位。经过这一件事,我经常在想,架构师到底是一个什么样的角色呢?
选育用留
曾经我有过一个疑惑,每次我把一个我认为技术不错的候选人转给我当时的总监,他总要问:“这个人聪明不聪明?"。作为工程师来说,一个人聪明不聪明重要呢?还是懂各种技术知识更重要呢?从前的我一直都认为,后者更重要。 但是经过这个项目,我再回过头来看,我会认为一个人聪明,情商高,技术一般,远比精通各种技术,但是情商低,理解事情困难的人更好。这个事情并不是非常绝对的,但是在现代工程的领域,往往更加注重协作,而较少真正存在技术深度的研发工作。选择前者能够让项目推进的更顺利,事半功倍。 为什么得出这个结论呢?套用2021年底还流行的一句话 —— “不要问我是怎么知道的。”
身体是革命的本钱
回想过去两年,可以说是各种身体状况频发,也许是因为年到三十,人到中年。也许是因为项目发展太快,步子太大扯到蛋了。不管怎么说,有一个好身体才能有本钱做更多的事情,实现更多在技术上的想法。
最后
这篇总结是我一直想写,但是总是因为某一些原因而没有写。搭建直播中台已经是大半年前的事情了,而今年年中因为部门调动,目前我已经不再负责这一块的业务,开始了新的征程。今天把这一段经历记录下来,结项,迈向新的开始。
文章作者 yingxinsong
上次更新 2021-12-02