合作机构:阿里云 / 腾讯云 / 亚马逊云 / DreamHost / NameSilo / INWX / GODADDY / 百度统计
罗马不是一天建成的。语聊房当前架构也是不断演进的结果。
在技术架构层面,语聊房作为搭建在直播体系上的业务,使用既有技术架构体系可以帮助我们快速搭建早期产品,但随着业务迭代,已有技术体系又成为新的技术架构的负债。
同样在业务架构层面,语聊房产品已经迭代一年,产品形态依然在快速变化,已有的业务架构又会成为新的业务架构的阻碍。
每一次产品需求的迭代,都会对已有技术架构和业务架构造成双重冲击。
本文将结合语聊房持续演进的过程,谈谈业务视角下的架构演进。以及如何构建能应对各种变化的系统,不断达到新的平衡。
了解架构演进之前,我们先了解语聊房业务的来龙去脉。从语聊房的前身PC版本多人连线算起,整块业务到现在已经迭代一年。
图片
上图介绍了这一年来的语聊房产品迭代的2个主要阶段。
第一个阶段是2022年7月,从0到1的产品探索期。直播已有的互动能力比如主播和主播视频PK,能力模型是围绕一对一建设的。一方发起另一方接受就可以开始互动,一方退出这一场互动就会结束。这种互动模型在产品上存在诸多限制,比如无法支持一个房间多个主播同时互动的业务。于是为了满足用户需求,我们开始探索了多主播间的互动能力,包括主播与主播,主播与观众的音视频互动的能力。在这个阶段主要目标是对齐竞品,同时完善我们开播工具的基础能力,丰富主播互动玩法。
第二个阶段是2023年,语聊房项目经过战略升级,成为专项进行运营。既是一次巨大的机会,又是巨大的挑战。一方面我们在功能层面与竞品还有明显的距离。另一方面在技术架构层面,语聊房的架构是从主播与主播间互动模型演变过来,与语聊房主播与用户间的互动还有很多需要调整的地方。同时相比探索期,专项整体迭代节奏加快,而且对技术质量要求更高。所以在这个阶段,主要目标变成在功能层面快速迭代以满足用户诉求, 同时技术架构上需要快速调整以响应产品变化。如何又快又好的完成需求,成为这一阶段技术上的主要矛盾。
图片
上图介绍了战略升级后, 语聊房在用户体验升级与产品迭代上进行的具体功能迭代事项。
语聊房业务构建与直播体系之上,所以要了解语聊房的架构,就必须先了解我们当前的直播业务和架构,才能帮助我们建立全面的认识,更好的理解决策时的一些思考。
图片
上图是典型的直播业务UI视图,中间部分为视频流播放器,上方为主播信息,榜单等信息,下方包括房间公告,弹幕互动,底部互动按钮等业务信息。
用户通过点击直播间,进入直播间,观看主播推送的视频流,同时可以通过弹幕,礼物等方式与主播进行实时互动。
图片
上图所展示直播架构只是当前的直播架构的冰山一角,完整的架构远比这个复杂。但为了更好的聚焦于语聊房架构,我们重点介绍将会与语聊房有交集的流程和模块。
主播首先使用B端客户端打开直播间,然后通过B端客户端采集进行直播的内容,比如摄像头,话筒,游戏程序,屏幕等内容,然后将内容通过压缩编码成合适的格式推送到视频云。视频云需要将接收到的视频数据转换成不同的视频格式并分发到全球各地不同的节点,用来满足各地观众使用不同的终端,对分辨率和格式的不同的需求。
介绍完B端这一系列流程后,下面就是观众使用C端客户端进入直播间。首先需要请求业务服务器P0和P1接口,P0接口会根据C端用户位置,终端设备,分辨率等维度,返回视频拉流地址,同时C端客户端也会根据视频横竖屏类型,房间类型等渲染出相关的视频内容进行播放。P1接口会根据房间和用户属性维度,返回当前房间相关的直播业务信息,比如房间分区,不同分区往往对应不同的业务玩法等。
同时直播内容安全也是非常重要的一环,我们需要保证观众看到的视频符合法律法规。所以需要对主播推送视频进行审核。通过审核后的内容才能推送给用户观看,所以不可避免的会造成延时,也就是主播与观众的时间轴不一致。上图中专门在每个环节上标注了延时时间。一方面我们需要延时来保证内容安全,同时各个子系统处理,分发,流转也需要时间,另一方面我们又希望提供主播与观众实时互动的能力。毕竟如果用户发完弹幕,几十秒后才能收到主播反馈,那用户体验将会收到极大影响。这一点对于实时性要求特别高的语聊房业务也是一个难点。
经过上面的介绍我们已经了解了直播的基本架构。已有的架构数据链路是主播音视频数据经过视频云推送给用户。举个列子就像有一个舞台,主播在舞台上表演,用户在舞台下观看。主播如果需要和另一个主播进行互动,就需要一个电话。我们使用的“电话“就是RTC,我们使用RTC技术来解决主播间实时音视频通信的需求。
在做主播多人连线之前,已有的互动模式包括主播和主播视频连线,主播和用户连麦等功能都是一对一互动模型。主播邀请另一个主播或用户发起一次视频连线或语音连麦,另一方同意即开始互动。然后其中一方退出本次互动状态就变为结束。显而易见,这无法满足下图这种类似于聊天室,主播可以邀请多人同时互动的业务需求。
图片
所以我们首先需要分离出场次和会话的概念。
主播首先创建一个互动场次,场次之内可以分别邀请多个主播,单个主播的加入离开对应会话概念。基于场次与会话的抽象,主播可以创建场次后邀请多个主播同时进行视频连线。即使场次创建人退出,场次仍然可以存在。
术语介绍
图片
上图是新增场次,会话,频道等领域之后的多人互动模型业务架构图,与上面直播业务架构相比,我们屏蔽了推流到观看过程细节,重点关注与rtc相关的业务交互。
当主播使用互动功能时,客户端将rtc音视频数据作为一个采集源, 与其它的采集源数据合成后推送给视频云,最后用户拉取视频流观看。
图片
这里又引出了一个新的问题,既然主播间可以使用rtc进行实时音视频互动,那用户也接入rtc,是否就可以不经过视频云直接观看主播的直播?
答案是yes。业内也有很多互动直播间只基于rtc的能力实现。但是显而易见,作为探索性业务,基于实现成本的考虑,作为旁路系统接入的实现成本远远低于改造整条链路。但带来的缺点就是,业务服务需要同时考虑2套系统的状态的一致性。这个状态一致性也会在后面给系统的演进带来更多的挑战。
图片
上图是基于业务架构图所对应的应用架构图
我们在服务层增加新的服务,用来处理场次,会话和rtc渠道的关系。
技术层面搭建好主播与主播的互动能力以后。我们沉淀了多人互动模型的技术资产。但产品层面还远远不够,一方面主播只能使用PC直播姬进行互动,缺少移动端互动能力,减少了能使用的主播数量。另一方便还不支持主播与观众进行互动,减少了互动功能使用场景,也减少了主播进行互动的意愿。
图片
我们认为社交是促进主播开播的一个契机。,语音聊天是非常重要的社交场景,有助于激发主播开播动机。
为了支持产品诉求,我们架构上需要做出如下的调整:
图片
上图是经过调整后的多人语聊业务架构图,相比多人互动架构图,我们屏蔽了rtc相关的交互细节,重点关注扩展到C端用户后系统架构的变化。
首先是互动能力扩展到移动客户端, 产品层面支持C端用户参与互动。我们根据用户是否参加互动,区分用户为观众态和互动态。
观众态:用户不加入rtc频道,通过视频云拉取主播推送的视频流,流里包含所有互动用户的rtc音频流。
互动态:用户不拉取视频云视频流, 通过rtc音频流参与互动
图片
然后是基于RBAC模型的用户权限设计。增加角色控制不同主播,管理员,用户的权限。
术语定义
最后是打通送礼链路, 以前观众只能给主播送礼,现在支持参与互动的用户送礼,这样也能提升用户互动意愿。
首先介绍一下麦位是什么:
参考上图多人互动业务示意图,主播的视频会固定在视频流左侧,右侧四个小格展示加入互动的其他主播。
参考上图语聊房业务示意图,主播固定在上方区域,下方2排共8个圆圈展示参与互动的用户头像。
麦位管理包括互动用户位置的分配,操作按钮展示与控制,比如静音,踢人,是否说话中状态展示等逻辑。
然后是问题的关键, 云端化对应的是本地化。最早设计时这些逻辑会什么会放到客户端上来做?这个问题还要从多主播互动这个业务来回答,多主播互动中每个房间5个位置,最多5个房间一起互动,一共5X5=25个位置。同时每次互动用户上下麦,都会导致25个位置渲染发生变化。另一方面早期的麦位控制也比较简单。不包括复杂的位置分配等逻辑。所以当时评估下来放在客户端上实现比服务端实现成本低。等到多人语聊业务上线以后,最初的实现已经无法满足复杂的麦位管理控制需求了。所以我们需要将麦位分配与控制逻辑从客户端迁移到服务端。
从客户端迁移到服务端的关键点在于控制权的转移。将之前麦位数据从B端产生,通过透传通道推送到C端消费。变成由B端和C端发送数据到服务端,服务端进行计算,存储和推送。同时架构升级过程中,需要兼容新老版本组合情况,保证程序向后兼容,不影响线上产品已有功能。
图片
众所周知,兼容性与代码逻辑和数据结构密切相关。新的代码会产生新的数据结构,同时要兼容老的数据结构与逻辑。老的代码处理不了新的数据结构,需要通过版本做访问隔离。迁移过程中代码与数据组合情况与测试点:
服务端数据 | 服务端代码 | B端版本 | C端版本 | 说明 |
老 | 新 | 老 | 老 | 兼容测试 ,分平台测试(PC直播姬,ios直播姬,Android直播姬,ios粉开播,Android粉开播) |
老 | 老 | 老 | 老 | 回归测试 |
老 | 老 | 新 | 老 | 不存在, 数据版本会和B端版本保持一致 |
老 | 新 | 新 | 老 | |
新 | 新 | 新 | 老 | 功能测试 |
新 | 老 | 新 | 老 | 人为使用姿势问题, 在未发布服务端代码的环境使用新版本 |
麦位管理功能统一到服务端后,带来的好处是业务扩展更容易,方便我们扩展更多的功能。但同样也因为所有数据都需要到服务端来获取,对于服务端的接口性能和实时性带来了巨大的压力。特别是当存在类似于赛事或者活动等大型热门房间,百万用户同时在线时,实时状态同步将是一个巨大的挑战。
图片
我们通过组合使用多个渠道,利用各自特点来平衡实时性与性能开销之间的矛盾。
经过上述一系列调整以后, 业务架构基础性比较稳定,开始探索语聊房内营收相关玩法。
图片
图片
通过在已有的送礼链路上,叠加玩法生命周期管理,分数计数,状态转移。构建玩法生态。
图片
图片
一个成熟的系统是一定需要一个无死角的观测能力,在任何领域都是这样。医疗、航空,包括人体系统。
将应用系统监控进行分层,可以分为如下几层:
1、基础设施监控(CPU、内存、网络、机房等)。这一层是任何计算机应用的基础依赖。
2、请求和成功率监控(QPS/TPS、RT、SLO等)。这一层主要是观测请求的数量和成功率。
3、业务监控(业务漏斗转化、业务状态扭转等)。这一层主要是观测业务系统内部的逻辑分支。
一般系统监控上述1、2层基本是默认都有的平台设施。作为业务系统,只有1、2层是不够的,1、2层监控无法感知业务异动。简单讲,如果你写了一个在业务上有问题的分支代码,此代码不会产生任何错误code。这类问题,可能1、2层监控是毫无察觉的,因为1、2层不观测这些。业务监控,一方面可以感知业务异动,还可以感知到1、2层故障带来的业务影响。
图片
用户看到的产品功能,可能只是冰山上面很小的部分。冰山下面部分是一个庞大的系统,会跨越多个微服务单元。语聊房是非常典型的多技术栈(app、pc、web、RTC、comet长链、业务后端等) ,多业务单元(语聊房业务后端、看播、开播、审核-工程、审核工作台、视频云、RTC等)合作的超大型项目。
人工排查一个问题的成本是非常高的。在项目初上线时,当时的相关系统配套并不完善,一个小问题都要把业务链条上的所有环节的人都要拉上一起排查。通过问诊平台可以一键全链路观测到所有节点。
图片
图片
可以看到一个用户的所有生命周期,对于排障基本可以节省90%时间。
上面介绍完语聊房业务形态和系统架构一年以来的变迁。我们了解了因为产品形态调整,架构需要调整来适配新的产品形态。有些调整短期是好的,但长期又花了更多时间处理新来的问题有些调整踩了一些坑。为了技术现状或者工时排期要求原因导致的架构妥协,然后事后又付出更多的工时成本迁移。回过头来想想是什么原因导致我们的已有架构在变动产品形态调整时,总是在偿还已有技术债务,或者自己挖了新坑自己再去填坑?
互联网从业人员可能最讨厌的一个词就是“变化“。产品需求变了,导致技术方案需要调整,代码需要重写。代码改动了,测试用例又得重新设计。工作量增加又导致项目时间调整,轻则软件bug,重则项目失控。
那么有没有通用的万能法则可以指导我们进行架构演进的,以不变应万变,真正又好又快?看过或者听过“没有银弹“这句话的人,可能已经知道问题的答案了。但是为什么没有呢?探讨一个可以解释万事万物的万能法则,不管是谁听了都会热血澎湃。古人也不例外,早在两千多年前,古希腊哲学家亚里士多德认为在各种物理规则的基础上,还有一种东西可以统辖和解释所有的物理规则。在他的作品集中,把他对逻辑、含义和原因等抽象知识的讨论编排在他讨论物理学的书册《自然学》之后,并给这些讨论一个标签:《在自然学之后》(τ? μετ? τ? φυσικ? βιβλ?α)。从古希腊文翻译到英文,于是就有了Metaphysics这个词,看到这个词就会联想到最近很火的Metaverse,还有改名为Meta的Facebook。如果按照元宇宙的译法,那么metaphysics就可以翻译为“元物理”。但日本人在翻译这个词语时,从《易经 》找到了 “形而上者谓之道,形而下者谓之器”一词。于是Metaphysics便翻译成了大家耳熟能详但又不太了解的“形而上学”这一词。
不管是亚里士多德的“本原“还是老子的“道“,都认为事物的现象背后必定有一个统一的规律,可以统辖和解释所有的规则,阐述天地世间万象变化。基于这种思想,就有了“格物致知”的说法。既然道存在于万事万物之中。那么同样的万事万物中也都包含着道,也就是说只要把一个事务研究透了,自然也就获得了道。王阳明和他的学生钱德洪一起切磋学问,二人都认为要做成儒家的“圣贤”,就得格尽天下之物,于是就指着园内的竹子,让钱德洪去看。钱德洪一入夜就去穷究竹子的道理,竭尽心思想了三天三夜,也没格出个所以然,还积劳成疾了。于是王阳明亲自去格竹,也是竭尽心思早晚想不到竹子的道理,到了第七天,也因劳思而得病。
按照我们现代人的思维里,即使把竹子研究的再好,也造不了汽车。同样的竹子格的再好,也成不了圣贤。世界上也不存在静止的,孤立的“道“能够解释万事万物。这件事也成为王阳明日后心学思想体系建立过程中的重要事件。心学主张知行合一,按照通俗的话也就是讨论“认识”和“行动”的关系。
我们都知道,不管是做技术架构,还是代码结构组成方式,都反应了我们对产品的认知。如果没有恰当的认知,就不可能做出合适的架构,甚至可能会导致项目彻底失败。既然没有永恒不变的“道“,那我们应该用什么样认知来指导我们的行动呢?
这个问题在《实践论》中做出了回答:
通过实践而发现真理,又通过实践而证实真理和发展真理。从感性认识而能动地发展到理性认识,又从理性认识而能动地指导革命实践,改造主观世界和客观世界。实践、认识、再实践、再认识,这种形式,循环往复以至无穷,而实践和认识之每一循环的内容,都比较地进到了高一级的程度。这就是辩证唯物论的全部认识论,这就是辩证唯物论的知行统一观。
下面我将结合语聊房实际业务聊聊到对这几个阶段的认识。
众所周知,互联网产品是对我们生活或者生产过程中的抽象,除了极少数天才级的产品大师能够设计出引领人类社会的产品,大多数的产品还只是打破时间和空间的限制,满足人类社会的需求。
下面是我们常用的一些产品对现实生活中的实现。
图片
图片
图片
图片
同样的道理,语聊房这个产品也不是凭空产生的,聊天的需求一样存在于现实生活中
图片
图片
现实世界的场景是个例化的,与实际产品还有很大的鸿沟。首先了解现实世界的运行逻辑,具有初步的感性认识后,我们需要进一步抽象成通用型的业务模型。然后通过观察竞品的类似产品的实现也有助于帮助我们建立感性认识。经过这个阶段,我们会对架构产生初步的概念。
现实的情况和竞品的实现帮助我们建立初步感性认识,通过对这些感性认识的整理,加以概念定义,类型归类,逻辑重组等阶段就能建立初步理性认识。但不同竞品的商业模式,品牌调性以及完成度都会与我们千差万别,直接全盘照抄往往是失败的前兆,同时工期上也是不可接受的。通过与产运规划对齐,理清实现路径,帮助我们了解每个阶段的主要目标和主要矛盾。
图片
到这个阶段,我们已经对所要做的事情有了初步的理性判断,这有助于我们下一步架构落地。
抽象是指从具体的事物中抽离出共性的概念或特点,将它们提炼出来形成一种抽象的概念或理论。计算机领域有一句名言,“任何问题都可以通过增加一层间接的中间层来解决“。原因就在于人的认知能力是有限的,抽象有助于降低我们理解复杂事物的成本。但是抽象同样也会带来模糊实现的问题。当我提起“马“, 我可能指的是河马,你脑海中可能想到的是斑马。所以我们需要,通过显示的定义概念来统一语言,帮助我们更好地沟通和理解彼此的意思,才能做到团队理解一致性。在领域驱动设计中,抽象和统一语言是非常重要的概念,它们可以帮助我们更好地理解和设计领域模型,从而创建高质量的软件系统。
语言只有在特定语境中才有意义,在不同语境中同一个概念往往会有不同的意义。特定语境往往对应确定的业务模型,比如同样是“订单”,在秒杀领域,拼单领域,团购领域等往往代表着不同的业务流程和现实意义。在代码实现上,我们通过package,class等方式来进行模块划分。在领域驱动设计中,我们通过限界上下文来保证领域内概念的一致性。
图片
在不同的BoundContext(限界上下文)中,同样的一个名词代表不同的业务模型或者模型的不同维度。
拿【语聊房间】来说,在内容安全Subdomain → 审核BoundContext中,这个【房间实体】是有着特定字端的(房间管控等级、是否需要认证手机号、是否大陆身份等)。这些字端是【语聊房间】概念实体在安全领域上下文中的特定表现。在整个开发架构上,我们也是参考领域来划分每个模块的职责边界。
图片
领域模型是逐步下沉的业务载体,彼此独立。最终通过在usercase 层 application来组装编排领域模型。
对业务问题空间求解是软件开发的首要问题。通过对问题空间的不断定义与探索,我们映射得到对应解空间的系统架构与应用架构。这一阶段主要目标是持续交付我们的架构。
图片
在网上流传广泛的介绍MVP的图。
先制作出一个最小可行的产品(例如小型滑板车或自行车),测试用户对其概念的认可程度,再根据反馈来决定如何进一步完善产品。MVP策略的优点在于试错成本低速度快风险低,能够满足快速迭代的需求。
随着架构的演进,我们需要有合适的评估机制,来评估变化对架构的影响,防止架构随着时间推移而退化。架构由很多维度构成,包括性能,安全性,稳定性,代码规范等,对于不同的维度,我们需要建立不同的指标来评估。
在开发架构管理上,进行代码级别的保障,包括以下措施:
在CICD上增加代码质量检查,保证代码符合规范:
图片
在自动化测试平台上,与测试团队共建自动化测试用例,覆盖全部关键场景用例,保证每次代码变更不会产生预期外的业务影响:
图片
Devops方面,对关键接口P999响应时间进行监控,保证系统性能不劣化:
图片
每日自动巡检,保证服务健康度:
图片
参考文章
朱德江哔哩哔哩资深开发工程师
王清培哔哩哔哩资深开发工程师
赵书彬哔哩哔哩高级开发工程师
TOP