為什么要優(yōu)化網(wǎng)絡(luò)性能
對(duì)于一款互聯(lián)網(wǎng)應(yīng)用册舞,用戶體驗(yàn)是成功與否的重要指標(biāo)之一障般。
網(wǎng)絡(luò)性能一般指請(qǐng)求的成功率藐石、延時(shí)等。目前的移動(dòng)互聯(lián)網(wǎng)時(shí)代于微,前端一般扮演信息展示與用戶交互的角色驱证,網(wǎng)絡(luò)性能對(duì)用戶體驗(yàn)的影響非常巨大勺三。
據(jù)統(tǒng)計(jì),網(wǎng)頁(yè)加載時(shí)間從 1 秒增加到 3 秒祈远,跳出率就會(huì)提高 32%车份;如果網(wǎng)頁(yè)加載時(shí)間從 1 秒增加到 6 秒扫沼,跳出率就會(huì)上升 106%缎除。
對(duì)于移動(dòng)端APP器罐,現(xiàn)在普遍在提一個(gè)APP秒開(kāi)率(1S內(nèi)完成APP冷啟動(dòng)及首頁(yè)展)和頁(yè)面秒開(kāi)率(1S內(nèi)完成頁(yè)面跳轉(zhuǎn)轰坊、渲染及展示)的指標(biāo)祟印,想要提高秒開(kāi)率颤芬,提高網(wǎng)絡(luò)性能是其中非常重要的一環(huán)驻襟。
HTTP請(qǐng)求流程
HTTP(Hyper Text Transfer Protocol,超文本傳輸協(xié)議)是目前移動(dòng)端應(yīng)用最廣泛的網(wǎng)絡(luò)傳輸協(xié)議之一减牺,掌握原理是優(yōu)化的第一步拔疚。
常規(guī)的HTTP請(qǐng)求流程如下圖所示:
整個(gè)流程中稚失,除了客戶端發(fā)起請(qǐng)求吸占、服務(wù)端處理這兩個(gè)在端上處理的環(huán)節(jié)凿宾,其余都與網(wǎng)絡(luò)有交互件蚕。兩個(gè)端上的處理,一般可以通過(guò)算法優(yōu)化排作、處理邏輯優(yōu)化等降低耗時(shí),這里我們不多做分析势似,下面我們主要看下與網(wǎng)絡(luò)交互的環(huán)節(jié)如何優(yōu)化履因。
優(yōu)化思路
DNS優(yōu)化
DNS防劫持
DNS 是將域名轉(zhuǎn)換為IP的查詢服務(wù)站故,使用UDP協(xié)議實(shí)現(xiàn)西篓。
一般客戶端的DNS功能通過(guò)查詢ISP(互聯(lián)網(wǎng)服務(wù)提供商)提供的DNS服務(wù)器實(shí)現(xiàn)。
出于性能考慮吮成,現(xiàn)代操作系統(tǒng)中內(nèi)置的本地DNS客戶端將緩存DNS搜索的結(jié)果橱乱;ISP的DNS也是如此,并不會(huì)按照DNS協(xié)議聲明的TTL去定期更新緩存粱甫。
DNS域名劫持現(xiàn)代互聯(lián)網(wǎng)最常見(jiàn)的共計(jì)方式之一泳叠,一般通過(guò)攻擊運(yùn)營(yíng)商DNS服務(wù)器或者偽造DNS服務(wù)器的方式實(shí)現(xiàn)。
DNS解析作為請(qǐng)求與網(wǎng)絡(luò)交互的第一步茶宵,如果發(fā)生DNS劫持危纫,會(huì)直接影響請(qǐng)求的成功率或者數(shù)據(jù)安全問(wèn)題。現(xiàn)在業(yè)內(nèi)常見(jiàn)的方式是采用 HTTPDNS 解決:
HTTPDNS的實(shí)現(xiàn)非常簡(jiǎn)單乌庶,就是用HTTPS代替不可靠的UDP進(jìn)行DNS查詢服務(wù)种蝶,繞開(kāi)了運(yùn)營(yíng)商的Local DNS。目前提供相關(guān)服務(wù)的公有云服務(wù)商很多安拟,例如阿里蛤吓、騰訊、網(wǎng)宿等,也可以自行搭建HTTPDNS服務(wù)。
DNS結(jié)果緩存
HTTPDNS服務(wù)通過(guò)HTTPS去進(jìn)行查詢,在沒(méi)有緩存的情況下,速度大大慢于傳統(tǒng)的UDP会油。一般一個(gè)公司的APP嫂冻,使用的域名大都相同服傍,關(guān)于這點(diǎn)我們可以通過(guò)本地緩存和定期更新(建議按照TTL間隔更新)的方式來(lái)解決从铲。
如果服務(wù)器多地部署,或者多IP,我們可以對(duì)DNS的結(jié)果進(jìn)行跑馬競(jìng)速后排序緩存,下次使用時(shí)按照之前的競(jìng)速結(jié)果使用,提高整體建聯(lián)性能押搪。
iOS在使用HTTPDNS的時(shí)候,可能有個(gè)小問(wèn)題,就是TLS的證書(shū)是對(duì)域名的,如果我們使用IP直接替換域名,會(huì)造成TLS不可用的問(wèn)題民鼓,iOS上層網(wǎng)絡(luò)庫(kù)NSURLConnection/NSURLSession沒(méi)有提供接口進(jìn)行SNI字段的配置饮亏,可以通過(guò)CFNetwork來(lái)實(shí)現(xiàn)简肴。具體實(shí)現(xiàn)搜索“iOS SNI”可以找到解決方案仍翰。
包體優(yōu)化
包體壓縮
傳輸數(shù)據(jù)的包體大小與傳輸耗時(shí)成正相關(guān)灵迫,壓縮算法是減小包體的最有效手段之一狞换。
HTTP壓縮是通過(guò)在Request的header聲明Accept-Encoding字段,表明客戶端支持的壓縮格式围苫,服務(wù)端解析后,會(huì)使用聲明列表內(nèi)的算法之一對(duì)Response的body進(jìn)行壓縮闰歪,并在Response的header內(nèi)Content-Encoding字段聲明使用的壓縮算法饱亿,客戶端收到Response后泵肄,按照此壓縮算法解壓即可獲得原始內(nèi)容银还。
目前HTTP使用的壓縮算法有:
- deflate:是同時(shí)使用了LZ77算法與哈夫曼編碼(Huffman Coding)的一個(gè)無(wú)損數(shù)據(jù)壓縮算法幽崩,無(wú)專(zhuān)利柒爵,并有眾多開(kāi)源實(shí)現(xiàn)
- gzip:基于deflate實(shí)現(xiàn)
- br:Brotli赚爵,該數(shù)據(jù)格式旨在進(jìn)一步提高壓縮比,對(duì)文本的壓縮相對(duì)deflate能增加20%的壓縮密度千所,而其壓縮與解壓縮速度則大致不變
高效序列化方式
目前在HTTP使用最多的數(shù)據(jù)系列化方式是JSON,JSON是基于文本的,雖然解析簡(jiǎn)單竿开,但是編碼長(zhǎng)度較長(zhǎng)嗦随,解析效率與傳輸效率較低唤殴。
目前比較流行的數(shù)據(jù)序列化方式是Google的Protobuf,簡(jiǎn)稱(chēng)PB乡范。PB是一種基于二進(jìn)制編碼的高效配名、輕量化的信息描述格式,它具有語(yǔ)言中立晋辆、平臺(tái)中立渠脉、高效、可擴(kuò)展等特性瓶佳,與 json芋膘、xml 相比,Protobuf 的編碼長(zhǎng)度更短、傳輸效率更高为朋。將JSON切換為PB也是比較常見(jiàn)的HTTP優(yōu)化手段臂拓,可以在降低傳輸包體大小的同時(shí),提高客戶端與服務(wù)端的編解碼速度潜腻,一舉兩得埃儿。下面是網(wǎng)上找到的pb、josn融涣、xml對(duì)比:
合并請(qǐng)求
如果一個(gè)頁(yè)面內(nèi)同時(shí)有多個(gè)請(qǐng)求童番,請(qǐng)求同時(shí)發(fā)起時(shí)可能會(huì)面臨重復(fù)建聯(lián),網(wǎng)絡(luò)帶寬擠兌等情況威鹿,影響請(qǐng)求性能剃斧,這種情況下我們會(huì)建議將請(qǐng)求進(jìn)行合并,減少請(qǐng)求數(shù)量來(lái)提高業(yè)務(wù)請(qǐng)求質(zhì)量忽你。
但是幼东,切記不可以一味地合并請(qǐng)求,因?yàn)楹喜⒑髠鬏敯w必然會(huì)變大科雳,合并的太多反而降低請(qǐng)求性能根蟹。原則上只合并相關(guān)的請(qǐng)求,降低同一個(gè)頁(yè)面的請(qǐng)求數(shù)量糟秘。
域名合并 + 連接復(fù)用
從HTTP/1.1版本開(kāi)始简逮,支持同域名的連接復(fù)用,即可以在同一個(gè)TCP連接上傳輸多個(gè)請(qǐng)求尿赚,正常HTTP請(qǐng)求需要TCP三次握手建聯(lián)和TLS握手散庶,連接復(fù)用減少了重復(fù)建聯(lián)的消耗,可以大大降低請(qǐng)求的前置耗時(shí)凌净。
連接復(fù)用的維度一般是域名悲龟,即相同的域名對(duì)應(yīng)的IP地址是相同的,可以復(fù)用相同的連接冰寻,所以可以通過(guò)合并域名的形式须教,盡量讓客戶端的請(qǐng)求使用同一個(gè)域名,大大提高連接復(fù)用的概率斩芭,優(yōu)化HTTP請(qǐng)求性能没卸。
冪等重試
冪等是指同一個(gè)請(qǐng)求多次調(diào)用,返回的結(jié)果都是相同的秒旋,對(duì)于支持冪等的請(qǐng)求约计,我們可以通過(guò)重試的方式提高請(qǐng)求的成功率。
HTTP協(xié)議中的GET迁筛、HEAD煤蚌、PUT等支持冪等耕挨,可以進(jìn)行重試。