找回密码
 会员注册
查看: 20|回复: 0

B站移动真机测试集群建设实践

[复制链接]

6

主题

0

回帖

19

积分

新手上路

积分
19
发表于 2024-10-11 16:29:01 | 显示全部楼层 |阅读模式
1. 背景最近几年B站业务高速发展,除了原有的主站业务又催生了很多新的业务,如国际版、必剪、猫耳、HD等,因此各个业务团队对测试手机的需求也显著增长,这对公司来说是一笔不小的开支,但现有测试手机资源分配不均,利用率也非常有限,导致各个团队开发、测试过程中都很难做到多机型覆盖,如何合理、高效利用这些测试手机资源,是摆在我们面前的一道难题。另外在B站内部业务高频率敏捷迭代的节奏下,客户端版本的迭代周期也变的越来越短,为了最大限度的保障产品质量,自动化测试成为整个质量保障过程中不可或缺的存在,而自动化测试需要高质量基础设施来支撑,不然就是空中楼阁,而对于移动APP来说,这个基础设施就是云测机房,也就是下图中的IaaS层。其中最上面的SaaS层提供诸如:兼容性测试、稳定性测试、性能测试、UI测试等各种各样的自动化测试能力,中间的PaaS层则提供:测试用例管理、测试数据管理、测试框架支持、测试任务调度以及测试报告展示等平台层服务,而laaS层作为底层服务,主要是为了把手机这类硬件资源抽象化为一种通用的测试资源来为上层提供通用的测试设备服务。1.1 IaaS 层现状1)大多数都是基于开发测试人员的个人测试手机在本地执行一些自动化测试脚本;2)有些团队是通过采购少量的测试手机,然后在本地搭建自动化测试设备的小集群。1.2 IaaS 层面临的挑战1)采购成本高:一方面需要覆盖市面上主流的移动设备品牌、型号、操作系统版本以及持续的更新换代,另一方面还需要服务器、数据线、USB Hub等IT设备和配件;2)稳定性差:不同品牌的手机存在兼容性问题导致设备掉线,另外传统的ADB连接一旦出现异常情况,需重启ADB服务端,导致全部ADB连接中断,无法快速恢复;3)运维管理困难:一方面在自动化测试执行过程中会遇到各种异常事件,比如:系统弹框、存储空间不足、断网、电量不足等,这些问题会大大降低测试任务的执行效率以及测试结果的有效性,导致开发和测试人员花费更多的精力用于分析失败日志、重跑测试任务以及修复运行兼容性问题等,另一方面设备在长期运行下会导致电池加速老化以及温度过高,进而容易出现电池鼓包,甚至存在潜在的火灾隐患。2. 目标1) 构建统一的IaaS底层服务,从而降低设备采购和运维成本,进而提升测试任务执行的效率和有效性;2) 提供通用且丰富的测试设备服务,支持多种测试框架,降低各业务线的接入成本。3. 方案选型关于移动真机测试集群的行业方案主要有两种:1) 公有云真机测试集群2) 私有云真机测试集群3.1 公有云真机测试集群公有云真机测试集群是指使用诸如:WeTest、Testin、阿里云测、华为云测、小米云测、360开测等厂商提供的云测服务,这种公有云服务通常是按照使用时间和使用的设备数量来计费的。采用这种方案的优点就是无需自建,而且公有云测服务的设备型号一般较为完备。但是缺点也很明显:首先是费用成本相对比较高,这个的话主要是根据你使用的设备数量和时间来计算的,如果测试任务很密集,任务执行时间很长的话,这个费用还是很高的;其次,这些公有云测服务通常仅支持少量几种主流的成熟测试框架,这样一来公司内各团队历史积累的测试用例集迁移成本就会比较高,而且是公有云测服务,因此无法快速响应业务的定制化需求;另外,这也无法支持测试任务运行时依赖的众多内网系统,例如Mock服务、测试环境等等,导致真正可测试覆盖的场景非常受限。3.2 私有云真机测试集群私有云真机测试集群是通过自建机房然后采购大量真机设备、服务器、专用机柜以及各种IT配件等来对内提供云测服务,如下图:采用这种方案的优点是可控性比较高,可以及时响应业务定制化需求,可以支持丰富的测试框架,另外由于在公司内网部署,所以可以无缝打通各种内网服务和平台;缺点是前期一次性成本投入比较高,只有当大量测试任务接入后,才能逐渐平摊降低成本,而且私有云测服务还存在设备运维更新换代的线性成本支出。对于自建机房中设备的来源,通常可以有两种渠道:首先就是常规的采购,这里可以优先采购二手机,不一定非得要全新的机器,其次还可以从IT那里回收研发测试团队淘汰下来的旧手机,一方面可以用来补充设备池中的低端机型,另外还可以节约公司成本。提到自建机房,很多人可能觉得只需要买一堆手机、平板,再买些PC机用数据线插上就可以了,但其实远非如此,就好比数据中心,并不是买一堆PC机和几个交换机就能够达到数据中心的效果一样,手机、平板作为消费级产品,各个厂商的规格质量差异很大,哪怕是同一厂商的不同型号也会有一定的差异,要想保障数百部手机、平板长时间提供稳定的测试服务是非常有挑战的。4. 系统架构IaaS层主要由三部分组成:操作使用层:通过Web GUI和CLI命令行的方式提供对Android真机的远程控制;调度管理层:设备的注册、查询、占用、释放、调度等,以REST API方式提供服务;容器实例层:这里主要是通过容器化的方式进行ADB的隔离,以提高Android设备ADB的连接稳定性。4.1 操作使用层由于不同用户对真机的使用诉求不同,有的用户倾向于命令行调试,而有的用户则倾向于Web页面调试,因此我们提供了比较多的调试手段,尽可能在满足用户核心诉求的情况下,让整个使用体验更简单、更稳定,以下是命令行的操作示例:方式一:adb -H IP -P PORT devices-H -P 的方式和普通adb命令相比需要增加额外的-H 和-P 参数,适合快速开始,测试一些简单的脚本和命令操作。方式二:export?ADB_SERVER_SOCKET=tcp:IPORT设置ADB_SERVER_SOCKET环境变量方式需要新开一个命令行终端,可以看到设置环境变量后可以获得类似adb直接连接的效果,适合运行一些已经写好脚本,不需要在额外增加参数,当然也仅仅在当前终端内的操作有效。方式三:adb connect IPORTadb connect 方式可以等价于adb连接本地wifi的设备。Web UI的操作示例:4.2 调度管理层实现移动设备的注册、更新、查询、调度及设备状态监控等,主要包括以下几个接口:获取设备列表接口:根据任务类型筛选符合条件的可用设备占用/释放设备接口:占用时分配可用时长,超时后自动释放更新设备接口:实时更新设备的在离线状态及可变属性,比如设备IP、系统版本等注册设备接口:对于新接入集群的设备实时上报获取设备信息接口:根据设备SN号获取设备的详细信息,比如品牌、型号、CPU架构等4.3 容器实例层iOS由于生态比较完善且闭环,设备的连接稳定性要高很多,基本很少出现设备掉线的情况,通过idevice_id、ideviceinfo、tidevice等命令即可实现与iOS设备的通信比如:获取设备信息、安装应用、截图、启动WDA测试等等,而Android主要是通过ADB命令行工具来管理和控制设备的,但现有的ADB连接存在以下的缺点:1)无法保证集群连接的稳定性,当多个ADB客户端连接一个ADB服务端时,即多台移动终端与PC端通过ADB连接,一旦某一台移动终端与服务端连接中断,可能会导致其他的移动终端连接中断;2)无法快速处理异常情况,传统的ADB连接系统基于单一的环境,无法为每一个 ADB连接配置独立所需环境,传统的ADB连接一旦出现异常情况,需重启ADB服务端,导致全部ADB连接中断,无法快速恢复。综合考虑,我们决定重新制定一套方案,其核心将围绕着adb server的隔离,即一台安卓设备只有一个adb server与其进行直接连接,首先我们可以知道adb的进程可以使用不同的端口进行隔离,但如果只依靠端口进行隔离,并不能控制adbd具体连接到哪一个adb server上面,测试结果发现几乎是随机连接到电脑的某一个adb server上面,因此自然想到了用容器进行隔离, 其实appium-docker已经有一套可用的方案,如下图:可以看出本质是将物理机中的usb node映射到了容器中,这和使用特权模式加上-v挂载文件路径的方法是完全等效的。但是这种方式并不能完全满足我们的需求,因为一旦设备掉线(包括非预期和预期掉线),就无法重新连接到当前容器,只能销毁重建,这也就意味着我们绝对不能使用adb reboot,adb tcpip,adb usb等所有会导致adbd重启的命令,之所以需要执行这类命令是因为我们后续的操作非常有必要将安卓设备的adbd以tcp方式重启。因此接下来的目标便是实现将主机的usb物理端口与容器进行绑定,即插在某一个usb端口的设备,统统映射到某一个标签的容器中。在ubuntu20.04系统中usb设备被抽象成了文件存放在/dev/bus/usb/路径下,整个挂载动作是则由udev完成的,那么我们只需要对容器添加device cgroup rule,在物理机上监听usb端口的动作,监测到有设备插入时和容器进行通信,并在容器内实现类似udev的挂载过程即可,下图便是改进后的结果:如此大费周章地实现了usb端口-容器的绑定究竟能带来哪些好处呢?我们将所有的容器都采用ipvlan L2网桥,每一个容器君都拥有和物理机平级的ip地址,利用adb forward将手机的5555端口与容器的5555端口绑定,外部机器便可以直接通过容器的ip地址和5555端口连接到手机的adbd,这种方式和adb远程连接非常相似,但是最大的区别便是远程连接是隔空通过wifi的tcp连接,而现在的方式是有线tcp连接,在网络稳定性延迟速度等方面都有了大幅度提升,而usb端口-容器的绑定便是这一切的基础,下图展示了单台物理机器的部署架构:经过充分测试该方案有效规避了由于单台设备adb异常导致整个adb server所有设备全部掉线的情况,并且单台物理机有效稳定挂载安卓设备的上限从原先的30台逐步提升至接近usb总线的上限(单个usb2.0最多识别127台设备),此外还可以通过pcie转usb的方式再增加更多设备,因此adb server可靠性问题得到了彻底解决。由上图可以看出该方案对物理机的负载也会成倍增加,使用原先的工控机部署后,负载长期高于cpu核数2倍以上,但是即便如此设备的日掉线率也从原先的10%~15%降低到2%~5%左右,大幅度降低了运维成本,如今我们已经将所有工控机全部升级到了4C8T 16G内存的中等配置,现在的日掉线率更是低至3%以内。5. IaaS 高可用保障移动真机测试集群作为重要的基础设施,高稳定性是最重要的指标之一,需要要能够为用户提供7x24小时的稳定性保障,我们基于以下几个维度设计了保障策略。1)机房层面稳定的机房供电,配置合适的UPS恒定的温度与湿度,一般需要在23度左右数据中心级别的防火和灭火系统2)网络层面移动设备联网方式由纯WIFI方案改造为USB+WIFI结合方案部署企业级高密AP提高WIFI信号可靠性构建电磁屏蔽机柜,降低WIFI信号互相干扰3)移动设备层面设备测试环境设置(包括但不限于:桌面、安全、开发者模式、输入法、权限监控等)4)基础服务层面多机部署,避免单点故障重要服务单独部署搭建高可用K8S集群,容器化部署服务5)监控层面基础资源监控:内存、CPU、磁盘基础服务监控:截图、dump、OCR、应用安装移动设备监控:在线率、在线数、调度成功率、执行成功率、网络、存储空间、温度、电量等6)运维层面自动处理移动设备的各种系统弹框根据设备监控告警,自动剔除异常设备并进行重启维护,待确认恢复正常后自动化加入设备池设备掉线后自动恢复同构对以上几个维度的保障,最终我们满足了7x24小时使用的需求,SLA指标达到了99%。5.1 遇到的典型问题及解决方案5.1.1 机房温度湿度过高,断电故障恢复慢电子产品长时间稳定运行对温度要求很高,一般需要在23度左右,因此我们通过专用的数据中心空调实现制冷,始终让机房整体温度保持在23度左右,另外通过K8S高可用集群以及supervisor进程管理工具,实现所有核心服务的开机自恢复。5.1.2 WIFI信号互相干扰,网络抖动严重手机上运行应用需要WIFI上网,一般家用WIFI设备同时支持10多个终端同时上网可能就会挂掉,我们采用了高密度的WIFI设备,但即使这样还不行,为什么呢?因为手机密度太高,狭小空间内要部署数百台手机,如此多的手机需要很多无线AP设备来支持,而AP设备密集部署会形成严重的同频干扰,手机WIFI上网会很不稳定,大大影响测试结果,特别对于一些老款手机使用WIFI经常网速很慢以至于断网,于是我们另辟蹊径,决定让设备使用usb数据线进行上网。在安卓5.0及以上版本中,Android Debug Bridge(adb)提供了反向映射端口的功能,即adb reverse,和adb forward相反,forward是指将安卓设备的端口映射到pc主机上,用于方便地访问设备的某些服务,而reverse则是将pc主机的端口通过adb bridge反向映射到安卓机器中,即你的设备如果是usb连接,那么数据流量就是走usb线,如果本身adb就是无线连接,那么还是会走无线网络。在这个前提下我们在设备的容器内开启一个线上透明代理并暴露在8888端口上,再将容器本地的8888端口通过adb reverse反向映射到手机中,最后将手机设置全局代理,ip地址填写127.0.0.1,端口填写8888,那么此时手机的8888端口其实是pc中透明代理的端口。用此方法可以将http/https流量通过usb线,走主机的透明代理进行访问。经过测试配置好代理之后,即便手机开启飞行模式关闭所有无线连接,手机依然可以访问互联网,证明usb联网有效。以下为原理介绍图:在上图中,我们使用agent用于控制8888端口反向代理的真实端口,用于切换线上和uat环境,在自动化测试过程中大大改善了由于WIFI不佳导致的各种问题。但是注意这种方式并非万能的,使用浏览器访问各种页面是几乎没有问题的,但是通常APP客户端可以使一部分流量绕过代理,那么这部分流量自然无法享受到usb联网。例如哔哩哔哩中视频流量就不走代理,如果关闭WIFI就会发现主页可以正常加载,但是所有视频都无法播放的情况,因此usb联网只能用于缓解无线AP的带宽压力,并不能完全替代WIFI。5.1.3 各种系统弹框先简单看一下弹框处理的背景,这里我简单列了一些主要的弹框类型。首先是安装弹框,在很多手机上安装应用的时候会弹出授权提示,这个弹框是无法通过简单的系统配置关闭的,只能通过自动化的方式来处理,特别是在oppo,vivo等手机上还需要用户输入用户名密码才可以安装应用;其次是权限弹框,这个是在Android6.0以后,Android为了用户安全引入动态权限申请导致的,再有就是USB调试弹框,这种一般出现在用户远程调试设备的时候。由于adbkey不一致导致出现授权弹框;另外还有像系统更新和USB连接这样的弹框,这些弹框会严重影响应用的安装成功率和测试执行稳定性。这也就是前面提到的影响测试有效性的一个因素,可能执行了100台机器,只有一半能正常安装,另外又只有一半能正常运行,这种情况是实际存在的。我们主要采用了如下两种方案结合使用:方案优点缺点适用场景无障碍服务可以脱机执行1、在执行自动化测试过程中,由于市面上绝大部分框架都是基于accessibility 的API,本身跟AccessibilityService 会有冲突,导致自动化测试开始执行的时候会自动杀掉AccessibilityService 服务,从而致使弹框处理服务不可用;2、如果弹框控件的clickable属性是false,AccessibilityService 服务是无法点击对应控件的;USB调试弹框这样的需要脱机处理的场景adb基于坐标点击,兼容性较好无法脱机执行除了脱机场景之外的所有弹框类型下图是弹框处理的简单流程,我们会在云端配置好各个机型的弹框信息,然后宿主机上的弹框处理服务会实时拉取配置信息进行规则匹配,当匹配到弹框信息后会尝试点击或者输入以处理弹框。5.1.4 手机电量消耗过快1)实时监听手机音量,当音量大于0就自动静音设备;2)实时监控手机屏幕亮度,自动将设备的屏幕亮度调节至最暗;3)采用专用的USB Hub供电;4)测试任务结束后关闭所有第三方应用程序。5.1.5 手机温度过高、存储空间不足、电量过低1)实时监控手机温度,高于某个阈值从可用设备中摘除,当温度恢复到正常温度,重新上线;2)实时监控手机存储空间,当低于某个阈值的时候从可用设备中摘除,并自动清理第三方应用和缓存文件,当存储空间恢复到正常大小,重新上线;3)实时监控手机电量,当低于某个阈值的时候从可用设备中摘除,当电量恢复到正常,重新上线。6. 落地效果目前laaS系统已经支撑了B站15个独立APP和20条业务线在不同场景下的移动端自动化测试设备需求,同时我们也一直在努力丰富真机设备的功能场景,不断提升系统的稳定性和性能,此外我们也在积极丰富SaaS层的自动化测试能力,通过和laaS层形成组合拳,解锁研发活动中更多的适用场景,帮助业务团队更好的提升能效。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2024-12-27 14:34 , Processed in 0.463347 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表