弹幕系统相关研究中期报告
zsx2015/5/30 in 记录整理 / 8 / 3430

这是本人在福州八中的研究性学习项目,闲得无聊发布在博客上,嘛,就是这样。

技术选型

服务端

先对需求进行评估,找出性能瓶颈。其服务器主要任务为接收弹幕并转发到客户端。

一条弹幕从用户手中发出,直到显示在屏幕上,其间延迟应低于1000ms。然而,用户得到其设备上“发送成功”的反馈时间,应不高于500ms。一般的网络环境中,客户端和服务端的延迟在200ms左右。也就是说,其需要在用户发送弹幕成功后立刻返回信息,将弹幕插入后台队列中,并最终向客户端主动推送。其实时性要求并不高,能在500ms里把服务端逻辑处理完即可。再加上其业务逻辑不复杂,故属于I/O密集型应用。

我选用iojs作为服务端。其异步处理的特性正好符合本项目的需求。再加上其生态环境良好,开发方便,故用之。作为Realtime应用,其需要向客户端主动推送信息。若自己在TCP协议之上扩展一套新协议,调试难度略高。故选用WebSocket协议。其数据库只担任存储数据服务,考虑到Web页面管理方便问题,选用MySQL。

客户端

既然已经选用iojs + WebSocket,那客户端自然用HTML相关技术了。传统的客户端开发技术也并不适合该项目,理由如下:

首先不考虑C / C++语言。为了保证开发效率,势必需要使用Qt等界面库,否则需要熟悉DirectX / OpenGL等相关技术。然而,考虑到可扩展性,为了实现更多的效果,势必需要使用脚本语言(如Lua)等对客户端进行扩展。开发难度高,开发周期长。所以,暂不考虑。

其次,因为该客户端有可能在Windows + PowerPoint和Mac + KeyNote下运行,所以需要考虑跨平台。很明显,为了跨平台,用C# / Java开发只能使用GTK# / GTK技术,而不能用WPF等。其开发效率相比之下显得太低。

现今,把JavaScript用在客户端开发方面的技术有不少,如nw.js / Electron。因对前者更为熟悉,故选用前者。


程序架构

服务端

iojs,通过Express中间件搭建一个HTTP服务器。得到弹幕请求后,通过关键词和用户是否被屏蔽判断是否允许发送弹幕,若否则返回错误。然后返回提交成功的信息,替换敏感词后进行进一步工作。将原始的弹幕记录到数据库,同时加入双向队列。队列大小一定。若过大,则需要从队列头出队列,原因是因为太老的弹幕没有意义。工作线程每隔一定时间自动从队列尾弹出需要的内容发送到客户端,服务端整套流程完成。最后,由nginx反向代理即可。

客户端

因为DOM有效率问题,一个节点的插入会导致整个页面的重新计算。所以不考虑CSS3 Animation和JavaScript Animation。在这里直接选用canvas,把整个页面设计为一个画布。在这个画布上自由发挥。

首先定义每一帧为一个Frame对象。每一帧上面都要有一个动画元素。定义一个Sprite对象作为动画元素的原型对象,拥有一个Draw方法的实现,用于在渲染每一帧的时候告诉自己如何呈现于Frame对象。

其次,定义继承于Sprite对象的Comment对象,这便是每一条弹幕。定义一个继承于Frame对象的CommentFrame对象,由其负责每一个Comment对象的管理。CommentFrame对象要自动渲染每一帧。为了保证效率,还需要一个Buffer,由CommentFrame对其进行管理。CommentFrame渲染各个Sprite对象到Buffer上,再由Buffer绘制到主画布上,实现每一帧的绘画。

再加一个socket模块自动获取消息,就算完成了。


负载测试

环境

网络

配置及备注

QPS

Windows 10 x64 9926

i3-3220 @ 3.30GHz

Node v0.12.0 (x64)

MySQL 5.7.5-ml5-log (x64)

本地

一个客户端连接


469.5




563.09



504.59



420.6

Linux 3.10.0-123.9.3.el7.x86_64

E5-2630 @ 2.30GHz

iojs v1.6.2

mariadb-server.x86_64 1:5.5.41-2.el7_0

阿里云杭州D

一个福州铁通客户端连接

默认配置

784.7




868.2

 

QPS意为Requests Per Second,即每秒处理请求数。


试用效果

在宿舍文化节试用,合计约一小时又三十分。

共有569人发送弹幕,筛选掉被拦截(如表白、色情词汇、脏话)弹幕,共得到4457条弹幕。校内人数为1357人,场内总人数估计约1200左右,约47%的人发送了弹幕。

达到了预期效果。

(下列图片来自当时参加活动的同学,已取得其允许,非常感谢)



解决问题

1.         跟踪用户

如何在不登录的情况下跟踪用户?若用随机Session + Cookie的话极易被清理,且有效期难以保证。有一些技术,如Canvas指纹可能是个好选择。(注意iOS设备的验证!如果是同样设置、同样型号的iPhone是否会重复?)

2.         连接稳定性

根据之前的测试,TCP连接由于网络环境过于复杂,稳定性比较差。约10分钟掉线一次。socket.io库本身自带心跳包,故用超时 + 自动重连解决问题。

3.         数据被画到界面上时的效率问题

当Comment对象过多时,每一个对象都要计算其位置并重绘。当同时有10000条以上时,这方面的卡顿会非常明显。结论是不需要考虑,数据量过大的弹幕没有意义。

4.         线程间通信与模块解耦合

    程序架构上的问题,用事件解决。

5.         负载测试

   发送弹幕接口采用HTTP POST,所以可直接用 ab进行测试。上有测试报告。由于一般连接的客户端少,所以没有很大的必要来测试其极限的连接数。


暴露问题

1.       无意义弹幕占比过大,有一部分人身攻击信息出现,总体弹幕素质不高。

2.       弹幕平均长度过长,容易遮挡其它弹幕。

3.       身份验证手段过于低级,以致一些人难以形成良好的弹幕观。

4.       Nwjs对于窗口透明支持度并不高。

5.       Linux下不能打开GPU加速。


如果本文对你有帮助,你可以用支付宝支持一下:

Alipay QrCode
大白 at 2018/2/2[回复]
你好 想问下如何解决在Windows下的调整窗口大小的问题。貌似在Windows下Frame为fasle是不能调整窗口大小的
zsx at 2018/2/7[回复]
resizable可以设置为true
闵聪 at 2015/10/19[回复]
666
abc at 2015/9/2[回复]
我就不信发帖还能知道我的主机
c at 2015/6/1[回复]
膜拜……!
MrHe at 2015/5/30[回复]
在台上的是博主吗?
zsx at 2015/5/30[回复]
我在后台也只能在后台