最近几年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压力测试的一些方案过程和心得,希望对大家的日常工作能有所帮助。
行动吧,在路上总比一直观望的要好,未来的你肯定会感 谢现在拼搏的自己!如果想学习提升找不到资料,没人答疑解惑时,请及时加入扣群: 320231853,里面有各种软件测试+开发资料和技术可以一起交流学习哦。
最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:
这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!