深入淺出:HTTP/2

上篇文章深入淺出:5G和HTTP里給自己挖了一根深坑,說是要寫一篇關于HTTP/2的文章,今天來還賬了。

本文分為以下幾個部分:

  1. HTTP/2的背景
  2. HTTP/2的特點
  3. HTTP/2的協議分析
  4. HTTP/2的支持?

HTTP/2簡介

HTTP/2主要是為了解決現HTTP 1.1性能不好的問題才出現的。當初Google為了提高HTTP性能,做出了SPDY,它就是HTTP/2的前身,后來也發展成為HTTP/2的標準。

HTTP/2兼容HTTP 1.1,例如HTTP Method,Status code,URI以及大部分Header Fields。

HTTP/2通過以下方法減少latency,用來改進頁面加載的速度,

  1. HTTP Header的壓縮,采用的是HPack算法。
  2. HTTP/2的Server Push,非常重要的一個特性。
  3. 請求的pipeline。
  4. 修復在HTTP 1.x的隊頭阻塞問題。
  5. 在單個TCP連接里多工復用請求。

HTTP/2支持HTTP 1.1里的大部分use case,例如桌面瀏覽器、移動瀏覽器、Web API、Web Server、代理服務器、反向代理服務器、防火墻和CDN等。

HTTP/2 頭部壓縮(HPack)

HPack是HTTP/2 里HTTP頭壓縮的算法,具體可以參看https://tools.ietf.org/html/rfc7541。下面簡單介紹一下HPack是如何工作的。

見下圖,該圖來自Google 的性能專家 Ilya Grigorik 的文章HTTP/2 is here, let's optimize!,它非常直觀地描述了 HTTP/2 中頭部壓縮的原理:

簡單說,HTTP頭壓縮需要在HTTP/2 Client和服務端之間:

  • 維護一份相同的靜態表(Static Table),包含常見的頭部名稱,以及特別常見的頭部名稱與值的組合;
  • 維護一份相同的動態表(Dynamic Table),可以動態地添加內容;
  • 基于靜態哈夫曼碼表的哈夫曼編碼(Huffman Coding);

在HTTP頭里,有些key:value是固定,例如:

 :method: GET:scheme: http

在編碼時,它們直接用一個index編號代替,例如:method:GET是2,這些在一個靜態表定義。靜態表的定義如下,總共61個Header Name,點擊URL https://tools.ietf.org/html/rfc7541#appendix-A查看所有靜態表的定義。

?

IndexHeader NameHeader Value
1:authority?
2:methodGET
3:methodPOST
4:path/
5:path/index.html
6:schemehttp
7:schemehttps
8:status200
.........
32cookie?
.........
60via?
61www-authenticate?

?

使用靜態表、動態表、以及Huffman編碼可以極大地提升壓縮效果。對于靜態表里的字段,原來需要N個字符表示的,現在只需要一個索引即可,對于靜態、動態表中不存在的內容,還可以使用哈夫曼編碼來減小體積。HTTP/2 標準里也給出了一份詳細的靜態哈夫曼碼表(https://tools.ietf.org/html/rfc7541#appendix-B),它們需要內置在客戶端和服務端之中。

關于HPack的算法和實現,后面專門抽一篇文章來寫。

HTTP/2 ALPN

HTTP/2協議里有個negotiation的機制,讓客戶端和服務器選擇使用HTTP 1.1還是2.0,這個是由ALPN來實現,關于ALPN,可以參看

ALPN(Transport Layer Security (TLS) Application-Layer Protocol Negotiation Extension,https://tools.ietf.org/html/rfc7301。?

下面是抓包截圖,在TLS里的Client Hello的包里,我們可以看到ALPN里由H2和HTTP/1.1,這就是說客戶端支持HTTP2以及HTTP 1.1.

當Server收到后,會識別Client發過來的協議列表,如果不認識就忽略掉。如果認識多個,則選擇一個最合適的協議發布給Client。也是在Server Hello里的ALPN返回,見下圖。

HTTP/2 Server Push機制

Server Push是HTTP 2最重要的一個特性。

在HTTP 1.1里,在同一個 TCP 連接里面,上一個回應(response)發送完了,服務器才能發送下一個,但在HTTP/2里,可以將多個回應一起發送。

下圖是PUSH模式,當請求一個HTML時,如果HTML里有CSS文件,server會一并推給client,而不像在HTTP 1.1下,還需要再發一個CSS的請求。

根據上圖,從理論上PUSH模式下性能會好很多。

舉個例子解釋一下。下面是一個簡單的HTML頁面,假說是index.html 。

<html>
<head><link rel="stylesheet" href="style.css">
</head>
<body><p>This is a sample to illustrate how HTTP/2 works</p><img src="example.png">
</body>
</html>

這里有三個文件需要處理:該HTML頁面、CSS文件style.css以及圖片example.png。在HTTP 1.1里為了處理這三個文件,Client需要發三個請求給Server。

首先,發送一個請求index.html,

GET /index.html HTTP/1.1

Client解析該HTML文件,繼而知道有2個style.css和example.png資源文件下載。

Client繼續發送2個請求下載他們。

GET /style.css  HTTP/1.1

以及

GET /example.png  HTTP/1.1

一般為了解決這兩個問題,像CSS文件,可以把CSS code直接放在HTML里,也可以把example.png轉化為base64 code嵌入在HTML里,以上只是把外部資源文件合并到HTML里。

除了上述方法,還有一個優化的方法,就是Preload(預加載),可以參看這里,https://w3c.github.io/preload/。?

所以我們可以把HTML代碼改成如下:

<link rel="preload" href="/styles.css" as="style">
<link rel="preload" href="/example.png" as="image">

那Preload是什么意思呢?就是說下載前一個頁面時,可以把相關的資源文件預先加載好,這樣感覺起來會快一些。但是有一個關鍵問題需要注意,即便是預加載的情況下,也不能減少HTTP請求次數。?

針對上面的問題,我們引出服務器推送(server push)。根據上面的圖,我們可以看出,Server還沒有收到Client的請求,就把各種資源推送給Client。

拿上面例子繼續舉例,當Client只請求index.html,但是Server把index.htmlstyle.cssexample.png全部發送給瀏覽器。這樣只需要一輪 HTTP 通信,Client就得到了全部資源。

?

HTTP/2的支持

現在主流的軟件都支持HTTP/2.

瀏覽器

基本上大部分瀏覽器在2015年底都支持HTTP/2了,包括Chrome、Opera、Firefox、IE 11、Safari,Edge。

在Chrome上,可以下載插件HTTP Indicator,判斷訪問的網站是否支持HTTP/2.

也可以打開Chrome的開發者工具,打開Network tab,可以看到Protocol為h2的就是HTTP/2請求。如果Initiator為push的,說明開啟了Server Push模式。

?

常用Server軟件

  1. Apache HTTPd,從版本2.4.12開始支持,通過模塊mod_h2來支撐。
  2. Apache Tomcat,從版本8.5開始支持。
  3. Jetty從9.3開始支持。
  4. Netty從4.1開始。
  5. IIS在Win10和WIndows Server 2016支持。
  6. Ngnix從1.9.5開始支持HTTP2,但Server Push功能則在1.13.9才開始。

硬件

  1. Ctrix NetScaler從11.x開始支持
  2. F5 BIG-IP從11.6開始。

CDN/Cloud

  1. Akamai
  2. AWS
  3. Azure
  4. Aliyun
  5. Tecent Cloud

緩存問題

如果開啟了Server Push模式,我們很容易意識到一個問題,那就是緩存問題。Server見到HTML頁面就把外部資源push給Client,如果沒有緩存,其實很浪費。為了解決這個問題,可以在第一次請求時push,后面的請求都不push了。

服務器推送有一個很麻煩的問題。所要推送的資源文件,如果瀏覽器已經有緩存,推送就是浪費帶寬。即使推送的文件版本更新,瀏覽器也會優先使用本地緩存。下面是 Nginx 官方給出的示例,根據 Cookie 判斷是否為第一次訪問(https://www.nginx.com/blog/nginx-1-13-9-http2-server-push/)。

server {listen 443 ssl http2 default_server;ssl_certificate ssl/certificate.pem;ssl_certificate_key ssl/key.pem;root /var/www/html;http2_push_preload on;location = /demo.html {add_header Set-Cookie "session=1";add_header Link $resources;}
}map $http_cookie $resources {"~*session=1" "";default "</style.css>; as=style; rel=preload, </image1.jpg>; as=image; rel=preload, </image2.jpg>; as=image; rel=preload";

HTTP/2的性能

有人專門做過測試,https://www.smashingmagazine.com/2017/04/guide-http2-server-push/#measuring-server-push-performance,借用該文的一張圖片,

可以看出,啟用HTTP/2后性能并未大幅度提升,所以在使用HTTP/2還是謹慎一些,如果使用不當,反而會使性能下降。

另外,Ngnix專門撰文描述7個提高HTTP/2的技巧https://www.nginx.com/blog/7-tips-for-faster-http2-performance/?。

參考文章:

  1. https://en.wikipedia.org/wiki/HTTP/2
  2. https://tools.ietf.org/html/rfc7301
  3. https://tools.ietf.org/html/rfc7541?(HPack)
  4. http://www.ruanyifeng.com/blog/2018/03/http2_server_push.html
  5. https://www.nginx.com/blog/nginx-1-13-9-http2-server-push/
  6. https://www.smashingmagazine.com/2017/04/guide-http2-server-push/#measuring-server-push-performance
  7. https://www.nginx.com/blog/7-tips-for-faster-http2-performance/?
  8. https://w3c.github.io/preload/
  9. http://velocityconf.com/devops-web-performance-2015/public/schedule/detail/42385

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/388798.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/388798.shtml
英文地址,請注明出處:http://en.pswp.cn/news/388798.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

畫了個Android

畫了個Android 今晚瞎折騰&#xff0c;閑著沒事畫了個機器人——android&#xff0c;浪費了一個晚上的時間。畫這丫還真不容易&#xff0c;為那些坐標&#xff0c;差點砸了鍵盤&#xff0c;好在最后畫出個有模有樣的&#xff0c;心稍安。 下面來看看畫這么個機器人需要些什么東…

數據治理 主數據 元數據_我們對數據治理的誤解

數據治理 主數據 元數據Data governance is top of mind for many of my customers, particularly in light of GDPR, CCPA, COVID-19, and any number of other acronyms that speak to the increasing importance of data management when it comes to protecting user data.…

mysql 選擇前4個_mysql從4個表中選擇

不要認為GROUP BY是必需的 . 雖然如果一個孩子有2個父記錄&#xff0c;你可能想用它來將2個父母分組到一行 - 但不確定這是否是你的要求 . 因為如果一個孩子有2個父母&#xff0c;那么將為該孩子返回的父母是未定義的 .假設所有孩子都有父母&#xff0c;所有父母都會有姓&#…

提高機器學習質量的想法_如何提高機器學習的數據質量?

提高機器學習質量的想法The ultimate goal of every data scientist or Machine Learning evangelist is to create a better model with higher predictive accuracy. However, in the pursuit of fine-tuning hyperparameters or improving modeling algorithms, data might …

mysql 集群實踐_MySQL Cluster集群探索與實踐

MySQL集群是一種在無共享架構(SNA&#xff0c;Share Nothing Architecture)系統里應用內存數據庫集群的技術。這種無共享的架構可以使得系統使用低廉的硬件獲取高的可擴展性。MySQL集群是一種分布式設計&#xff0c;目標是要達到沒有任何單點故障點。因此&#xff0c;任何組成部…

Python基礎:搭建開發環境(1)

1.Python語言簡介 2.Python環境 Python環境產品存在多個。 2.1 CPython CPython是Python官方提供的。一般情況下提到的Python就是指CPython&#xff0c;CPython是基于C語言編寫的。 CPython實現的解釋器將源代碼編譯為字節碼&#xff08;ByteCode&#xff09;&#xff0c;再由虛…

python數據結構之隊列(一)

隊列概念隊列&#xff08;queue&#xff09;是只允許在一端進行插入操作&#xff0c;而在另一端進行刪除操作的線性表。隊列是一種先進先出的&#xff08;First In First Out&#xff09;的線性表&#xff0c;簡稱FIFO。允許插入的一端為隊尾&#xff0c;允許刪除的一端為隊頭。…

Android實現圖片放大縮小

Android實現圖片放大縮小 package com.min.Test_Gallery; import Android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; import android.graphics.Matrix; import android.os.Bun…

matlab散點圖折線圖_什么是散點圖以及何時使用

matlab散點圖折線圖When you were learning algebra back in high school, you might not have realized that one day you would need to create a scatter plot to demonstrate real-world results.當您在高中學習代數時&#xff0c;您可能沒有意識到有一天需要創建一個散點圖…

java判斷題_【Java判斷題】請大神們進來看下、這些判斷題你都知道多少~

該樓層疑似違規已被系統折疊 隱藏此樓查看此樓、判斷改錯題(每題2分&#xff0c;共20分)(正確的打√&#xff0c;錯誤的打并說明原因)1、 Java系統包提供了很多預定義類,我們可以直接引用它們而不必從頭開始編寫程序。 ( )2、 程序可以用字符‘*’替代一個TextField中的每個字…

PoPo數據可視化第8期

PoPo數據可視化 聚焦于Web數據可視化與可視化交互領域&#xff0c;發現可視化領域有意思的內容。不想錯過可視化領域的精彩內容, 就快快關注我們吧 :) 微信訂閱號&#xff1a;popodv_com谷歌決定關閉云可視化服務 Fusion Tables谷歌宣布即將關閉其 Fusion Tables 云服務&#x…

AC自動機題單

AC自動機題目 真的超級感謝xzy 真的幫到我很多 題單 [X] [luogu3808]【模板】AC自動機&#xff08;簡單版&#xff09; https://www.luogu.org/problemnew/show/P3808[X] [luogu3796]【模板】AC自動機&#xff08;加強版&#xff09;https://www.luogu.org/problemnew/show/P37…

java list用法_Java List 用法詳解及實例分析

Java List 用法詳解及實例分析Java中可變數組的原理就是不斷的創建新的數組&#xff0c;將原數組加到新的數組中,下文對Java List用法做了詳解。List:元素是有序的(怎么存的就怎么取出來&#xff0c;順序不會亂)&#xff0c;元素可以重復(角標1上有個3&#xff0c;角標2上也可以…

python字符串和List:索引值以 0 為開始值,-1 為從末尾的開始位置;值和位置的區別哦...

String&#xff08;字符串&#xff09;Python中的字符串用單引號 或雙引號 " 括起來&#xff0c;同時使用反斜杠 \ 轉義特殊字符。 字符串的截取的語法格式如下&#xff1a; 變量[頭下標:尾下標]索引值以 0 為開始值&#xff0c;-1 為從末尾的開始位置。[一個是值&#x…

邏輯回歸 python_深入研究Python的邏輯回歸

邏輯回歸 pythonClassification techniques are an essential part of machine learning and data science applications. Approximately 70% of problems in machine learning are classification problems. There are lots of classification problems that are available, b…

spring定時任務(@Scheduled注解)

&#xff08;一&#xff09;在xml里加入task的命名空間 xmlns:task"http://www.springframework.org/schema/task" http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd&#xff08;二&#xff09;啟用注…

net user 用戶名 密碼 /add 建立用戶

net user 用戶名 密碼 /add 建立用戶 other: net use \\ip\ipc$ " " /user:" " 建立IPC空鏈接 net use \\ip\ipc$ "密碼" /user:"用戶名" 建立IPC非空鏈接 net use h: \\ip\c$ "密碼" /user:"用戶名" 直接登陸后映…

JavaScript是如何工作的:與WebAssembly比較及其使用場景

*摘要&#xff1a;** WebAssembly未來可期。 原文&#xff1a;JavaScript是如何工作的&#xff1a;與WebAssembly比較及其使用場景作者&#xff1a;前端小智Fundebug經授權轉載&#xff0c;版權歸原作者所有。 這是專門探索 JavaScript及其所構建的組件的系列文章的第6篇。 如果…

友元 java_C++ 友元關系詳解

在C中&#xff0c;在某些情況下&#xff0c;允許特定的非成員函數訪問一個類的私有成員&#xff0c;同時仍然阻止一般的訪問&#xff0c;這是很方便做到的。例如&#xff0c;被重載的操作符&#xff0c;如輸入或輸出操作符&#xff0c;經常需要訪問類的私有數據成員。這些操作符…

Matplotlib中的“ plt”和“ ax”到底是什么?

Indeed, as the most popular and fundamental data visualisation library, Matplotlib is kind of confusing in some perspectives. It is usually to see that someone asking about的確&#xff0c;作為最受歡迎的基礎數據可視化庫&#xff0c;Matplotlib在某些方面令人困…