掃二維碼與項(xiàng)目經(jīng)理溝通
我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
隨著直播行業(yè)的飛速發(fā)展,越來越多的企業(yè)涉足這一領(lǐng)域,直播間的穩(wěn)定性和用戶體驗(yàn)成為了直播平臺(tái)競(jìng)爭(zhēng)的重要因素。但是,由于直播間涉及到多個(gè)復(fù)雜的技術(shù)環(huán)節(jié),如視頻傳輸、網(wǎng)絡(luò)通訊、數(shù)據(jù)處理等,因此直播間的性能壓測(cè)顯得尤為重要。在客戶端直播間的壓測(cè)實(shí)踐中,APM壓測(cè)技術(shù)是一種常用的性能測(cè)試方法,通過對(duì)應(yīng)用程序的性能進(jìn)行實(shí)時(shí)監(jiān)控和診斷,可以快速定位和解決性能瓶頸,提升直播間的穩(wěn)定性和用戶體驗(yàn)。

創(chuàng)新互聯(lián)建站是一家專注于網(wǎng)站設(shè)計(jì)、成都網(wǎng)站設(shè)計(jì)與策劃設(shè)計(jì),鄄城網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)建站做網(wǎng)站,專注于網(wǎng)站建設(shè)十余年,網(wǎng)設(shè)計(jì)領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:鄄城等地區(qū)。鄄城做網(wǎng)站價(jià)格咨詢:13518219792
由此可知,APM壓測(cè)對(duì)于保證直播間的穩(wěn)定性、提升用戶體驗(yàn)、發(fā)現(xiàn)系統(tǒng)瓶頸和優(yōu)化系統(tǒng)性能都非常重要。
綜上所述,通過負(fù)載測(cè)試、帶寬測(cè)試、性能測(cè)試、安全測(cè)試和可靠性測(cè)試等壓測(cè)方式,可以全面評(píng)估直播間的性能、穩(wěn)定性、安全性和可靠性,從而確保直播間能夠滿足用戶的需求和期望。
得物直播間主要采用的壓測(cè)方式是負(fù)載測(cè)試、性能測(cè)試。
首先我們壓測(cè)的目標(biāo)是【基于直播間的IM性能壓測(cè)】,壓測(cè)的主要目的是監(jiān)測(cè)當(dāng)客戶端某個(gè)直播間長(zhǎng)時(shí)間接收到大量IM消息的時(shí)候,是否會(huì)出現(xiàn)卡頓、crash或者OOM等性能問題。在每次發(fā)版前跑一輪壓測(cè),提前在線下暴露直播間的性能問題,避免性能問題被帶到線上。
在具體的壓測(cè)手段上我們希望能夠滿足以下幾個(gè)條件:
基于上面幾點(diǎn)要求,在探索壓測(cè)的方式,我們直播業(yè)務(wù)組大概經(jīng)歷了下面三個(gè)階段:
直播間壓測(cè)的第一階段采用的方式比較簡(jiǎn)單,通過腳本模擬用戶發(fā)送評(píng)論、點(diǎn)贊等IM到需要壓測(cè)的房間。需要自己編寫相應(yīng)的python代碼,發(fā)送相對(duì)應(yīng)的IM消息到某個(gè)直播間,以下是部分Python腳本的部分內(nèi)容:
class APIUtils:
""" 僅適用于測(cè)試環(huán)境 """
@staticmethod
def token(user_id: int):
resp = requests.get('https://xxxx.com', params={'user_id': user_id})
return resp.json().get('token')
@staticmethod
def change_rc_im(user_id: int):
try:
im_info = requests.post(
'http://xxxx.com',
headers={'userId': '1'},
data={'kolUserId': user_id}
)
im_id = im_info.json().get('data', {}).get('list', [{}])[0].get('id', 0)
requests.post(
'http://xxxx.com',
headers={'userId': '1'},
data={'kolUserId': user_id, 'id': im_id}
)
except:
pass
time.sleep(3)
data = {
"startTime": int(time.time()) + 1,
"endTime": int(time.time()) + 600 * 6,
"kolUserId": user_id,
"imSwitch": 1,
"id": 0
}
requests.post('xxxx.com',
headers={'userId': '1'}, data=data)
@staticmethod
def get_topic(user_id: int, room_id: int):
""" 獲取房間號(hào) """
headers = {
'POIZON-USERID': str(user_id),
'POIZON-ISGUEST': 'false',
'platform': 'iPhone',
'v': '4.78.0'
}
try:
resp = requests.get('xxxx.com',
headers=headers, params={'roomId': room_id})
return resp.json().get('data').get('room').get('imInfo').get('chatRoomId')
except Exception as e:
raise e
主要流程如下圖:
這種方式實(shí)現(xiàn)的壓測(cè)比較簡(jiǎn)單,也能覆蓋一些比較重要的IM消息,但是也有幾個(gè)比較明顯的缺點(diǎn):
在本階段著重于解決上個(gè)階段遺留下來的問題,針對(duì)獲取房間ID的問題,這個(gè)只需要后端提供相應(yīng)的開播列表接口即可,問題是如何使得壓測(cè)這個(gè)流程操作起來更方便?這里我們就想到了可視化,鼠標(biāo)點(diǎn)一下就能壓測(cè)豈不是非常簡(jiǎn)單!于是我們基于前端技術(shù),使用Vue3搭建了一個(gè)簡(jiǎn)易的IM消息操作頁(yè)面,可以在這個(gè)可視化界面選擇自己想要發(fā)送的房間和IM號(hào),并且在做這個(gè)工具的同時(shí)豐富了IM消息發(fā)送的一些邏輯,可以針對(duì)消息優(yōu)先級(jí)、房間消息還是全站消息做了個(gè)性化處理,順便為IM的mock調(diào)試做了一些工作。
然后在這個(gè)基礎(chǔ)上,調(diào)接口告訴后端需要壓測(cè)的房間,再讓后端去調(diào)用第一階段的腳本去壓測(cè)相應(yīng)的房間。
該方式省去了之前需要自己去手動(dòng)獲取房間ID的麻煩,并且在做這個(gè)可視化Mock平臺(tái)的時(shí)候加入了mock IM的功能和壓測(cè)關(guān)系不大,本質(zhì)上和腳本實(shí)現(xiàn)的壓測(cè)方式并無區(qū)別。
這個(gè)階段解決了上面遺留的隨著功能迭代,消息類型覆蓋的問題,同時(shí)為了進(jìn)一步解放人工介入,基于Teslab自動(dòng)化平臺(tái),用UI腳本的方式定時(shí)去跑我們的壓測(cè)功能,實(shí)現(xiàn)了真正的自動(dòng)化壓測(cè)功能。下面分別解釋每個(gè)步驟的具體操作
在客戶端每個(gè)IM消息類型,都有一個(gè)對(duì)應(yīng)的IM消息Java類,每增加一個(gè)IM消息類型,都會(huì)有一個(gè)實(shí)體類去對(duì)應(yīng),這些類都繼承于基類BaseLiveChatMessage,因此我們?cè)贐aseLiveChatMessage里面加了一個(gè)接口抽象方法,用于產(chǎn)生此消息類型的mock數(shù)據(jù)。
那么我們?cè)谛录覫M數(shù)據(jù)的時(shí)候,繼承BaseLiveChatMessage,就需要強(qiáng)制覆蓋這個(gè)方法,去生成自己的mock消息,非常好的解決了維護(hù)性的問題,因?yàn)椴桓采w這個(gè)mock方法是無法通過編譯的。
下面是警告消息和抽獎(jiǎng)消息的Mock代碼:
有了上面的基礎(chǔ),在測(cè)試工程里面加一個(gè)IMTest測(cè)試類,主要邏輯是掃描所有繼承BaseLiveChatMessage類的子類,然后反射構(gòu)造函數(shù),調(diào)用mock接口即可獲取到相應(yīng)IM類的mock消息實(shí)體,偽代碼如下:
//獲取BaseLiveChatMessage子類
if (allSubClass == null) {
allSubClass = ClassUtils.getAllSubClass(BaseApplication.getInstance(), BaseLiveChatMessage::class.java)
val iterator = allSubClass?.iterator()
while (iterator?.hasNext() == true) {
val next = iterator.next()
try {
next.getDeclaredMethod("mock", Int::class.java)
} catch (e: NoSuchMethodException) {
}
}
}
// ....
allSubClass?.forEach {
val o = constructorMap[it]?.newInstance() as BaseLiveChatMessage
var message: BaseLiveChatMessage? = null
message = o.mock(0)
justPostIM(message) //發(fā)送IM
}
之后的壓測(cè)就是控制發(fā)送頻率、壓測(cè)時(shí)間即可實(shí)現(xiàn)本地的壓測(cè),無需依賴服務(wù)端實(shí)現(xiàn)。
到此為止,基本已經(jīng)解決了文章最開始的幾個(gè)問題,IM消息的覆蓋率和可維護(hù)性也得到了保證。
在現(xiàn)有的基礎(chǔ)上,為了使得壓測(cè)更加自動(dòng)化,我們接入了Teslab自動(dòng)化測(cè)試平臺(tái),可以定時(shí)啟動(dòng)自動(dòng)化UI腳本,提升壓測(cè)效率,自動(dòng)化腳本是基于UiAutomator,語法非常簡(jiǎn)易,維護(hù)成本很低。
綜上,第三階段的壓測(cè)策略通過客戶端發(fā)起的方式,實(shí)現(xiàn)了IM壓測(cè)使用方式方便、支持多設(shè)備壓測(cè)和壓測(cè)指標(biāo)有記錄的目標(biāo)。同時(shí),我們還需要在實(shí)際實(shí)施過程中不斷優(yōu)化和改進(jìn),以進(jìn)一步提高壓測(cè)效率和結(jié)果的可靠性。
壓測(cè)流程圖:
壓測(cè)只是一個(gè)手段,最重要的是發(fā)現(xiàn)問題,解決問題,通過三個(gè)階段的壓測(cè)也發(fā)現(xiàn)了不少問題。
通過三個(gè)階段的壓測(cè),團(tuán)隊(duì)成功地發(fā)現(xiàn)并解決了一些iOS方面的問題。其中,最重要的是發(fā)現(xiàn)了壓測(cè)時(shí)長(zhǎng)超過20分鐘時(shí),CPU異常高并伴隨著界面卡死的情況。經(jīng)過排查,發(fā)現(xiàn)問題源于消息逐條往業(yè)務(wù)層分發(fā),導(dǎo)致CPU消耗太大和UI界面刷新太頻繁(每秒鐘刷新大幾十次)。針對(duì)這個(gè)問題,團(tuán)隊(duì)采取了兩個(gè)解決方案:一是通過定時(shí)器向業(yè)務(wù)層分發(fā)消息組,而不是逐條分發(fā)消息;二是在定時(shí)器內(nèi)部做線程切換,保證在一段時(shí)間內(nèi)只有一次的線程切換。
此外,團(tuán)隊(duì)還在壓測(cè)過程中發(fā)現(xiàn)了內(nèi)存持續(xù)上漲產(chǎn)生的OOM情況,原因是某些IM有動(dòng)畫執(zhí)行時(shí)間,一段時(shí)間內(nèi)只會(huì)執(zhí)行一次,高并發(fā)情況下就會(huì)不斷累積導(dǎo)致內(nèi)存溢出。對(duì)于這個(gè)問題,團(tuán)隊(duì)采取了對(duì)動(dòng)畫執(zhí)行的優(yōu)化方案,避免了內(nèi)存溢出的情況。
另外,通過kylin組件,團(tuán)隊(duì)還發(fā)現(xiàn)了若干內(nèi)存泄漏問題,并及時(shí)解決了這些問題,保證了直播應(yīng)用的穩(wěn)定性和可靠性??傊ㄟ^三個(gè)階段的壓測(cè),團(tuán)隊(duì)成功地發(fā)現(xiàn)和解決了多個(gè)問題,不僅提升了應(yīng)用的性能和穩(wěn)定性,也為團(tuán)隊(duì)的技術(shù)積累和發(fā)展提供了有益的經(jīng)驗(yàn)和啟示。
性能壓測(cè)的確是保證直播間穩(wěn)定、高效運(yùn)行的重要手段,但我們不能把它看作是代碼開發(fā)的終點(diǎn)。好的代碼應(yīng)該是能夠被整個(gè)團(tuán)隊(duì)共同維護(hù)的,代碼的可讀性、可維護(hù)性和可擴(kuò)展性同樣重要。只有在開發(fā)和維護(hù)過程中,不斷注重代碼質(zhì)量和團(tuán)隊(duì)協(xié)作,才能讓直播間持續(xù)地為用戶提供優(yōu)質(zhì)的服務(wù)。
在進(jìn)行直播間性能壓測(cè)的同時(shí),也需要關(guān)注代碼的可讀性和可維護(hù)性。我們應(yīng)該建立嚴(yán)格的代碼審核機(jī)制,對(duì)代碼質(zhì)量進(jìn)行監(jiān)控和控制,以確保代碼的可靠性和可擴(kuò)展性。同時(shí),注重團(tuán)隊(duì)協(xié)作,建立團(tuán)隊(duì)內(nèi)部溝通和合作的機(jī)制,讓團(tuán)隊(duì)成員能夠共同維護(hù)好直播間,提供更好的用戶體驗(yàn)。

我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流