移动测试开发 WebRTC 压力测试实战

opentest-oper@360.cn · 2023年08月31日 · 3417 次阅读

最近团队需要对外采 webrtc 服务性能做验收,验收合格才能进入下一步,所以要求做一下压力测试。如何对 webrtc 服务进行压力测试是一个很有难度和挑战的工作,因为 webrtc 客户端实际使用上产生的压力瓶颈主要来源对象是码流而非传统的 HTTP 并发请求。因为业务要求服务至少能支持提供 300 路并发,于是准备 300 路 webrtc 连接验证下 SFU 服务器压力情况,这里分享进行压测的思路及方式和一些可以说的结论,如果在这方面有相关经验的测试技术方案的测试同行,请加评论给予指导帮助。

Webrtc 压测主要涉及到以下两个问题:

1.那么多的压力客户端从哪里来?
2.如何监控服务器性能?

第一个问题:第一想法是请服务端开发同事出一份 Linux C++ 版本 webrtc 客户端的代码。支持开上百个线程对应上百个 webrtc 客户端,然后跑在多台服务器上开始压测,读取本地视频流和音频流作为输入。后来经过沟通感觉有点给开发同事增加了不少测试内容的工作量,再加上开发同事的时间也很紧张。经过与厂商的沟通以及网上冲浪调研,找到了解决这个问题的方案,准备通过使用 playwright 模拟浏览器作为 webrtc 压力的客户端完成请求,并读取本地文件作为音视频输入。

第二个问题:经过讨论服务端开发可以自行搭建监控服务,然后接入到 grafana,增加可视化模板,就可以获取到用户连接数、RTC 流数量、CPU 使用率、服务器实时码率、服务器消耗流量、内存使用等数据。(PS)内存监控需要自行配置,要有内存回收机制,另外 limited 内存需要设置合理。

开始测试之前我们要先搞清楚被测系统的框架,我们知道在 WebRTC 技术的实际应用中,衍生出了媒体服务器的用法,那媒体服务器区分成 MCU(Multipoint Control Unit)和 SFU(Selective Forwarding Unit)两类网络结构。MCU 是一种传统的中心化网络结构,参与者仅与中心的 MCU 媒体服务器连接。MCU 媒体服务器要合并所有参与者的视频流,生成一个包含所有参与者画面的视频流,参与者只需要拉取合流画面。而在 SFU 网络结构中,虽然仍有中心节点媒体服务器,但是中心节点只负责转发,不做合流、转码等资源开销较大的媒体处理工作,所以服务器的压力会小很多,服务器配置也不像 MCU 的要求那么高。每个参与者需要 1 个上行链路和 N-1 个下行链路,带宽消耗高于 MCU。那我们本次被测试系统架构使用的是 SFU 网络结构,如下:

我们搞清楚系统框架后,为实现压力测试目标,需要使用具备以下几点的自动化工具:
◆稳定且可预测的设备及运行网络;
◆能在不同条件下进行测试,可动态控制的可配置网络;
◆可以测试来自不同地点的用户;
◆对结果进行详细的可视化分析,以方便理解测试结果。
接下来走入正题,开始进入测试工作。

一、编写 webrtc 压力客户端代码

因为团队想看到实际压测中的全链路表现,比如房间管理,分散均匀的进入不同会议室,和多人进入一个会议室通话情况等。
开始脚本工具调研,playwright 是微软开源的自动化 UI 测试工具,支持 Chrome、Firefox、Edge 等多种浏览器,兼容多种语言、多种操作系统。它基于 Websocket 协议,可以接受浏览器(服务端)的信号。
Playwright 安装简单,pip 安装时会自动下载浏览器驱动:
pip install playwright
playwright install,
安装时会自动下载浏览器依赖,windows 系统在%USERPROFILE%\AppData\Local\ms-playwright 路径下。
使用:
from playwright.async_api import async_playwright
网上很多帖子就不过多赘述了。
具体 Webrtc 核心测试代码:

args 使用如下参数启动即为下面的效果:

f"--use-fake-device-for-media-stream",
f"--use-fake-ui-for-media-stream"

如果想读取本地视频及码流作为 webrtc client 音视频为输入即为下列参数:

f"--use-fake-device-for-media-stream",
f"--use-fake-ui-for-media-stream",
f"--no-sandbox",
f"--use-file-for-fake-video-capture=./webrtctest/1.y4m",
f"--use-file-for-fake-audio-capture=webrtctest/2.wav"

调试代码中,在基础代码上进行封装,首先准备一个 csv 文件,里面可以存鉴权使用的 authCode 之类的信息,同时按行读取 csv,并且会根据 csv 里面有多少行来决定打开多少个标签页,并选择使用 await 异步方式打开,然后根据读到的 authCode,去进行下一步生成的 session_token 进行代码编写,再进行 await page.goto(url),根据功能特性进行操作步骤,另外场景二需要多人进入一个会议室,客户端策略是每个人都默认展示第一屏, 相应的增加了会议中翻页的功能,并根据 await div_locator.count() 数进行循环翻页,用的是协程,只有等上一个标签页面完成了所有程序后才能进行下一个标签页面,只要算出当前标签页最多能点多少次就好了,之后再进入的人不会影响上一个标签页,从而上一个标签页也不会再继续翻页了,这样就解决了使用同一份代码,不同人进入会议后都在不同页码的问题,这样就能遍历到所有的翻页,也就是说如果有 30 个人进入会议,分别在 1-5 的屏上。但是后来发现 rtc 当中经常的断开重连后又默认展示第一页,又改变策略为共享屏幕,继续修改代码。

在调试的时候,会经常出现超时的问题

后来在 goto url 里面增加 timeout=10000000 的参数,解决了该问题。

await page.goto(url, timeout=10000000)

二、测试实施

好了,本地的测试代码调试通过了,服务端也准备就绪。但是,那么多的发压真实设备怎么来,让同事全部使用自己的电脑?那肯定是不够的也不现实的,因为服务端做了一些策略限制,比如不管会议室里面多少人,只有第一页的人有流量,这是为了节约成本。另外 playwright 虚拟浏览器也是非常消耗资的,浏览器需要运行多个解码器,本身也是一种负担,所以一台测试机上不能开太多标签页,使用了一下,8G 内存的测试机开 4 个标签页,也就是 4 个 webrtc 连接;20G 内存的测试机开 7 个 webrtc 连接,基本测试机的 CPU 使用就已经是 100% 了。使用基于云的解决方案意味着,那还得花时间去写一份移动端的代码,而且移动端的兼容性代码需要花更多时间,另外移动网络和设备会如何影响你的基础设施,此方案排除。虽然也可是申请虚拟机,但是还是想看到各个测试机真实的流状态,最后决定通过公司内部申请 Windows 测试机做为压测机器。

比较好的准备工作如下:
①.测试机器:环境准备,为了快速的让 IT 人员准备机器,大概 50-60 台, 我们先把需要的测试工具,测试脚本和脚本依赖环境 requirements 文件都给 IT 人员,让 IT 人员先统一的帮忙安装好系统的同时帮助我们安装好我们需要的软件环境。
②.测试准入:需要申请的一些特殊网络准入,也让 IT 人员做好 MAC 地址的记录,拿到 list 后统一一次性申请。
③.测试网络:申请交换机,准备好网线。
④.测试同步:因为测试机很多,每个单独运行脚本也是非常耗时的,开始的时候调研想过使用 Playwright Grid 进行分布式测试,Playwright Grid 的原理就不过多的说,大概就是可以在远程机器上启动浏览器,实现多台设备同时运行测试。这可以加快测试时间,模拟真实用户环等,其中步骤里面有一句:测试脚本直接运行在 Grid 服务器上,使用与本地 Playwright 一致的 API,不需要修改代码。实际中是我们每台机器的代码都有不一样的地方,比如 authCode 或者要进入的会议号都不一样等,所以就放弃了 Grid 的方案。
下面是一部分压力测试机画面:

压力测试下的共同功能验证体验测试
部分主观感受指标,当着参考。
1.视频:
5 分:完美。画面十分清晰流畅
4 分:好。画面有轻微的不清晰、轻微的降帧,仔细看能看的出来,但感觉还算流畅
3 分:中。偶有卡顿、或者画面不清晰,但是还能接受
2 分:差。频繁卡顿,但是还算可用
1 分:不可接受。完全卡住,或者画面不可辨,完全不可用
2.音频:
5 分:完美。声音清晰、流畅(与打移动电话体验一致)
4 分:好。音质不错,虽然不完美,但不影响交流
3 分:中。音质一般(有卡顿、吞字、不清晰、声音忽小忽大),但凑合也能用
2 分:差。经常听不清楚,影响交流
1 分:不可接受。完全听不清楚对方说什么

三、问题记录和调优

webrtc 服务端环境,服务端使用集群方式部署的,有不同城市的服务器,本次压力测试的目标不是压测集群的压力极限, 而是看在 300 路 webrtc 连接压力下,同时房间管理,多人通话是否正常,资源使用是否合理,调度是否合理等。
本次压力测试,肯定是在客户端和服务端联调完成后,能正常工作,并且该解决的 p0,p1 级问题之后才进行,要不当中很多问题会影响压力测试进度。 当然我们更需要知道在一定压力下,邀请相关人员加入一起体验测试功能,发现更多的问题也是目标之一。
测试中途发现重要问题:
服务端:1.IP 调度不准确。2.内存使用过高。3.内存存在泄漏,回不到原点。
客户端:1.客户端经常掉线或者 rtc 断开重连等。2.一个会议室达到一定人数后就会自动锁会,再往里面加入就非常困难了, 经常收不到入会请求 ,不知道是客户端没有发出去还是主持人没有收到请求,收不到准入客户端就入不了会,脚本就超时失败了。

典型问题调优过程:
内存无法回到原点的问题,服务端排查找原因,sfu 内存回收慢的问题,是 linux 运行时内存控制方式不同导致,那调研 linux 内存管理方式,切 ptmalloc 到 tcmalloc,适时手动操作内存释放。
客户端 rtc 断开重连问题,①.开始的时候,房间管理频繁断开,排查发现并发接收消息有问题,服务端修改并发接收结构,并且改大超时时间为 10 秒;另外客户端增加房间管理重连重试机制;②.测试一段时间又出现房间管理连接断开,重连后状态不同步。解决办法就是连上 websocket 就发消息,修改保证连上 websocket 并加入房间才发送消息;③.解决后发现网络稳定的时候,房间管理的长连也有频繁断开情况。解决办法就是连上 websocket 就发消息,修改保证连上 websocket 并加入房间才发送消息。
压测中记录好问题产生的原因和解决方法,然后继续调优验证直到服务端资源使用符合预期为止。其他的问题有的作为已知问题待解决。

四、测试报告

测试报告里面包含三部分,测试结论,资源使用情况,主要功能验证情况,以及测试当中发现的问题分析。
测试结论:300 路连接并发下,可以较好地支持码流为 xxxkbps 的码流 300 路对等链接,太具体的详细数据不便于写出。
资源使用包括:用户连接数,RTC 流数量,CPU 使用率,服务器实时码率,服务器消耗流量,内存使用,截取趋势图展示。检查服务器资源是否是线性的。
功能验证包括:各种场景的主观感受均值,掉线次数等等,生成一个 excel 表记录。
测试发现问题:测试当中发现的问题经过服务端客户端同事的多次排查,需要解决集群的资源,客户端问题,写上发生的原因,以及解决方法等。

以上,为本次 webrtc 压力测试的一些方案过程和心得,希望对大家的日常工作能有所帮助。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册