Android端TCP長(zhǎng)連接的性能優(yōu)化教程分享
前言
大家應(yīng)該都知道,在Android端實(shí)現(xiàn)TCP長(zhǎng)連接場(chǎng)景其實(shí)不多,我們最熟悉的不過(guò)推送和HTTP協(xié)議的實(shí)現(xiàn)(OkHttp),本文討論的是在實(shí)現(xiàn)推送長(zhǎng)連接的情況下怎么來(lái)做性能優(yōu)化,下文只是我的一點(diǎn)拙見(jiàn),有不妥之處還望指出,下面話(huà)不多說(shuō)了,來(lái)一起看看詳細(xì)的介紹吧。
推送長(zhǎng)連接
可以說(shuō)大部分APP是離不開(kāi)推送(push)這個(gè)功能的,不過(guò)平常我們都是接入第三方SDK(極光、個(gè)推等)居多,因?yàn)橐鲆粋€(gè)推送服務(wù),不光客戶(hù)端要編寫(xiě)相應(yīng)的Socket通信代碼,服務(wù)器端更是麻煩,要處理大規(guī)模的長(zhǎng)連接服務(wù),消息還得及時(shí)送達(dá),一兩臺(tái)服務(wù)器可是吃不消。相對(duì)來(lái)說(shuō)客戶(hù)端編寫(xiě)Socket通信的代碼會(huì)簡(jiǎn)單一些,但是也是要處理一些平臺(tái)相關(guān)的問(wèn)題,比如推送服務(wù)進(jìn)程如何保活,APP進(jìn)程如何跟推送服務(wù)進(jìn)程通信,如何節(jié)省手機(jī)電量和手機(jī)弱網(wǎng)情況下如何提升通信質(zhì)量等一系列的問(wèn)題。這些問(wèn)題以后有時(shí)間分析,下面來(lái)看看TCP長(zhǎng)連接性能如何來(lái)優(yōu)化
影響TCP性能的點(diǎn)
TCP/IP體系太復(fù)雜了,想完全掌握確實(shí)很困難,我們只分析影響TCP性能的幾個(gè)因素,看看在Android客戶(hù)端可不可以進(jìn)行優(yōu)化
TCP連接的三次握手時(shí)延
我們知道要建立TCP連接,需要經(jīng)過(guò)三次握手,三次握手成功后連接建立成功
- 客戶(hù)端請(qǐng)求新的連接,需要發(fā)送一個(gè)設(shè)置了SYN標(biāo)記的分組,向服務(wù)器說(shuō)明這三個(gè)連接請(qǐng)求
- 如何服務(wù)器接受了這個(gè)連接請(qǐng)求,會(huì)向客戶(hù)端回送一個(gè)設(shè)置了SYN和ACK的分組,向客戶(hù)端說(shuō)明連接請(qǐng)求已經(jīng)被接受了
- 客戶(hù)端收到這個(gè)表明連接請(qǐng)求被接受的分組后,要發(fā)送一條攜帶ACK標(biāo)記的確認(rèn)消息(可能會(huì)在這個(gè)消息中攜帶業(yè)務(wù)數(shù)據(jù))表明連接已經(jīng)建立成功了,可以開(kāi)始發(fā)送數(shù)據(jù)了
那建立TCP連接的三次握手而產(chǎn)生的時(shí)延對(duì)我們會(huì)有影響嗎,大部分情況下是沒(méi)有的,只有當(dāng)HTTP請(qǐng)求傳輸?shù)臄?shù)據(jù)量比較小,然后呢這樣的HTTP請(qǐng)求又非常頻繁,這樣算下來(lái),握手產(chǎn)生的時(shí)延占比就很高了,這種情況下就要通過(guò)重用已有的連接來(lái)減少連接的次數(shù)。而推送長(zhǎng)連接本身就是在保持連接的穩(wěn)定性,無(wú)需在這點(diǎn)上進(jìn)行優(yōu)化
延遲確認(rèn)
由于因特網(wǎng)本身無(wú)法保證可靠的分組傳輸,TCP就自己實(shí)現(xiàn)確認(rèn)機(jī)制來(lái)確保數(shù)據(jù)的可靠傳輸,成功接收TCP分組數(shù)據(jù)的接收者都需要向發(fā)送者回送一個(gè)小的確認(rèn)分組,發(fā)送者在一定的時(shí)間內(nèi)沒(méi)有收到這個(gè)確認(rèn)分組,就認(rèn)為之前發(fā)送的數(shù)據(jù)沒(méi)有成功,然后會(huì)重發(fā)數(shù)據(jù)
但是由于確認(rèn)分組非常的小,TCP為了有效的利用網(wǎng)絡(luò),會(huì)把確認(rèn)分組塞到同向傳輸數(shù)據(jù)中去,組合在一起發(fā)送傳輸,如果在一定的時(shí)間內(nèi)沒(méi)有同向傳輸數(shù)據(jù)咋辦,豈不是一直會(huì)重發(fā)?TCP肯定不會(huì)允許這種情況發(fā)送的,TCP針對(duì)這種情況實(shí)現(xiàn)了一種延遲確認(rèn)算法,在一定的窗口時(shí)間(一般是100~200毫秒),確認(rèn)分組還沒(méi)有被捎帶的話(huà),那么確認(rèn)分組就會(huì)單獨(dú)發(fā)送
根據(jù)自己之前編寫(xiě)TCP長(zhǎng)連接的經(jīng)驗(yàn),一般會(huì)在應(yīng)用層設(shè)計(jì)一個(gè)業(yè)務(wù)ACK包機(jī)制,當(dāng)收到一個(gè)業(yè)務(wù)數(shù)據(jù)時(shí),馬上會(huì)回送一個(gè)業(yè)務(wù)層的ACK包,這個(gè)業(yè)務(wù)層的ACK包就是同向傳輸數(shù)據(jù),確認(rèn)分組馬上會(huì)被捎帶,不會(huì)觸發(fā)延遲確認(rèn)算法,但是如果我們收到的消息頻率很高,那產(chǎn)生的ACK包就會(huì)非常的多,再假設(shè)業(yè)務(wù)層的ACK包并不需要那么的及時(shí),我們是否可以組合業(yè)務(wù)層ACK包再發(fā)送呢?
TCP慢啟動(dòng)
TCP連接的性能還受到擁塞控制機(jī)制的影響,當(dāng)TCP連接剛開(kāi)始連接上時(shí),并不能一下子就發(fā)送很多的分組,可能是一開(kāi)始只能發(fā)送一個(gè)分組,然后收到確認(rèn)分組后,就可以發(fā)送兩個(gè)分組,然后就是四個(gè)分組,以此類(lèi)推。這個(gè)就是TCP慢啟動(dòng),發(fā)送數(shù)據(jù)的能力是慢慢提升的
由于我們編寫(xiě)的是長(zhǎng)連接,這種機(jī)制對(duì)我們的影響并不大
Nagle算法
由于TCP并沒(méi)有規(guī)定每個(gè)分組最小值,所以我們可以每次都傳輸一個(gè)字節(jié)的數(shù)據(jù),但是TCP有固定的標(biāo)記和首部(至少40個(gè)字節(jié)),如果TCP發(fā)送大量的包含少量數(shù)據(jù)的分組時(shí),網(wǎng)絡(luò)的真實(shí)利用率就很低,網(wǎng)絡(luò)整體性能會(huì)嚴(yán)重的下降。
所以呢TCP利用了Nagle算法,在發(fā)送了一個(gè)分組前,將大量TCP數(shù)據(jù)綁定在一起,提高網(wǎng)絡(luò)的效率。Nagle算法鼓勵(lì)發(fā)送全尺寸的分組,而且只有當(dāng)所有的分組都被確認(rèn)后,才能發(fā)送非全尺寸的分組,不然的話(huà)就緩存起來(lái),直到積累足夠發(fā)送一個(gè)全尺寸分組數(shù)據(jù)時(shí)才會(huì)將緩存的數(shù)據(jù)發(fā)送出去
那這個(gè)對(duì)我們編寫(xiě)TCP長(zhǎng)連接時(shí)有什么影響呢,由于我們的心跳包和ACK包一般都很小,那么服務(wù)端就不能及時(shí)收到我們的心跳包和ACK包,會(huì)產(chǎn)生時(shí)延,可以通過(guò)下面的代碼來(lái)禁用Nagle算法
Socket.setTcpNoDelay(true);
TIME_WAIT累積與端口耗盡
這個(gè)跟服務(wù)端相關(guān),一般與客戶(hù)端沒(méi)什么關(guān)系,這里就不說(shuō)了
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
- Android性能優(yōu)化以及數(shù)據(jù)優(yōu)化方法
- 簡(jiǎn)單了解Android性能優(yōu)化方向及相關(guān)工具
- Android性能之冷啟動(dòng)優(yōu)化詳析
- Android性能測(cè)試關(guān)注的指標(biāo)整理
- Android高性能日志寫(xiě)入方案的實(shí)現(xiàn)
- Android圖片性能優(yōu)化詳解
- Android性能調(diào)優(yōu)利器StrictMode應(yīng)用分析
- Android APP性能優(yōu)化分析
- 淺談android性能優(yōu)化之啟動(dòng)過(guò)程(冷啟動(dòng)和熱啟動(dòng))
- 獲取Android界面性能數(shù)據(jù)的快捷方法
相關(guān)文章
Android使用MediaCodec將攝像頭采集的視頻編碼為h264
這篇文章主要為大家詳細(xì)介紹了Android使用MediaCodec將攝像頭采集的視頻編碼為h264,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-10-10Android 判斷SIM卡屬于哪個(gè)移動(dòng)運(yùn)營(yíng)商的實(shí)現(xiàn)代碼
有時(shí)候我們需要在Android中獲取本機(jī)網(wǎng)絡(luò)提供商呢,這里簡(jiǎn)單分享下,方便需要的朋友2013-05-05Android自定義RecyclerView實(shí)現(xiàn)不固定刻度的刻度尺
這篇文章主要為大家詳細(xì)介紹了Android自定義RecyclerView實(shí)現(xiàn)不固定刻度的刻度尺,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-07-07Android實(shí)現(xiàn)bitmap指定區(qū)域滑動(dòng)截取功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)bitmap指定區(qū)域滑動(dòng)截取功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09Android開(kāi)發(fā)AsmClassVisitorFactory使用詳解
這篇文章主要為大家介紹了Android開(kāi)發(fā)AsmClassVisitorFactory使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06Android 解決游戲發(fā)行切包資源索引沖突的問(wèn)題
這篇文章主要介紹了Android 解決游戲發(fā)行切包資源索引沖突的問(wèn)題,幫助大家更好的理解和學(xué)習(xí)使用Android,感興趣的朋友可以了解下2021-03-03Android實(shí)現(xiàn)錄音功能實(shí)現(xiàn)實(shí)例(MediaRecorder)
本篇文章主要介紹了Android實(shí)現(xiàn)錄音的實(shí)例代碼(MediaRecorder),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-07-07Android GestureDetector手勢(shì)滑動(dòng)使用實(shí)例講解
這篇文章主要為大家詳細(xì)介紹了Android GestureDetector手勢(shì)滑動(dòng)使用實(shí)例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-07-07