微博直播场景下,如何实现百万并发的答题互动系统

3,125 阅读8分钟

内容来源:2018 年 09 月 07 日,新浪微博系统开发工程师陈浩在“RTC2018 实时互联网大会”进行《微博直播场景下百万并发的消息互动系统》演讲分享。IT 大咖说作为独家视频合作方,经主办方和讲者审阅授权发布。

阅读字数:2867 | 8分钟阅读

观看嘉宾演讲视频回放及PPT,请点击:t.cn/Ew1WrzR

摘要

本次分享主要介绍微博直播场景系如何实现答题互动系统的技术方案。

直播答题简介

传统的手机直播主页面一般由直播音视频流和下方的消息互动两部分组成。直播答题不同的地方仅在于引入了一个答题互动的方式。主持人的口令能够控制客户端行为,也就是答题的发起由他决定,答对的用户会获得奖金激励,每轮答题结束后会立刻展示出实时数据,比如每个选项的选择人数。

技术挑战分析

直播答题的核心需求是在海量用户同时在线的情况下,确保每个用户的答题画面都能展现,并能在直播过程中流畅的参与答题,最终分得奖金。

高并发

在直播答题中,海量用户要在首题下发的前几分钟全部成功加入房间,在答题的10秒倒计时内又会有海量用户同时提交答案,答题的过程中会产生海量答题的消息下发。这三个场景都存在一个明显的波峰,给我们带来的技术挑战在于海量数据高并发的处理能力。

可靠性

成功展示答题画面是用户参与答题的首要条件,每轮答题都可能淘汰一批参与用户,正常情况下只有在用户答错的时候才会被淘汰。但如果由于未展示答题画面而产生淘汰,那就是技术问题了,而我们的硬性要求是不能因为技术原因导致用户淘汰。所以这里的技术难点是海量题目消息下发的成功率以及答题画面的成功展现。

实时性能

每一轮的答题只有10秒的倒计时,因此要确保在这个时间内确保能展示画面给用户,答题结束后需要实时展示出统计结果。这个技术难点在于极短时间内对海量数据的实时下发和统计分析。

答题设计方案

我们为解决问题所设计的技术方案是基于微博直播现有的技术架构,上图是微博直播互动的架构图,核心在于短连和长连这块。短连接使用私有Wesync协议,支持SSL,它是支撑百万下发消息互动的核心服务。长连负责维护消息可通道可动态扩缩容,并支持用户分组。

其实整个方案设计的核心是解决答题信令通道选择问题,也就是如何下发题目的消息,让用户在短时间内收到。

方案一

我们首先想到的方案是轮询,客户端不断发起查询请求,由服务端控制是否返回结果。不过大量无用的请求会消耗带宽资源,给服务端带来了持续性的压力。同时由于和音视频流不在一个通道内,所以题目到达的时间和音视频流到达时间难以保持一致。

方案二

方案二是复用音视频流的通道,将题目信息直接放入音视频流中一起下发。这样题目下发的时间就和主持人口令发出的时间一致,用户感知不到时间差,体验要好很多。它的缺点是一旦网络抖动或者直播中断,题目信息就会丢失。

方案三


第三个方案是不依赖直播通道,转而复用互动通道下发,这样通道就独立了,不再受直播流影响。它的缺陷也是在于无法保持题目下发时间和音视频到达时间的一致。

这是3个方案的一个简单对比。可以看到采用互动通道的方式,接入难度和扩展性较好,而直播流通道的方式,扩展性就比较差,因为它依赖于音视频流。

经过综合考虑,我们最终的方案决定使用独立通道,确保答题信令不受直播流信号影响。且由于微博直播现有的互动通道能支持千万级消息下发,所以复用互动消息通道的方式是更好的选择。


上图为直播答题的整个流程图,答题和评论互动由短连服务支撑,在发题和结果展示信息方面使用pub的方式,然后经过广播消息通过长连发送给用户。

典型问题解决

实时典型问题解决

直播流经过采编设备最终推给客户是有时间延迟的,客户端收到的题目和视频流到达时间不一致。如上图所示,主持人在t0发题,用户在t2才能听到声音,而题目在t1就到达了。

对此的解决方案是在视频流的扩展字段中添加服务器时间戳,并在互动通道的下发题目消息体中也添加服务器时间戳,最终客户端通过直播流扩展字段中的时间戳匹配答题消息进行展现。

实时方面的另一个典型问题是海量数据的实时统计。首先每一轮答题都要实时计算海量用户的状态和统计结果,这些数据包括用户答案是否正确、用户是否需要复活、用户是否有复活卡。其次每一轮答题只有发题和展示答案两个指令,因此没有单独的指令告诉服务器何时处理数据,而且海量数据还需要快速计算。

一次性获取所有数据肯定是不现实的,所有我们的方案是化整为零,并行处理。当发题指令到达服务端的时候,先按照一定规则对用户进行细粒度拆分,同时根据流延时、答题结束时间计算出数据处理的开始时间,然后将切分好的用户分片和执行时间封装成任务分片置于一个延时队列中,到达执行时间后由处理机的集群拉取任务。

处理机拉取到任务后会根据用户的选择、状态以及长连地址,对用户消息进行整合,将众多小消息合并成消息体。

消息体最后会发送给长连,长连接服务收到消息体后再进行拆分,按照uid拆分下发给用户。

可靠性典型问题解决

就像前面提到的,用户在弱网环境下很容易发生丢包断连导致无法收到题目信息,从而被淘汰。既然用户的网络环境我们无法保证,那么只能去实现更稳定更快速的自动重连机制,同时服务端在一定时间内无条件重传题目消息,客户端通过消息id判重。另外下发的消息体内包含了最迟展现时间,这样即使直播流断了也能展示答题画面。

高并发典型问题解决

高并发涉及的问题有多个。首先是如何高并发提交答案,如果有百万用户在线,需10秒内提交完答案,提交请求集中在3-6秒,此时QPS峰值预估在30万。另外还要保证用户答案能在短时间内完全提交,不能请求撤回。

解决的思路也很简单,主要是实现逻辑分离和请求合并。对用户的请求处理快速返回,重逻辑往后延迟,上行保持轻逻辑。在资源端对用户的请求做合并,交给独立的线程池进行批量的提交。但流量达到负荷设计阈值的时候,自动随机重试请求做时间补偿,以保证用户都能提交答案。

第二个问题是海量消息下发,对于千万级消息实时下发的系统来说,订阅端的网络带宽压力也是巨大的。面对带宽压力,一方面可以进行消息压缩,减少传输中的冗余,另一方面是消息降量,根据用户选项对一些小消息进行分组合并。消息推送能力在于提升消息的吞吐量。

第三个问题是上线保证方面,直播答题没有灰度放量的过程,上线即全量,对系统服务承载能力需要一个量化的数据进行评估。

所有我们在上线之前要进行多轮压测以及持续的性能优化,功能开发的同时测试人员会进行测试方案设计,问题修复阶段进行单接口测试,找出接口性能瓶颈点。接口优化的同时进行整体压测环境搭建。之后的性能优化阶段,由测试人员着手单机的综合压测和全链路压测。

以上为本次分享内容,谢谢大家!