1. 前言
场景线上化在各行各业已经成为一个趋势,贝壳也在尝试将多种场景搬到线上。比如线上对经纪人培训、线上看房、线上带看、线上签约等。
为了应对新冠疫情对公司业务的影响,在春节过后公司决定以最快速度上线直播业务。项目前期面临着时间短、任务重、人力少等问题,于是项目之初,客户端是按照功能实现的方式来进行开发的,以优先确保项目的如期上线。
直播功能上线后收到不少好评。随着直播场景和需求的多样化,纯粹面向单一项目的开发已经无法满足当下对直播的诉求,建设客户端的直播平台以支撑多样化直播场景迫在眉睫。
接下来将介绍我们在直播平台建设过程中遇到的问题以及积累的一些经验。
2. 行业难点
合理的协同开发,需要解决多人同时协同开发一个页面或者一个功能;
3. 贝壳直播1.0版的业务痛点
图1
中台和前台的部分边界不够明确,有些逻辑具体属于前台还是中台,没有划分标准,造成开发过程中需要花费大量时间讨论解决这类问题。而且各端规范不够一致,不易理解,接入成本高;
直播SDK技术分层不合理,很多业务逻辑和直播核心功能相互耦合,相互依赖和引用,造成内聚程度低、复用性差、扩展性低。一个功能需要对接多个业务后端,效率比较低下;
动态配置化程度低,很多运营热区位,易变的功能区,缺乏动态配置下发的能力,而且接口对版本兼容也不够,很小的功能点的修改可能需要发版解决;
快速进入开发成本高,由于直播和业务基本耦合在一起,需要花费大量时间梳理流程和功能,新人不能快速进入开发节奏。
时序图如下:
4. 贝壳直播2.0版的改进
4.1 明确边界和职责
由于直播和直播衍生出的业务涉及到的系统比较繁多,而且有些系统之间的功能严重相互重叠,我们第一步需要明确各系统的职责,以及相互调用的流程。
首先,我们熔断了客户端与商业化系统、拓客平台的直接交互,改造成客户端只与一个业务前台交互。所有的业务功能,移动端只需与前台交互即可完成。由前台去对接各个平台及系统,最大限度的简化移动端陷入复杂的多端交互中。
边界明确后的架构图如下:
4.2 功能聚合和收敛
由于直播功能众多,并且流程复杂,涉及到的后端和系统繁多,导致直播的业务接入成本很高。这种情况下,需要做的是在各端职责明确的前提下,将直播相关的核心流程和功能封装统一管理。
同时以接口或者抽象的形式把关键节点暴露给业务,保证功能节点的单一性而又不伤害业务的扩展性。简而言之,高度内聚核心流程和功能,降低业务逻辑的耦合和下沉。
改造后的架构图如下:
4.3 平台化与分层
因为直播的核心流程是固定的,不会随着业务不同而改变,所以直播的核心流程应该是在直播平台管理,而且平台需要中断业务与直播中台的直接交互。业务只需向直播平台获取需要的服务,剩下的就像普通业务开发一样。
同时为了兼容不同业务使用直播流程中的部分功能,需要对技术做纵向分层,主要分成:基础库(Basic)、直播框架(Framework)、控制层(Controller)、组件层(Compose)等,每一层都具备单一的功能职责。分层后的架构如下:
基础库(Basic):统一收口框架层(Framework)、控制层(Controller)、业务层(Business)的初始化以及必要参数的承接,使得初始化的入口只有一处,确保业务接入的唯一性、准确性,基础库没有多余的逻辑,仅仅用来做一些网络、业务标识等一些必要的初始化及信息暂存。
直播框架(Framework):封装了直播的核心流程包括实时音视频、CDN旁路观看、IM、共享资料等。业务直接依赖框架层(Framework),可以满足对直播的核心功能的使用。
控制层(Controller):将直播中台和直播框架(Framework)串联起来,直播中台通过接口和配置文件来控制直播的流程以及功能,显著提升了直播在多场景下的灵活运用,结合框架层(Framework),业务即可直接跑通直播的核心流程。
组件层(Compose):封装一些业务通用的组件,比如点赞、分享、连麦、弹幕消息等,组件层是一个独立的层,不依赖任何层。完全不耦合任何业务或者依赖,显著提升了直播业务的开发效率。
4.4 动态化配置
通过技术分层的设计,彻底将功能从纵向进行了解耦,而且每层功能结构清晰。为了可以灵活实现不同直播类型的随时切换,我们需要将很多功能及流程动态化,与后端一起梳理易变的功能区以及商定对应的解决方案。
根据进入直播间的接口返回的数据决定是TRTC进房,还是CDN旁路观看;根据权限接口的数据决定是否具备某些功能,如点赞、连麦、推流、开启直播等;根据接口数据动态控制运营热区,如抽奖、领券、专属服务等;根据配置决定功能区具备哪些功能,如消息发送、点赞、分享、礼物、楼盘、资料共享等;根据配置决定直播类型,如庆典活动、会议类型直播、泛直播等。
4.5 监控和日志
任何框架都必须具备的能力之一就是监控和数据上报的能力,直播平台亦是如此。
平台需要具备上报数据的逻辑,但是无需具备具体上报的功能,简而言之就是平台按照特定的逻辑将数据、日志收集存储下来。触发具体上报条件时,借助各端的上报功能进行具体的上报,这么做的优势是无需适配不同业务端的上报异常,而且无需维护具体数据上报的版本库。
加入监控后的架构如下:
4.6 “零”成本接入
解决完上面几个问题后,接下来需要解决的就是如何降低业务的接入成本以及学习成本。我们的目标是像Google提供给开发者的引用方式一样,只需引入对应的版本库、做简单的初始化,后续流程和功能自动完成。业务的关注点聚焦在业务上,无需关心直播相关的内容。
4.6.1 接入方式
implementation(rootProject.ext.depsLibs.common_live) {
changing = true;
transitive = true
}
implementation(rootProject.ext.depsLibs.ke_live_compose) {
changing = true;
transitive = true
}
implementation(rootProject.ext.depsLibs.ke_live_controller) {
changing = true;
transitive = true
}
implementation(rootProject.ext.depsLibs.ke_live_framework) {
changing = true;
transitive = true
}
implementation(rootProject.ext.depsLibs.ke_lib_basic) {
changing = true;
transitive = true
}
4.6.2 初始化
//设置点播相关事件回调
mLiveController.setLivePlayListener(mLivePlayListener);
final String groupId = getRoomId() + "";
//注册直播各个节点事件回调
VideoManager.getInstance().registerCloudListener(groupId, mCloudListenerImpl);
//注册IM相关事件及广播
MessageManager.getInstance().registerMessageListener(groupId, mMessageListener);
4.6.3 资源回收
mLiveController.onRelase();
VideoManager.getInstance().unRegisterCloudListener(mCloudListenerImpl);
MessageManager.getInstance().unRegisterMessageListener(mMessageListener);
4.7 终极形态
5. 业务使用场景
目前贝壳系业务接入直播平台的有:通关培训、训练场、在线谈判、在线核签、新房泛直播、新房1vN、二手泛直播、海外泛直播、庆典活动、二手带看工作台、新房带看工作台、装修等。效果如下:
6. 后记
在满足前期业务需求的快速迭代之后,我们紧接着就开始了对直播框架的优化和升级。通过技术分层,我们把直播相关的流程和功能做了高度封装,彻底解除了业务与直播的耦合、业务与中台的耦合、业务与各个前台的耦合。使得直播功能的开发与普通业务开发几乎相同。而且由于封装了大量通用型组件,使得业务开发更加高效。