HTTP/1.1 協議該如何優化?
問你一句:「你知道 HTTP/1.1 該如何優化嗎?」

我想你第一時間想到的是,使用 KeepAlive 將 HTTP/1.1 從短連接改成長鏈接。
這個確實是一個優化的手段,它是從底層的傳輸層這一方向入手的,通過減少 TCP 連接建立和斷開的次數,來減少了網絡傳輸的延遲,從而提高 HTTP/1.1 協議的傳輸效率。
但其實還可以從其他方向來優化 HTTP/1.1 協議,比如有如下 3 種優化思路:
盡量避免發送 HTTP 請求;
在需要發送 HTTP 請求時,考慮如何減少請求次數;
減少服務器的 HTTP 響應的數據大小;
下面,就針對這三種思路具體看看有哪些優化方法。
1 如何避免發送 HTTP 請求?
這個思路你看到是不是覺得很奇怪,不發送 HTTP 請求,那還客戶端還怎么和服務器交互數據?小林你這不是耍流氓嘛?
冷靜冷靜,你說的沒錯,客戶端當然要向服務器發送請求的。
但是,對于一些具有重復性的 HTTP 請求,比如每次請求得到的數據都一樣的,我們可以把這對「請求-響應」的數據都緩存在本地,那么下次就直接讀取本地的數據,不必在通過網絡獲取服務器的響應了,這樣的話 HTTP/1.1 的性能肯定肉眼可見的提升。
所以,避免發送 HTTP 請求的方法就是通過緩存技術,HTTP 設計者早在之前就考慮到了這點,因此 HTTP 協議的頭部有不少是針對緩存的字段。
那緩存是如何做到的呢?
客戶端會把第一次請求以及響應的數據保存在本地磁盤上,其中將請求的 URL 作為 key,而響應作為 value,兩者形成映射關系。
這樣當后續發起相同的請求時,就可以先在本地磁盤上通過 key 查到對應的 value,也就是響應,如果找到了,就直接從本地讀取該響應。毋庸置疑,讀取本次磁盤的速度肯定比網絡請求快得多,如下圖:
聰明的你可能想到了,萬一緩存的響應不是最新的,而客戶端并不知情,那么該怎么辦呢?
放心,這個問題 HTTP 設計者早已考慮到。
所以,服務器在發送 HTTP 響應時,會估算一個過期的時間,并把這個信息放到響應頭部中,這樣客戶端在查看響應頭部的信息時,一旦發現緩存的響應是過期的,則就會重新發送網絡請求。HTTP 關于緩說明會的頭部字段很多,這部分內容留在下次文章,這次暫時不具體說明。
如果客戶端從第一次請求得到的響應頭部中發現該響應過期了,客戶端重新發送請求,假設服務器上的資源并沒有變更,還是老樣子,那么你覺得還要在服務器的響應帶上這個資源嗎?
很顯然不帶的話,可以提高 HTTP 協議的性能,那具體如何做到呢?
只需要客戶端在重新發送請求時,在請求的 Etag 頭部帶上第一次請求的響應頭部中的摘要,這個摘要是唯一標識響應的資源,當服務器收到請求后,會將本地資源的摘要與請求中的摘要做個比較。
如果不同,那么說明客戶端的緩存已經沒有價值,服務器在響應中帶上最新的資源。
如果相同,說明客戶端的緩存還是可以繼續使用的,那么服務器僅返回不含有包體的 304 Not Modified 響應,告訴客戶端仍然有效,這樣就可以減少響應資源在網絡中傳輸的延時,如下圖:
緩存真的是性能優化的一把-,小到 CPU Cache、Page Cache、Redis Cache,大到 HTTP 協議的緩存。
2 如何減少 HTTP 請求次數?
減少 HTTP 請求次數自然也就提升了 HTTP 性能,可以從這 3 個方面入手:
減少重定向請求次數;
合并請求;
延遲發送請求;
我們先來看看什么是重定向請求?
服務器上的一個資源可能由于遷移、維護等原因從 url1 移至 url2 后,而客戶端不知情,它還是繼續請求 url1,這時服務器不能粗暴地返回錯誤,而是通過 302 響應碼和 Location 頭部,告訴客戶端該資源已經遷移至 url2 了,于是客戶端需要再發送 url2 請求以獲得服務器的資源。
那么,如果重定向請求越多,那么客戶端就要多次發起 HTTP 請求,每一次的 HTTP 請求都得經過網絡,這無疑會越降低網絡性能。
另外,服務端這一方往往不只有一臺服務器,比如源服務器上一級是代理服務器,然后代理服務器才與客戶端通信,這時客戶端重定向就會導致客戶端與代理服務器之間需要 2 次消息傳遞,如下圖:
如果重定向的工作交由代理服務器完成,就能減少 HTTP 請求次數了,如下圖:
而且當代理服務器知曉了重定向規則后,可以進一步減少消息傳遞次數,如下圖:
除了 302 重定向響應碼,還有其他一些重定向的響應碼,你可以從下圖看到:
其中,301 和 308 響應碼是告訴客戶端可以將重定向響應緩存到本地磁盤,之后客戶端就自動用 url2 替代 url1 訪問服務器的資源。
如果把多個訪問小文件的請求合并成一個大的請求,雖然傳輸的總資源還是一樣,但是減少請求,也就意味著減少了重復發送的 HTTP 頭部。
另外由于 HTTP/1.1 是請求響應模型,如果第一個發送的請求,未收到對應的響應,那么后續的請求就不會發送,于是為了防止單個請求的阻塞,所以一般瀏覽器會同時發起 5-6 個請求,每一個請求都是不同的 TCP 連接,那么如果合并了請求,也就會減少 TCP 連接的數量,因而省去了 TCP 握手和慢啟動過程耗費的時間。
接下來,具體看看合并請求的幾種方式。
有的網頁會含有很多小圖片、小圖標,有多少個小圖片,客戶端就要發起多少次請求。那么對于這些小圖片,我們可以考慮使用 CSS Image Sprites 技術把它們合成一個大圖片,這樣瀏覽器就可以用一次請求獲得一個大圖片,然后再根據 CSS 數據把大圖片切割成多張小圖片。
這種方式就是通過將多個小圖片合并成一個大圖片來減少 HTTP 請求的次數,以減少 HTTP 請求的次數,從而減少網絡的開銷。
除了將小圖片合并成大圖片的方式,還有服務端使用 webpack 等打包工具將 js、css 等資源合并打包成大文件,也是能達到類似的效果。
另外,還可以將圖片的二進制數據用 base64 編碼后,以 URL 的形式潛入到 HTML 文件,跟隨 HTML 文件一并發送.
https://isparta.github.io/compare-webp/index.html
https://zh.wikipedia.org/wiki/https://en.wikipedia.org/wiki/Lossy_compression
https://en.wikipedia.org/wiki/Lossless_compression
https://time.geekbang.org/column/article/242667
https://www.tutorialrepublic.com/css-tutorial/css-sprites.php
https://blog.csdn.net/weixin_38055381/article/details/81504716
https://blog.csdn.net/weixin_44151887/article/details/106278559
HTTP Linux TCP/IP web前端 網絡
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。