1. 程式人生 > >HTTP/2 與 WEB 效能優化(二)

HTTP/2 與 WEB 效能優化(二)

提醒:本文最後更新於 1327 天前,文中所描述的資訊可能已發生改變,請謹慎使用。

在「HTTP/2 與 WEB 效能優化(一)」這篇部落格中,我主要寫了 HTTP/2 中的 Server Push 給 WEB 效能優化帶來的便利,今天繼續來聊一聊 HTTP/2 其他方面的改變。

我們知道,HTTP/2 並沒有改動 HTTP/1 的語義部分,例如請求方法、響應狀態碼、URI 以及頭部欄位等核心概念依舊存在。HTTP/2 最大的變化是重新定義了格式化和傳輸資料的方式,這是通過在高層 HTTP API 和低層 TCP 連線之間引入二進位制分幀層來實現的。這樣帶來的好處是原來的 WEB 應用完全不用修改,就能享受到協議升級帶來的收益。

HTTP/2 的連線

HTTP/1 的請求和響應報文,都是由起始行、首部和實體正文(可選)組成,各部分之間以文字換行符分隔。而 HTTP/2 將請求和響應資料分割為更小的幀,並對它們採用二進位制編碼。下面這幅圖中的 Binary Framing 就是新增的二進位制分幀層:

http2_binary_framing_layer

先來看看這幾個概念:

  • 幀(Frame):HTTP/2 資料通訊的最小單位。幀用來承載特定型別的資料,如 HTTP 首部、負荷;或者用來實現特定功能,例如開啟、關閉流。每個幀都包含幀首部,其中會標識出當前幀所屬的流;
  • 訊息(Message):指 HTTP/2 中邏輯上的 HTTP 訊息。例如請求和響應等,訊息由一個或多個幀組成;
  • 流(Stream)
    :存在於連線中的一個虛擬通道。流可以承載雙向訊息,每個流都有一個唯一的整數 ID;
  • 連線(Connection):與 HTTP/1 相同,都是指對應的 TCP 連線;

在 HTTP/2 中,同域名下所有通訊都在單個連線上完成,這個連線可以承載任意數量的雙向資料流。每個資料流都以訊息的形式傳送,而訊息又由一個或多個幀組成。多個幀之間可以亂序傳送,因為根據幀首部的流標識可以重新組裝。下面有一幅圖說明幀、訊息、流和連線的關係:

http2_stream_message_frame

TCP 協議本身更適合用來長時間傳輸大資料,這樣它的穩定和可靠性才能顯露出來。HTTP/1 時代太多短而小的 TCP 連線,反而更多地將 TCP 的缺點給暴露出來了。

HTTP/1 的連線

在 HTTP/1 中,每一個請求和響應都要佔用一個 TCP 連線,儘管有 Keep-Alive 機制可以複用,但在每個連線上同時只能有一個請求 / 響應,這意味著完成響應之前,這個連線不能用於其他請求(怎麼判斷響應是否結束,可以看這裡)。如果瀏覽器需要向同一個域名傳送多個請求,需要在本地維護一個 FIFO 佇列,完成一個再發送下一個。這樣,從服務端完成請求開始回傳,到收到下一個請求之間的這段時間,服務端處於空閒狀態。

後來,人們提出了 HTTP 管道(HTTP Pipelining)的概念,試圖把本地的 FIFO 佇列挪到服務端。它的原理是這樣的:瀏覽器一股腦把請求都發給服務端,然後等著就可以了。這樣服務端就可以在處理完一個請求後,馬上處理下一個,不會有空閒了。甚至服務端還可以利用多執行緒並行處理多個請求。可惜,因為 HTTP/1 不支援多路複用,這個方案有幾個棘手的問題:

  • 服務端收到多個管道請求後,需要按接收順序逐個響應。如果恰好第一個請求特別慢,後續所有響應都會跟著被阻塞。這種情況通常被稱之為「隊首阻塞(Head-of-Line Blocking)」;
  • 服務端為了保證按順序回傳,通常需要快取多個響應,從而佔用更多的服務端資源,也更容易被人攻擊;
  • 瀏覽器連續傳送多個請求後,等待響應這段時間內如果遇上網路異常導致連線被斷開,無法得知服務端處理情況,如果全部重試可能會造成服務端重複處理;
  • 另外,服務端和瀏覽器之間的中間代理裝置也不一定支援 HTTP 管道,這給管道技術的普及引入了更多複雜性;

基於這些原因,HTTP 管道技術無法大規模使用,我們需要尋找其他方案。實際上,在 HTTP/1 時代,連線數優化不外乎兩個方面:開源節流

開源

這裡說的開源,當然不是「Open Source」那個開源。既然一個 TCP 連線同時只能處理一個 HTTP 訊息,那多開幾條 TCP 連線不就解決這個問題了。是的,瀏覽器確實是這麼做的,HTTP/1.1 初始版本中允許瀏覽器針對同一個域名同時建立兩個連線,在修訂版(rfc7230)中更是去掉了這個限制。實際上,現代瀏覽器一般允許同域名併發 6~8 個連線。這個數字為什麼不能更大呢?實際上這是出於公平性的考慮,每個連線對於服務端來說都會帶來一定開銷,如果瀏覽器不加以限制,一個性能好頻寬足的終端就可能耗盡服務端所有資源,造成其他人無法使用。

但是,現在包含幾十個 CSS、JSS,幾百張圖片的頁面大有所在。為了進一步榨乾瀏覽器,開更多的源,往往我們還會對靜態資源做域名雜湊,將頁面靜態資源分散在多個子域下載入。多域名能提高併發連線數,也會帶來很多問題,例如:

  • 如果同一資源在不同頁面被雜湊到不同子域下,會導致無法利用之前的 HTTP 快取;
  • 每個域名的第一個連線都要經歷 DNS 解析的過程,這在移動端可能需要耗費幾百毫秒;
  • 更多的併發連線 + Keep-Alive 機制,會顯著增加服務端和客戶端的負擔;

這裡稍微吐槽下:本地 TCP 連線和本地埠也是一種資源,為了做 WEB 效能優化,開更多的域名讓瀏覽器建立更多的併發連線,是很霸道和不公平的做法。

另外,HTTP/1 協議頭部使用純文字格式,沒有任何壓縮,且包含很多冗餘資訊(例如 Cookie、UserAgent 每次都會攜帶),所以一個頁面的請求數越多,頭部帶來的額外開銷就越大。我們一般會用短小且獨立的域名來託管靜態資源,就是為了減小這個開銷(域名越短請求頭起始行的 URI 就越短,獨立域名不會共享主域的 Cookie,可以有效減小請求頭大小,這個策略一般稱之為 Cookie-Free Domain)。

節流

由於我們不能無限制開源,所以節流也很重要。除了砍掉頁面內容,第二次訪問時利用 HTTP 快取之外,通常能做的就只有合併請求了。根據合併的內容不同,一般又分為以下幾種:

  • 非同步介面合併(Batch Ajax Request);
  • 圖片合併,雪碧圖(CSS Sprite);
  • CSS、JS 合併(Concatenation);
  • CSS、JS 內聯(Inline);
  • 圖片、音訊內聯(Data URI);

上面這份列表並不完整,我也沒打算列全,這些就足以說明 HTTP/1 時代我們在效能上所做過的不懈努力了。可惜,他們並不完美,分別列舉一下他們的缺點:

非同步介面合併:批量介面返回的時間受木桶效應影響,最慢的那個介面拖累了其他介面。

圖片合併:首先,為了顯示一張小圖,而不得不載入合併後的整張大圖,一是可能浪費流量;二是佔用更多記憶體。其次,合併圖片中任何一處修改,都會導致整張大圖快取失效。這些問題可以根據不同場景,選用 Data URI、Icon Font、SVG 等技術來改造。另外,雪碧圖的生成和維護都比較繁瑣,最好使用工具自動管理。

CSS、JS 合併:合併後的資源需要整體載入完才開始解析、執行。原本載入完一個檔案就可以解析並執行一個,將很多個檔案合併成一個巨無霸,會整體推後可用時間。為此,Chrome 新版引入了 Script Streaming 技術,能邊載入邊解析 JS 檔案。Gmail 為了解決這個問題,將多個 JS 檔案合併為一個由多個 inline script 片段組成的 html,用 iframe 引入,以達到邊載入變解析執行的效果。另外,與圖片合併類似,CSS、JS 合併也會遇到「無論多小的改動,都會導致整個合併檔案快取失效」的問題。

CSS、JS 內聯:上篇文章我詳細分析過內聯的優點和弊端。主要兩個問題:1)無法利用快取;2)多頁面無法共享。

圖片、音訊內聯:除了也有上面兩個問題之外,二進位制檔案以 Data URI 方式內聯,需要進行 Base64 編碼,體積會變大 1/3。

結論

HTTP/1 時代,我們為了節省昂貴的 HTTP 連線(TCP 連線),採用了各種優化手段,這些方案或多或少會引入一些問題,但是相比收益來說還是值得做,也應該做。但是,有了 HTTP/2 的多路複用和頭部壓縮,HTTP 連線變得可以隨心所欲了,本文提到的這些連線數優化手段確實可以退休了。

哦對了,據官方預測,HTTP/1 至少還需要 10 年才能徹底退出歷史舞臺,另外儘管 HTTP/2 協議允許脫離 TLS 部署,但 Chrome 和 Firefox 都表示不支援非 TLS 的 HTTP/2,之後很可能一個網站會同時提供 HTTP/1.1、HTTP/1.1 over TLS、HTTP/2 over TLS 三種服務。如何在每種情況下,都能給使用者提供最好的體驗,需要更加深入的優化研究和更加精細的優化策略。由此可見,在很長一段時間內,WEB 效能優化非但不會落幕,反而會更加重要。

備註

--EOF--

提醒:本文最後更新於 1327 天前,文中所描述的資訊可能已發生改變,請謹慎使用。

相關推薦

HTTP/2 WEB 效能優化

提醒:本文最後更新於 1327 天前,文中所描述的資訊可能已發生改變,請謹慎使用。 在「HTTP/2 與 WEB 效能優化(一)」這篇部落格中,我主要寫了 HTTP/2 中的 Server Push 給 WEB 效能優化帶來的便利,今天繼續來聊一聊 HTTP/2 其他方面的改變。 我們知道,HT

HTTP/2 WEB 效能優化

提醒:本文最後更新於 1333 天前,文中所描述的資訊可能已發生改變,請謹慎使用。 2013 年 11 月份開始,我的部落格開始支援了 SPDY 協議(詳見這裡),也就是 HTTP/2 的前身。今年二月份,Google 宣佈將在 16 年初放棄對 SPDY 的支援,隨後 Google 自家支援

HTTP/2 WEB 效能優化

提醒:本文最後更新於 1320 天前,文中所描述的資訊可能已發生改變,請謹慎使用。 在連續寫了兩篇關於「HTTP/2 與 WEB 效能優化」的文章後,今天來寫這個系列的最後一篇。在正式開始之前,我們先來簡單回顧下之前兩篇文章: 「HTTP/2 與 WEB 效能優化(一)」的結論是:HTTP/2

淺談前端效能優化——對HTTP傳輸進行壓縮

1、前端效能優化的一點: 對js、css、圖片等進行壓縮,儘可能減小檔案的大小,減少檔案下載的時間,從而減少網頁響應的時間。   2、前端效能優化的另一點: 對HTTP傳輸進行壓縮,即在js,css、圖片等資源已經壓縮的基礎上(其實,檔案的壓縮與否均可,檔案的壓縮跟HTTP傳輸過程的壓縮沒關

Android 效能優化之佈局優化

60fps VS 16ms 根據Google官方出品的Android效能優化典範,60幀每秒是目前最合適的影象顯示速度,事實上絕大多數的Android裝置也是按照每秒60幀來重新整理的。為了讓螢幕的重新整理幀率達到60fps,我們需要確保在時間16ms(100

MySQL批量插入效能優化

"jdbc:mysql://192.168.104.163:3306/testdb",                                          "vcom", "vcom", 2, 4,                                          "c:\\te

WEB效能優化:Resin下的 GZIP壓縮

最近在做前端的效能優化,發現一個頁面引入的js、css等外部資源過多的話,瀏覽器第一次請求的時候會下載很大的資源,那麼在使用者網路不好的情況下,頁面的載入速度會受很大的影響,因此要對WEB前端做各種優化。 在此第一步做的就是所有資源的壓縮,在開發環境編寫好的js和css檔案

使用UE4開發VR專案_效能優化_思路和方法

  把佔螢幕面積較大的,靠視點較近的,半透明較多的,材質複雜的,邊界盒較大的,粒子數量多的進行集中優化。離視點較遠的,可以使用LOD減少粒子繪製。當GPU進行立體渲染(Stereo Rendering)的時候,當視點越近,視差看到位移的位置就越遠。離視點近的粒子很容易出錯。引擎裡的粒子大多數都是面向攝像機的一

高併發&效能優化------系統監控工具使用

上一篇主要從總體介紹了高併發&效能優化的相關思路和方法,本篇主要介紹系統監控工具。     【CPU檢視工具】 ------top命令(效能) 進入top命令後,按1即可看到每核CPU的執行指標與詳細指標: 咱們依次說明下紅框裡面的引數: Load Average

手遊客戶端的效能----Unity和C#版之字串拼接,Struct和Class的區別應用

接著上篇文章: 2、字串拼接(簡單,直接結論)        使用“a” + “b”在幾次(10次以內吧)連線是不會產生gc的但是大量連線就會產生;         連線多的用StringBuilder,內部

淺談JavaSE效能優化1——BufferedImage畫素級渲染

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

web前端學習html學習筆記部分7--web儲存2

1.2.20  web儲存 1.2.20.1  Web儲存-客戶端儲存資料新方法   1.兩種方式     1)localStorage - 沒有時間限制的資料儲存     2)針對一個sessionStorage - 針對一個session的資料儲存   2.與coo

Web前端效能優化

1. 靜態資源的壓縮與合併 我們在開發的時候會習慣縮排和寫註釋,方便我們在日常的維護,但將程式碼上傳至服務端後,我們完全可以把那些空格、製表符、換行符進行壓縮,以此減少請求資源的大小;同樣的,我們在服務端所引用的第三方庫進行合併,能減少 HTTP 的請求數量 將

【MySql】Sql優化——影響效能的因素

一、前言 在上一篇部落格中,小編向大家簡單介紹了一下Mysql執行的流程:客戶端傳送一條查詢給資料庫伺服器,伺服器先進行許可權檢測,然後在快取中查詢,如果命中了快取,就立即返回儲存在快取中的結果,如果沒有,就再經過解析器解析,前處理器進行預處理,優化器優化,得到

Web前端效能優化新增Expires頭

什麼是Expires頭? Expires儲存的是一個用來控制快取失效的日期。當瀏覽器看到響應中有一個Expires頭時,它會和相應的元件一起儲存到其快取中,只要元件沒有過期,瀏覽器就會使用快取版本而不會進行任何的HTTP請求。Expires設定的日期格式必須為GMT

開源處理器Rocket的分支預測機制研究效能評估

3 Rocket處理器分支預測機制分析 3.1 分支預測機制設計分析 Rocket處理器除了實現BTB、BHT,還實現了RAS,都在BTB Module中實現,BTB Module的介面以及與Rocket Core的連線如圖3所示。 Rocket處理器主要在流水線的取

Oracle 查詢技巧優化 多表查詢

前言 上一篇blog介紹了Oracle中的單表查詢和排序的相關技巧(http://blog.csdn.net/wlwlwlwl015/article/details/52083588),本篇blog繼續介紹查詢中用的最多的——多表查詢的技巧與優化方式,下面依舊

前端效能優化-- 檔案的壓縮合併

首先我們需要搞清楚,我們為什麼需要進行檔案的壓縮與合併?壓縮與合併的原因主要有兩點 減少HTTP請求數 減小HTTP的請求大小 這裡的主要優化方式有3點: HTML/CSS/JS檔案的壓縮 CSS/JS檔案的合併 開啟GZIP壓縮 如何進行HTML壓縮 使用線上網站壓縮

2. 垃圾收集器記憶體分配策略

上一篇我們已經討論了記憶體回收的內容,我們再來說一下,物件的記憶體分配策略往大方向講,就是在堆上分配,物件主要分配在新生代的Eden區上,如果啟用了本地執行緒分配緩衝,將按執行緒優先在TLAB上分配。普

MySQL優化——什麼影響了MySQL效能

影響效能的幾個方面: 伺服器硬體 伺服器系統 資料庫儲存引擎的選擇 資料庫引數配置 資料庫結構設計和SQL語句 一、伺服器硬體 1、CPU的選擇 我們的應用是否是CPU密集型的 對於cpu密集型的應用,我們需要加快sql語句的處理速度。