NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

弹幕系统更新的血与泪

  • 2019-11-13
  • 本文字数:3220 字

    阅读完需:约 11 分钟

弹幕系统更新的血与泪

16 年是直播浪潮兴起的元年,许多互联网公司的业务都开始涉足直播内容模块。我目前所在公司接手的第一份工作,就是直播业务中的弹幕系统优化。随着公司直播业务的变化,弹幕系统从最初的版本到后来优化了三四个版本,这个过程大概持续了一年的时间,本文将从我司早期的弹幕系统开始给大家介绍整个更新过程的“血与泪 ”。

早期弹幕系统

一、基本状况

1.由 PHP + Gateway 框架编写。


2.所有的 Client ID 存放在 Redis 里面。


3.最初由三台机器挂载在 LVS 系统后方提供服务。


4.使用多进程的方式,开启多个 worker 进程来处理消息传递内容。

二、存在的问题

1.内存占用量巨大,单机(4 核 8 G 配置)承受 500 左右的 Client 就会达到内存上限。


2.每次发送消息的时候,每台机器都需要从 Redis 里面拿取对应房间的所有 Client ID;并发高时,Redis 的单进程处理效率和内网带宽就成为瓶颈 。


3.单机的并发处理能力被消息处理的 worker 进程数量限制。同时开启过多的进程,也是对系统资源的格外浪费。


4.单房间超过 2000 人的时候,消息的延迟有可能会达到 1 分钟左右,这是极其严重的问题。

三、临时改造

由于需要解决的问题比较紧迫,所以快速做了一些逻辑上的改变和业务层面的取舍:


1.对 Redis 的实例进行了拆分,使用了双机,单机 4 实例的方式,分散了 Redis 的压力。


2.对消息处理 worker 进程的逻辑做了一些修改,限制单位时间内进行广播的消息数量,多余的消息会被丢弃 。


3.对于已经完成了直播进入点播状态的房间,额外启用了另外一套弹幕系统来进行分流。


4.单个房间切成多个房间进行消息处理。

四、改造之后的效果

1.Redis 压力大幅度降低;


2.单机 IO 性能压力降低;


3.同样数量的机器,可以承载更多的直播房间个数。



但是,根本问题并没有得到解决。在临时解决压力问题之后,我们需要花一些时间来重新对弹幕系统进行分析,按照分析后的需求,对新的弹幕系统进行重构。

新的弹幕系统

一、新弹幕系统面临的挑战

1.单房间人数较高,依照我们公司直播情况,单房间 5 - 10 万人同时在线是会出现的。


2.由于直播内容等情况造成的某时间段用户暴涨。


3.需要尽可能实时到达,延迟过高的话会大大降低互动的实时性。


4.每一条消息,都要递送大量的长连接。


5.大量长连接的维护机制。


6.在运营的过程中,需要处理用户黑名单、IP 黑名单、敏感词等需求。

二、新的弹幕系统需求

1.由于内存的管理对于 PHP 来说算是一个短板,对于大并发且长时间稳定不需要经常更新维护的系统来说,并非最好的选择,因此选一门合适的语言是必须的。


2.分布式支持,可以快速的横向扩展,单房间人数可以支持到十万级别。


3.可以方便快捷的对系统进行第三方消息的发送(例如礼物信息、系统通知等)。


4.尽量使用本地内存管理来记录房间内客户端连接,剩下大量的数据交互和查询时间。


5.并发支持消息广播,提高广播效率。

三、新弹幕系统版本的改造方法

1.选择当前正红且对高并发支持良好的 Golang 作为开发语言。


2.使用开发语言进行客户端连接的管理,且每台机器只管理自己收到的连接请求。


3.使用并发的房间内广播逻辑,同时对多人进行广播。

新弹幕系统改造的相关经验

下面先对一个模块细节进行分析,然后进一步分析模块上层的调度逻辑。

一、房间管理

type RoomInfo struct {     RoomID         string      //房间ID     Lock           *sync.Mutex //房间操作锁     Rows           []*RowList  //房间多行Slice     Length         uint64      //当前房间总节点数     LastChangeTime time.Time   //最后一次更新时间 } type RowList struct {     Nodes []*Node //节点列表 }
复制代码


由于每个房间都有自己的 ID,客户端建立连接之后,就会被放到一个大厅房间里面。接着,客户端自己提交 RoomID 上来,连接会被重新连接到对应的房间里面。 每个连接在建立之后,都会被包装成一个 Node,放到 Rows 里面。


type Node struct {     RoomID       string     ClientID     int64     Conn         *websocket.Conn     UpdateTime   time.Time     LastSendTime time.Time //最后一次发送消息时间     IsAlive      bool     DisabledRead    bool//是否已经被关闭了发言权限}
复制代码


每一个 Node 中,都有一个 IsAlive 来表示连接是否成功。如果连接断开,或者因为其他原因强制停止服务的话,会修改此标记状态。然后由定时的处理机制将此连接关闭并从内存中清除。


Rows 的本质就是一组事先设定了长度的 Node Slice。发送消息的时候,每一组 slice 使用一个协程来顺序发送。同一房间内的链接,就可以依照 slice 分组进行并发发送。 发送的时候,会使用锁将整个房间锁住,以防止并发情况下同一连接混入两条信息。

二、消息管理

var messageChannel map[string]chan nodeMessage func init() {     messageChannel = make(map[string]chan nodeMessage) } func sendMessageToChannel(roomId string, nm nodeMessage) error {     //如果房间不存在,创建一个房间     if c, ok := messageChannel[roomId]; ok {         c <- nm     } else {         //创建房间通道         messageChannel[roomId] = make(chan nodeMessage, 1024)         messageChannel[roomId] <- nm         //创建房间实例         roomObj := &RoomInfo{}         roomObj.RoomID = roomId         roomObj.Rows = make([]*RowList, 0, 4)         roomObj.Lock = &sync.Mutex{}         //创建新的协程来监控房间         go daemonReciver(messageChannel[roomId], roomObj)         go timerForClean(messageChannel[roomId])         //如果是大厅的话,启动大厅清理协程         if roomId == "" {             go CleanHall(roomObj)         }     }     return nil }
复制代码


以上是关于弹幕信息传递的一部分代码。首先,每一个房间,都有自己的消息通道,所有的这些通道根据 RoomID 为 key,记录在一个叫做 messageChannel 的 map 里面。 每次收到消息的时候,都直接把消息丢到 channel 里面,就可以了。(后面由守护协程来处理)如果没有房间通道的话,就建立房间的通道 channel,并启动每个房间的一系列协程。

三、服务器管理

这里的方案比较简单,其实就是建立一个上一层的聊天室即一个房间,所有的服务器都会主动连接到这里,每一个服务器收到的信息,就会在这个房间里面广播到别的机器去。

四、守护协程们管理

守护协程处理很多琐碎的事情,保证房间内信息的正常分发以及房间连接的正常管理。各个守护协程的功能如下:


1.消息发送协程:每个房间配备一个,从 channel 里面获取到要发送到本房间的消息,然后在并发调用各个 RowList 的发送消息机制。


2.房间整理协程:因为会有连接断开、房间更换等修改 Node 状态的行为,所以定期会有房间整理协程来进行节点整理,删除当前房间无关的节点等以提高消息的发送效率。


五、测试相关

运行环境: 云主机 8 核 16 G 实例


操作系统: Centos 7(未进行系统优化或参数调整)


测试内容: 单机建立 15000 websocket 连接,并且发送消息,进入指定房间(所有连接进入同一房间)。一个客户端进入房间,发送一条消息,经过敏感词处理、IP 和用户黑名单处理,然后被广播到所有节点。


测试结果如下:


CPU 占用: 保持在 5% 以下


内存占用: 2GB(包括操作系统本身开销)


网络占用: 峰值 10Mb/s 左右


发送效率: 15000 节点广播,100ms - 110ms 左右。


根据测试结果计算:


完全可以在 8 核 16G 的机器上,实现无压力运行 50K 并发,峰值接近 60 - 70K 的处理能力。

六、更多分享

我目前正在尝试把完成这套弹幕系统的基本功能开源出来。已经提取出来了一部分,感兴趣的读者可以通过链接查看。


弹幕系统给视频直播/点播增加了更多内容的互动娱乐性质,从最初的 A 站 B 站发展到现在各主流视频网站 APP。如何健康高效的管理弹幕系统,也是当下视频行业需要重视的一门技术活。


本文转载自公众号 UCloud 技术(ID:ucloud_tech)。


原文链接:


https://mp.weixin.qq.com/s/CXp6Q2pxo3Pc7yQg4gM1vw


2019-11-13 11:57775

评论

发布
暂无评论
发现更多内容

Mysql 生成排序序号

六月的雨在InfoQ

8月月更

彻底搞懂云桌面配置及实践踩坑【华为云至简致远】

神奇视野

Python 科技

NFT盲盒挖矿DAO智能合约dapp系统开发详情

开发微hkkf5566

交大医学院临床研究中心如何将 ModelWhale 应用于临床医生教学、研究丨数据科学 x 临床医学

ModelWhale

人才培养 数据科学 低代码平台 教学 临床医学

一次做数据报表的踩坑经历,让我领略了数据同步增量和全量的区别

百思不得小赵

数据同步 增量同步 全量同步 签约计划第三季 8月月更

生物统计师与临床医生协同研究使用的低代码洞察平台丨数据科学 x 临床医学

ModelWhale

团队协作 Jupyter Notebook 数据科学 低代码开发 临床医学

利用java实现视频人像分割及视频背景替换

夏夜许游

Java 图像分割 视频人像分割 背景替换

基于ModelArts的动漫头像自动生成丨【华为云至简致远】

科技云未来

华为云ModelArts

多图预警!华为 ECS 与 阿里云 ECS 对比实战【华为云至简致远】

科技云未来

华为云 虚拟私有云VPC ECS

使用华为HECS云服务器打造Telegraf+Influxdb+Grafana 监控系统【华为云至简致远】

科技云未来

Grafana Influxdb 系统管理 开源监控系统 提高效率

【实战】Next.js + 云函数开发一个面试刷题网站

狂奔滴小马

Serverless React

云硬盘EVS详解以及如何用与避坑【华为云至简致远】

神奇视野

Python 后端 云服务 科技

阿里云 EMAS Serverless 升级发布

移动研发平台EMAS

小程序云开发 阿里云 Serverless 开发者 云开发

利用华为云ECS服务器搭建安防视频监控平台【华为云至简致远】

科技云未来

nginx securecrt RTMP SSH工具

DeepLink在转转的实践

转转技术团队

ios android 客户端

开源一夏 | 打工人的第25天-曾经的考研人

Amazing_eve

#开源

ffplay视频播放原理分析

百度Geek说

音视频

为什么Spring Boot项目加上就可以更新版本?

冉然学Java

程序员 源码分析 springboot Java 分布式 Java core

2022最新发布超全的Java面试八股文,整整1700页,太全了

Java工程师

Java 面试 八股文

手摸手带你完成智慧路灯构建及避坑【华为云至简致远】

神奇视野

Python 科技

阿里大佬力荐的这份“Spring全家桶”太强了,在轻松中学习掌握

Java工程师

Java spring spring-boot

兆骑科创创业大赛,双创服务平台,线上直播路演

兆骑科创凤阁

使用前端技术实现静态图片局部流动效果

dragonir

CSS JavaScript html 前端 SVG

上海web前端培训课程

小谷哥

快速定位线上慢SQL问题,掌握这几个性能排查工具可助你一臂之力

IT学习日记

MySQL性能优化 数据库优化 MySQL 数据库 签约计划第三季 explain关键字

大数据程序员培训学习多长时间可以找工作

小谷哥

Jupyter Notebook 交互式编程 & 低代码拖拽式编程 | 数据科学生态下的理想平台

ModelWhale

云原生 Jupyter Notebook 数据科学 低代码开发 协作平台

R7 6800H+RTX3050+120Hz 2.8K OLED屏,无畏Pro15 2022开启预售

科技热闻

开源一夏 | 阿里云物联网平台之极速体验

六月的雨在InfoQ

阿里云 开源 物联网 8月月更

兆骑科创高层次人才引进平台,创新创业赛事活动路演

兆骑科创凤阁

高性能创作本,日常修图剪辑选华硕无畏Pro15 2022完全足矣!

科技热闻

弹幕系统更新的血与泪_文化 & 方法_大妖_InfoQ精选文章