攜程酒店統一云手機平臺探索與實踐
作者簡介
酒店無線效能研發組,負責酒店無線團隊基礎能力平臺的研發,比如Cloud Touch平臺(云端手機),內容運營平臺,自動化測試流程等,通過對日常規律性事務的抽象總結提供解決方案,提高平臺所承載業務的整體效能。
一、背景
攜程內部會有大量的部門或團隊需要在App新版本、新站點完成研發階段所有功能測試后,在上架前(Post Release)階段,再進行無拘束的從客人視角驗收的訴求(比如競品對比、Localization體驗等)。對于已經上架的版本,我們的客服人員在客人協助、新員工培訓等場合,也有著使用生產資源來獲得與客人同一視角的環境訴求,這對我們研發流程中已經存在的測試環境的適用性提出了巨大的挑戰,無論從操作體驗、還是資源對齊等多方面,測試環境都難以滿足訴求。
- 例如為滿足Trip.com的新站點上線前的海外駐地驗收訴求,需支持新站點的新功能提前向定向人群釋放的能力。
- 例如為滿足客服在對客協助時,能充分理解客人的進線問題,需支持員工和客人的視角保持一致的App操作平臺。
二、全場景建設
我們綜合評估了相似訴求以及平臺能力可能的輻射面后,下圖呈現了我們對系統(下文統一命名Cloud Touch)的適用人群的預期:
以駐地驗收場景為例:基于Cloud Touch平臺,可統一收口驗收人員的設備管理,通過云平臺提供統一的遠程操作入口。這樣不論我們的員工在世界任何駐地,都可以方便的使用中心化維護的設備,同時新站點的RC包將在Cloud Touch上提前上架,完成待驗收版本的部署。
以客服協助場景為例:基于客服工作臺給員工提供統一的進入Cloud Touch的入口,可供員工在與客人的對話中了解客人的對應App版本,能快捷的在設備池中選擇相關預置好的實機進行場景鑒定工作。
(以上示意圖)
三、基于Cloud Touch的技術解決方案
3.1 核心平臺設計
基于以上分析,平臺需要解決的是覆蓋不同應用場景的設備資源的分配管理問題,實現不同地域請求的中心化分發問題,提供本地設備的遠程操控以及畫面的實時同步問題,以達到類似于遠程桌面的交互體驗。并且可基于平臺化的收口能力為不同業務場景提供統一的預置參數和環境的配置,使各項工作的標準化能進一步得到提升。
3.2 設備分池設計
我們有大量的客服員工座席,同時也有研發線的測試驗收人員,設備池的足夠大是硬件條件,但是如何有效的利用這些設備,協調好不同應用場景的人和設備的關系,這還需要一套滿足核心場景的分配策略設計,主要的核心流程如下:
3.3 遠程設備操控設計與實現
實現了平臺化和設備的統一分發工作后,那么技術的核心在于如何選型并實現一套端到端的遠程控制方案。
因為不同系統的對接技術不同,此處我們以iOS的實現為例,WebDriverAgent是Facebook 在17年的 SeleniumConf 大會上推出的一款新的iOS移動測試框架(WDA),WebDriverAgent 在 iOS 端實現了一個 WebDriver Server 能夠實現與瀏覽器進行交互,它的實現使用了經典的Server-Client架構(C/S),客戶端發送一個Requset,服務器端返回一個Response,借助這個 Server 我們可以遠程控制 iOS 設備。
WDAClient:基于WebDriverAgent實現的WDA的客戶端。facebook-wda 就是 WDA 的 Python 客戶端庫,通過直接構造HTTP請求直接跟WebDriverAgent通信。
WDAServer:運行WDA App的機器,實現了WebDriver的通訊協議。
Session:服務器端需要維護客戶端的Session,客戶端首次發送請求的字符串是'/session/sessionId/url′。服務器端根據url打開對應的url地址,同時將sessionId解析成真實的值,然后返回給客戶端。以后客戶端再向瀏覽器發送請求時,會攜帶session值一起發送。
WebElement:WebDriverAPI中的對象,代表頁面上的一個DOM元素。
JsonWireProtocol:是通過使用webdriver與remote server進行通信的 web service 協議 。通過http請求,完成和remote server的交互。
Mobile JSON Wire Protocol Specification:移動端自動化協議。
(此處引用了WDA官方的部分基礎技術說明,如您感興趣可以再進一步參考github上的facebook archive項目)
3.3.1 指令集適配
Client端可以接收多種不同類型的指令以完成不同的動作,主要包括以下幾種:
(1)基本指令通信格式(iOS/Android格式公用,處理略有不同,以下用iOS舉例):
{
"serial":"00008030-000D48A40291802E", // IOS設備udid
"type":"M_TOUCH", // 命令類型枚舉值
"message":{
"action":0, // 鼠標或鍵盤 0按下 1松開
"keycodeType":"ascii", // 代表鍵盤事件輸入的是ascii碼
"keyCode":60, // 鍵盤按下了哪個鍵 非ascii時響應對應系統鍵
"position":{
"x":687, // 鼠標點擊事件x像素坐標
"y":1116, // 鼠標點擊事件y像素坐標
}
}
}
(2)基本指令:鼠標事件(點擊/滑動操作)
- 前端頁面根據設備上報的分辨率和用戶在畫面上操作的位置,計算鼠標的像素位置x,y并組裝鼠標事件命令
- Client收到actinotallow=0命令時(即按下鼠標時),記錄鼠標按下的坐標和命令的時間
- Client收到actinotallow=1命令時(即松開鼠標時),記錄鼠標松開的坐標和命令的時間。
- Client根據設備的scale(IOS設備像素和uiKit的縮放比)將命令下發的像素坐標轉換為ui操作坐標,獲得命令的起點和終點。將按下和松手的時間差值作為命令的執行時間,組裝WDA命令。
- 請求WDA的url為:/wda/swipe,根據起點、終點、命令執行時間、命令觸發頻率的不同可產生點擊、長按、雙擊、滑動的效果
(3)基本指令:按鍵事件
- 前端記錄用戶按下的按鍵并轉換為ascii碼,組裝鍵盤輸入事件,長時間按壓會連續產生的命令;用戶在頁面上點擊的系統按鍵(電源、主頁、菜單鍵)也會被轉換為鍵盤輸入事件
- Client收到actinotallow=0時,若收到ascii碼的字符,則觸發字符輸入事件;若收到系統按鍵,則組裝對應的命令完成操作
- 字符輸入事件: /wda/keys接口默認有同步快照機制,會消耗大量時間確保輸入按照順序進行,平均響應時間1字符/秒。云手機對時效的要求更高,所以將WDA快照機制刪除,并在Client中使用隊列,將短時間內的多個字符合并成1個字符串,調用1次/wda/keys即可完成多個字符的輸入,做到輸入實時響應
- 電源鍵:請求/wda/locked獲取當前鎖屏狀態后,調用/wda/lock或者/wda/unlock進行鎖屏與解鎖
- 主頁鍵:請求/wda/home回到主頁
- 菜單鍵(APP選擇頁):WDA未提供對應接口,通過組裝上劃命令請求/wda/dragfromtoforduration,模擬上劃進入菜單頁。注:這里不能使用/wda/swipe,沒有效果
- Client收到actinotallow=1時,代表用戶已經松手,不做響應
(4)復雜腳本指令
- 在上方提到的基本的操作之外,Client還可以接受更多命令入參并支持喚起UI自動化腳本,自動化腳本將會完成更加復雜的指令,從而實現智能化控制與使用
- 接收啟動app類型、用戶賬號密碼,頁面deeplink等,喚起app完成用戶登錄后直接跳轉進入對應頁面
- 接收app下載地址、版本號等,實現app的卸載與安裝并處理彈窗等信息
3.4 遠程畫面同步的設計與實現
關于畫面的同步,先拋一下大家熟知的ffmpeg,這是一個開源的跨平臺音視頻處理工具,它可以用于錄制、轉換和流媒體處理等多種音視頻操作。我們通過抓幀操作,數據通過ffmpeg進行處理后依次進行h.264轉碼,并將編碼信息推給到web端直播服務,當前30s的視頻約 30M,h.264轉碼后只有 3MB,畫面流目前設置為1秒20幀。
3.4.1 畫面抓取
iOS設備畫面抓取流程:
(1)WDA mjpegServer
WDA自帶mjpegServer,mjpegServer會不斷地調用截屏API,并將截屏數據壓縮后組裝成mjpeg的數據流格式發送到畫面流的端口。
(2)截屏速度/壓縮質量參數
WDA mjpegServer可以通過參數對截圖的速度,截圖后的壓縮質量進行設置。根據服務器性能和使用場景對FBMjpegServerScreenshotQuality和FBMjpegServerFramerate進行調整以得到最好效果。
人眼對幀數的感知在24幀左右,所以我們將FBMjpegServerFramerate設置為24,用戶在使用時就不會感受到卡頓(幀率的選擇在3.4.2第四小節講述)
static NSUInteger FBMjpegScalingFactor = 100; // 截圖縮放比,默認100,一般不做修改
static NSUInteger FBMjpegServerScreenshotQuality = 25; // 截圖壓縮質量,范圍1-100,默認25。值越大圖片質量越好。
static NSUInteger FBMjpegServerFramerate = 24; // 截圖輸出速度,即幀率,默認10
(3)Client畫面獲取
用戶開始使用時,會產生畫面初始化命令發送給Client。
Client通過GET請求畫面流的端口,便可以得到連續的mjpeg畫面流。
得到的畫面流數據格式是以--BoundaryString分隔開的一張張mjpeg圖片,每一張圖片都可以單獨作為jpeg圖片保存下來。
3.4.2 流媒體處理
iOS畫面流轉視頻流流程:
上文提到的Client端可以通過GET請求畫面流端口得到一張張的jpeg圖片,mjpeg是幀內編碼,數據非常大。如果直接將該畫面流數據推送給服務器,對使用方的帶寬要求會非常高,所以要轉成h.264的幀間編碼方式。
(1)Client請求畫面流端口并逐幀抓取圖片
通過ffmpeg請求畫面流端口,通過解碼器抓取每一張jpeg圖片。
(2)h.264編碼
將抓取到的每一張jpeg圖片都交給ffmpeg的編碼器,設置參數并進行h.264編碼并輸出到標準輸出。
補充:解碼器和編碼器的幀率設置需要略大于WDA設置的截屏速度,這樣才能保證畫面的響應一直是實時的。
(3)推流至流服務器
我們使用了平臺研發中心框架架構研發部多媒體組提供的流服務器。通過引入框架團隊提供的JAR包,便可方便將數據推流至服務器上。
ffmpeg編碼器標準輸出的每一幀,都會用設備在平臺上的主鍵作為唯一標識標記發送給流服務器。
公司的流服務器在接收到數據后,會根據唯一標識生成類似于直播間的播放地址。前端訪問該地址便可以看到手機的畫面。
(4)推流碼率
我們需要選取合適的幀率和碼率,以達到視頻流暢度和清晰度上的平衡:
以碼率上限設定為4.5mbps為例,用戶端所需要的網絡速度峰值550KB/s左右。
所需帶寬(KB/s) ≈ 推流碼率最大值(bps)/8/1024。
因為實際上用戶的操作速度,并不會非常快,對于帶寬的占用會更少,一般操作引起的畫面變動所需帶寬在150-200KB/s左右,而靜止狀態下所需帶寬僅在5-40KB/s
綜合各個方面,我們是以WDA截屏速度為24的基礎上適當加入了關鍵幀,將Client推流幀率定在30幀/s,碼率上限設定為4.5mbps,實測占用帶寬350KB/s左右,畫面顯示流暢、清晰、無花屏。
而我們使用的WIFI下載速度最高值在7.5MB/s左右,因此推流碼率和帶寬不是瓶頸。瓶頸主要在于ffmpeg將圖片流轉換為視頻流的效率。通過計算,Client端java單線程ffmpeg的轉碼效率在每秒40幀左右,這可以通過技術優化得到提高。
四、數據采集
作為一套相關工種的員工將賴以推進日常工作的基礎平臺來講,其穩定性必須是全維度可檢測的,不僅需要支持對系統日常運行的健康進行監控,同時也要支持采集足夠的運行數據,提供給平臺研發人員分析并推進后續的迭代工作。
平臺穩定性:通過各種監測維度數據及日志,提升用戶感知穩定性;
使用檢測量:用于評估用戶依賴平臺工作的量,后期平臺迭代對用戶影響度;
五、實踐總結
在面向自動化測試領域,包括攜程在內,其實有很多的UI自動化測試方案所采用的技術與此相似,甚至使用的技術底座都是相同的,比如WDA框架就是Facebook 推出的一項新的iOS移動測試框架。
無獨有偶,我們團隊在最初實現一些技術功能后,也是首先重點推廣于測試場景。但是攜程的業務面非常寬廣,我們不僅有開發測試場景,還有內容核驗場景,尤其是我們的國際化走在前列,有大量的海外員工也要一起參與到非常多的驗收環節。
那么像應用版本,參數配置,環境初始化,資源準備這些環節在不同國別的同事間同步或培訓,是相當耗費人力和成本的,且效果并不佳。基于我們對技術和平臺的深度分析和演進后才發現,其實技術的應用空間很廣,使一項基礎的技術平臺化起來后,很容易將場景、人員、設備、配置都統合在一起,很多交流成本可以直接降低,驗收設備的不充分利用問題也得到很好的解決,尤其是共性問題的發現和解決變得高效。
在我們后續的工作中,還將基于當前的一些體驗進行以下幾個方面的持續優化:
- 模擬器場景支持并發安裝包
- 單設備的多場景復用
最終使平臺的體驗完全可替代實機操作,讓我們的潛在用戶切身感受到上平臺比自己在手機上做各項工作更加便利與高效。