背景 | 腾讯会议于2019年12月底上线,两个月内日活突破1000万,被广泛应用于疫情防控会议、远程办公、师生远程授课等场景,为疫情期间的复工复产提供了重要的远程沟通工具。上线100天内,腾讯会议快速迭代20个版本,满足不断增长的用户需求,多次登顶APP STROE中国区免费榜总榜No.1。
极速增长的会议视频流质量上报数据,让腾讯会议视频流质量分析系统经受着巨大的考验。为了向全网用户提供高效稳定的服务,以及对重要的大型会议进行保障护航。在充分讨论调研了大量方案后,腾讯会议视频流质量分析团队与腾讯云Elasticsearch(下文简称“ES”)团队展开合作,积极探索云端数据分析引擎架构的更多可能。
伴随爆发增长的用户需求,腾讯会议的日活也在不断地刷新着历史记录。
从1月29日起,为了应对疫情下远程办公的需求,腾讯会议每天都在进行资源扩容,日均扩容云主机接近1.5万台,8天总共扩容超过10万台云主机,共涉及超百万核的计算资源投入。
在会议中,偶尔存在会议实时音视频流卡顿、音视频不同步等会议质量问题,造成上述问题的可能因素比较多,当前运行的网络有丢包或连接不稳定的情况就是其中一种。
为了帮助运营团队快速精准地定位分析问题,需要大量运行时的数据支撑,如网络相关的入网类型、码率、丢包率、网络切换、ip切换等数据,以及客户端相关的CPU使用率、内存使用率、操作系统版本、产品版本等数据信息。
因会议是一个多用户参与交互的过程,定位问题不仅需要涉及到单个用户的情况,也要从房间的维度洞察各个用户之间的联系。通过腾讯会议客户端实时上报的视频流运行时信息,运营团队可以快速地对单用户、单房间的视频流会议质量情况有直观的了解,为分析问题提供了数据支撑。
除了数据的实时上报,另一方面,借助多维分析,我们还可以在实时数据中挖掘出异常情况。如某个地区大面的卡顿,某个版本出现特定的问题等。通过dashboard或数据报表的形式,帮助运营团队及时掌控全局情况,快速发现潜在问题。
快速增长的用户数以及不断刷新纪录的同时在线房间数,让腾讯会议视频流质量分析系统经受高压力,给运营团队及时排查用户问题带来了巨大的挑战。深究根本原因,是因为视频流分析系统在如此高压力、高吞吐的场景下,写入性能严重不足导致。由于系统最关键的部分,是一个基于lucene自研的搜索引擎,扩容能力比较差,依赖于研发团队针对业务的优化。在数据量暴涨的背景下,不能进行快速扩容以满足需求。
为了保证全网腾讯会议用户都能高效稳定地进行会议沟通,保证运营团队能对用户会议中的卡顿等问题及时进行排查,以及对重要的大型会议进行保障护航。在充分讨论调研了大量方案后,腾讯会议视频流分析团队决定从原来的自研数据分析系统,紧急迁移至使用腾讯云ES作为数据分析引擎的架构上。
在进行架构方案选型的过程中,主要从以下几个方面进行了考虑:
腾讯会议视频流质量数据上报至ES的流量,峰值高达1000+w/s。在如此高吞吐的极限写入场景下,能持续稳定地提供数据读写服务,确实是一个挑战。在腾讯内部,也存在着类似腾讯会议视频流质量数据上报的这样的大批量、大吞吐写入场景,在使用过程中,业务部门经常会发现写入性能不高,且CPU使用率不稳定的问题,资源利用率严重不足。
腾讯云ES内核团队对类似的高压力写入场景进行了追踪及分析,并在同样的场景下进行了多个方案的压力测试,发现ES单节点的压力写入测试与lucene基准的写压力测试有较大的差距。通过对调用火焰图进行分析并对比测试translog的一些调优参数,最终定位发现translog文件的rollGeneration操作与flush操作有互斥,两个操作互相频繁的加锁干扰,一次rollGeneration操作的平均耗时达到了570ms,在高压力写入场景下,频繁的rollGeneration会严重影响写入性能。
在与社区进行了大量的讨论及压测之后,最终确定了优化方案:采用rollGeneration的过程中,在关闭原translog文件之前,先执行一次flush,巧妙地避免了操作的互斥。这个方案对流程的改造最轻量优雅,且优化后的写入性能提高了20%以上。这部分优化的代码经腾讯内部的业务验证后,最终整理提交回馈给了社区。由于这个优化在ES写入的所有场景下均适用,且对性能的提升非常显著,Elastic的创始人对该PR高度赞扬,并给腾讯云总裁发来了公开感谢信。
腾讯云ES在社区开源的内核之上,根据云上的内外部业务的场景案例积累,做了大量的内核优化。除了上面介绍的translog的优化,还有带“_id”的写入操作剪枝优化、查询计划优化等等,满足了客户在性能方面的需要,并积极将一些通用的优化提交至社区,截至目前为止,腾讯云提交的pr约有50+被合并到了主干。
由于原自研的数据存储查询引擎在设计之初并未预估到视频流数据的暴增,之前的分布式架构在扩容的操作中依赖较多的人工操作,需要业务层感知计算分片路由等过程,且分片数据不能自动迁移。在疫情期间,继续沿用原有的架构很难满足快速扩容的需求,导致视频流上报数据写入慢,数据大量堆积在队列中。
腾讯云ES有着完善的分布式设计,单个集群支持扩容至数百甚至上千个节点。有可靠完备的选主算法逻辑以及sharding路由策略做保障。数据分片支持数据冗余,防止由于硬件故障导致的数据丢失,并提升集群的读性能。同时,数据可以按索引维度设置数据分片及副本数目,可以根据业务特点更灵活地设置合理的数值,降低了数据存储的成本。
腾讯云ES依托于腾讯云CVM进行构建,资源池充足,仅在疫情刚开始的一个月内就扩容了3W核,集群弹性伸缩的便利性得到了验证。扩容节点数目及变更节点配置等均为自动化功能,支持控制台及API一键操作,扩容过程平滑,不影响业务读写。
在集群扩容的场景中,相信很多业务都遇到过使用ES进行扩容后,大量新写入数据有读写热点,都堆积到新加入的节点上,导致节点被打挂,影响整个集群的写入性能。随着数据的增长,腾讯会议业务也扩容至千级节点的规模,那么上面的问题在腾讯云ES中是如何解决的呢?
社区开源版本的ES,在shard分配的时候,会优先考虑各个节点上已有的shard数量,目的是尽量保持各个节点的shard和数据的均衡。当集群数据在各节点之间已经处于balance状态时,这时候增加新节点。由于新节点上面的shard数最少,就会造成上面的问题,新写入的数据都分配在新的节点上,造成新的节点压力过高而宕机。
为了帮助客户解决上述问题,腾讯云ES内核团队在原有allocationDecider责任链基础上,开发了一个新的decider分配算法,将一个index的所有分片,尽量平均地分配在各个节点上,使得新写入数据的读写流量被均匀分担,避免了新写入数据的访问热点。
腾讯会议视频流质量数据分析系统,从2月份开始进行ES架构的方案切换开始,写入吞吐从5w/s不断攀升,现已达到100w+/w。业务的突发增长有时候来的很突然,并不能在前期做有效的评估。社区中的很多用户也遇到过类似的问题,由于没有预估到业务突发的增长,并且在业务层没有做好服务降级等机制,导致突发的写入查询流量打崩了整个集群,使ES服务甚至整个业务长时间不可用。那么,在类似腾讯会议这样的场景中,是怎样解决ES突增写入查询流量的问题的呢?
例如早期我们内部一个日志集群,写入量一天突增 5 倍,集群多个节点 Old GC 卡住脱离集群,集群 RED,写入停止,这个痛点确实有点痛。我们对挂掉的节点做了内存分析,发现大部分内存是被反序列化前后的写入请求占用。我们来看看这些写入请求是堆积在什么位置。
ES high level 的写入流程,用户的写入请求先到达其中一个数据节点,我们称之为数据节点。然后由该协调节点将请求转发给主分片所在节点进行写入,主分片写入完毕再由主分片转发给从分片写入,最后返回给客户端写入结果。右边是更细节的写入流程,而我们从堆栈中看到的写入请求堆积的位置就是在红色框中的接入层,节点挂掉的根因是协调节点的接入层内存被打爆。
针对这种高并发场景,我们的优化方案是服务限流。除了要能控制并发请求数量,还要能精准地控制内存资源,因为内存资源不足是主要的矛盾。另外通用性要强,能作用于各个层级实现全链限流。
在很多数据库使用场景,会采用从业务端或者独立的 proxy 层配置相关的业务规则的限流方案,通过资源预估等方式进行限流。这种方式适应能力弱,运维成本高,而且业务端很难准确预估资源消耗。
ES原生版本本身有限流策略,是基于请求数的漏桶策略,通过队列加线程池的方式实现。线程池大小决定了处理并发度,处理不完放到队列,队列放不下则拒绝请求。但是单纯地基于请求数的限流不能控制资源使用量,而且只作用于分片级子请求的传输层,对于我们前面分析的接入层无法起到有效的保护作用。原生版本也有内存熔断策略,但是在协调节点接入层并没有做限制。
我们的优化方案是基于内存资源的漏桶策略。我们将节点 JVM 内存作为漏桶的资源,当内存资源足够的时候,请求可以正常处理;当内存使用量到达一定阈值的时候分区间阶梯式平滑限流。例如上图中浅黄色的区间限制写入,深黄色的区间限制查询,底部红色部分作为预留 buffer,预留给处理中的请求、merge 等操作,以保证节点内存的安全性。
限流方案里面有一个挑战是:我们如何才能实现平滑限流?因为采用单一的阈值限流很容易出现请求抖动,例如请求一上来把内存打上去马上触发限流,而放开一点点请求又会涌进来把内存打上去。我们的方案是设置了高低限流阈值区间,在这个区间中,基于余弦变换实现请求数和内存资源之间的平滑限流。当内存资源足够的时候,请求通过率 100%,当内存到达限流区间逐步上升的时候,请求通过率随之逐步下降。而当内存使用量下降的时候,请求通过率也会逐步上升,不会一把放开。通过实际测试,平滑的区间限流能在高压力下保持稳定的写入性能。
我们基于内存资源的区间平滑限流策略是对原生版本基于请求数漏桶策略的有效补充,并且作用范围更广,覆盖协调节点、数据节点的接入层和传输层,并不会替代原生的限流方案。
用户数暴增,留给系统验证切换的时间非常短,这要求我们必须使用一种简单快速的解决方案。需要在一周之内输出适用方案,并进行线上数据的切换。如原架构使用kafka队列做数据的投递,由自研的消息接入服务进行消息的接入、清洗并最终写入自研的数据存储分析服务。由于时间紧迫,新的方案需要尽量保留原有架构的大部分基础设施,并做尽量少的代码开发改动。
在这方面,ES的社区生态做得非常完备。从采集端、收集端到存储都有一整套解决方案。通过logstash的易用性和强大的生态插件,可以快速替代原有的自研数据接入组件,进行数据的清洗转换等ETL过程。如原有架构中使用的kafka,在logstash中就已经包含了相应的input插件。并且有大量数据格式的解析插件支持,对于数据的一些解析、过滤、清洗等操作可以直接在logstash的pipeline中进行简单的配置即可,基本上是0开发量。
丰富的各语言SDK,方便快速的对视频流分析平台前后台进行快速切换,实际从代码修改到上线完成只用了一天的时间。同时,ES社区也比较活跃,国内有10万+的开发者参与其中,问题都可以比较快地得到回复和解决。在此,也特别感谢ES的研发团队及一线运维团队,在疫情期间,对腾讯会议进行了7*24小时的支持,并对于使用ES的一些疑难问题给出了大量的解决方案。
在腾讯会议视频流质量数据分析系统全部切换至ELK架构之后,达成了100w+/s的数据写入性能要求,数据从入队列到可被S搜索到的延迟时间从小时级别缩短至了秒级,保证了业务数据同步的实时性要求以及运营分析系统的查询延迟要求。
截止到目前,腾讯会议集群随着业务的增长已平滑扩展至数百节点,百万核数规模,满足了业务数据增长下的扩容需求。
并且,得益于内核稳定性方向的大量优化,腾讯云ES的服务稳定性上达到了99.99%,保证了万亿级别数据量高压力使用场景下的服务稳定性,为腾讯会议的运营分析及问题排查保驾护航。
腾讯会议的普及与腾讯云ES在数据搜索查询、高并发、弹性扩展以及安全领域的技术能力密切相关。腾讯云ES在腾讯会议视频流质量服务上的成功实践,也为视频会议这个细分行业领域提供了一个优秀的范例,拓展了行业解决方案的思路。
未来,腾讯云ES仍将不断迭代,针对用户需求,不推打磨技术和产品,持续输出稳定可靠的Elasticsearch服务。