HTTP協議-3-HTTP/2是如何維持長連接的?

先說結論:HTTP/2的“長連接” = 一個TCP連接 + 多路復用 + 二進制幀 + 流控制 + 持久會話管理
它不只是“連接不斷”,更關鍵的是:在這個長連接上,可以同時并發傳輸成百上千個請求和響應,互不阻塞!

1、HTTP/2的“長連接”從哪開始?

和HTTP/1.1一樣,HTTP/2也是基于TCP協議的。

首先會做的事情和HTTP1.1還是一樣的,如:
1、客戶端(比如瀏覽器)和服務器建立TCP連接
2、然后進行TLS握手(如果是HTTPS,可選)

握手完成后,客戶端發送一個特殊的“連接前綴”(Connection Preface),如:

"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"

它的作用是告訴服務器:
“我要用HTTP/2了,別當成HTTP/1.x處理。”

從此刻起,這個TCP連接就被“升級”為一個HTTP/2連接,并期望長期保持。

2、核心機制:多路復用(Multiplexing),讓一個連接“變寬”

(1)、HTTP/1.1的問題(串行排隊)

在HTTP/1.1中,即使有keep-alive,也只能:

  • 發請求A → 等響應A → 發請求B → 等響應B → …
  • 或者開6個TCP連接來并發(浪費資源)

這就像是:一條單車道公路,雖然可以供多輛汽車經過,但汽車只能一輛一輛走。

主要問題:

  • 隊頭阻塞(Head-of-Line Blocking):HTTP/1.1的每個請求必須串行發送(一個接一個),前一個請求未完成時,后續請求必須排隊等待。例如,加載網頁時,如果圖片A的請求卡住了,CSS和JS的請求也會被堵住。
  • 頻繁建立連接:為了并行請求,瀏覽器通常會建立多個TCP連接(如6-8個),但頻繁的連接建立和關閉會消耗資源。
(2)、HTTP/2的解決方案:多路復用

HTTP/2把所有請求和響應拆成小塊(幀),然后在同一個TCP連接上交錯發送。

這就像是: HTTP/2將一個TCP連接想象成一條多車道公路,每個請求和響應是不同的車輛(數據流),它們可以并行行駛(并發傳輸),互不干擾。

  • 每個請求/響應對(如一個圖片請求和它的響應)被分配一個唯一的Stream ID(流標識符),接收方通過這個ID將數據重新組裝。
  • 示例:
    • 請求1(圖片A):Stream ID = 1
    • 請求2(CSS文件):Stream ID = 3
    • 請求3(JS文件):Stream ID = 5
    • 這些請求的數據幀可以混合在同一個TCP連接上傳輸,服務器根據Stream ID分別處理。

效果:

  • 單連接并發請求和處理:一個TCP連接可以同時處理數十甚至上百個請求,無需反復建立連接。
  • 消除隊頭阻塞:即使某個請求的數據包丟失,其他請求的數據仍能繼續傳輸。

3、關鍵技術:二進制分幀層(Binary Framing Layer)

這是實現多路復用的底層基礎。

1、消息結構分層

HTTP/2把通信分成三層:
在這里插入圖片描述

2、什么是Frame(幀)?

HTTP/1.1的文本格式問題:

  • HTTP/1.1的請求和響應使用純文本格式(如GET /index.html HTTP/1.1),解析效率低,且冗余信息多(如重復的頭部字段)

HTTP/2的二進制分幀:

  • 數據切片:HTTP/2將每個請求/響應拆分成多個幀(Frame),每個幀是二進制格式的小數據塊。

幀有種類:

  • HEADERS幀:存放請求頭或響應頭(如Host、User-Agent)
  • DATA幀:存放請求體或響應體(如 HTML 內容)。
  • SETTINGS幀:配置參數
  • PING幀:心跳探測
  • RST_STREAM幀:取消某個流
  • GOAWAY幀:優雅關閉連接

每個幀的格式像這樣:
在這里插入圖片描述
注意:Stream ID它決定了這個幀屬于哪個“對話”。

示例:

  • 請求GET /image.jpg會被拆分為:
    1、HEADERS幀(包含Host: example.com等頭部)。
    2、DATA幀(可能分多個,傳輸圖片的二進制數據)。
  • 服務器收到后,根據Stream ID和幀類型重組完整請求。

效果:

  • 高效解析:二進制格式比文本解析更快。
  • 減少冗余:通過頭部壓縮進一步優化。

3、什么是Stream(流)?

  • 一個Stream是客戶端和服務器之間的一個獨立的雙向數據流。
  • 每個HTTP請求/響應對應一個或多個Stream。
  • 每個Stream有唯一ID:
    • 客戶端發起的Stream ID是奇數(1, 3, 5…)
    • 服務器發起的(如Server Push)是偶數

舉例:

  • 請求首頁:Stream 1
  • 請求CSS:Stream 3
  • 請求JS:Stream 5
  • 請求圖片:Stream 7

這些Stream的幀可以在同一個TCP連接上混在一起發送:

[DATA, Stream=3]
[HEADERS, Stream=5]
[DATA, Stream=1]
[HEADERS, Stream=7] 
[DATA, Stream=3]

接收方根據Stream ID把屬于同一個流的幀重新組裝成完整請求或響應。

這就是多路復用:多個請求/響應并行在一個連接上傳輸,不互相阻塞!

4、頭部壓縮:減少重復信息的傳輸

HTTP/1.1的頭部冗余:

  • 每次請求都攜帶大量重復頭部(如User-Agent、Cookie),占總傳輸量的50%以上。

HTTP/2的HPACK壓縮:

  • 靜態表:預定義常用頭部字段(如:method: GET、host),用短編碼代替完整字段。
  • 動態表:客戶端和服務器維護一個共享的動態表,記錄最近傳輸的頭部值(如cookie: abc123),后續請求只需引用索引
  • 示例:
    • 首次請求頭部::method: GET, host: example.com, user-agent: Chrome
      • 動態表記錄這些值。
    • 后續請求只需發送索引(如:method: 1, host: 2),大幅減少數據量。

效果:

  • 頭部體積減少50%-90%,提升傳輸效率。

5、服務器推送:主動發送資源

傳統方式的延遲:

  • 瀏覽器加載HTML后,發現需要CSS/JS文件,再發起新請求,增加往返延遲。

HTTP/2的服務器推送:

  • 主動推送:服務器在客戶端請求HTML時,預測客戶端可能需要的資源(如CSS、JS),提前通過PUSH_PROMISE幀推送。
  • 示例:
    • 客戶端請求index.html。
    • 服務器響應HTML內容,并通過PUSH_PROMISE推送style.css和script.js。
    • 客戶端收到后,直接從本地緩存或推送數據中獲取資源,無需額外請求。

效果:

  • 減少請求次數:關鍵資源提前加載,縮短頁面渲染時間。

6、流量控制與優先級:智能分配帶寬

流量控制:

  • 滑動窗口機制:客戶端和服務器通過WINDOW_UPDATE幀動態調整接收窗口大小,防止緩沖區溢出
  • 示例:客戶端通知服務器:“我現在只能接收10KB數據”,服務器按此限制發送。

優先級:

  • 權重分配:每個流(請求)可以設置優先級(1-256),服務器優先處理高權重流。
  • 依賴關系:通過PRIORITY幀 建立流之間的依賴樹,例如優先加載HTML再加載圖片。

4、HTTP/2是如何“維持”這個長連接的?

1、不主動關閉連接(默認持久)

  • 服務器和客戶端都傾向于長期保持這個TCP連接。
  • 不像HTTP/1.1那樣容易超時斷開。(斷開連接時間會比HTTP1.1要長)
  • 瀏覽器對同一個域名通常只建立1~2個HTTP/2連接,然后一直復用。

2、使用PING幀保活

  • 客戶端或服務器可以定時發送PING幀探測連接是否還活著。
  • 對方必須回復一個PONG幀。
  • 這有點像“心跳包”,防止NAT或防火墻誤殺空閑連接。

3、流控制(Flow Control)防止壓垮對方

  • 每個Stream和整個連接都有流控窗口。
  • 接收方可以告訴發送方:“我只能接收這么多數據,別發太快。”
  • 通過WINDOW_UPDATE幀動態調整。
  • 這讓連接更穩定,避免緩沖區溢出。

4、優雅關閉:GOAWAY幀

  • 服務器想關閉連接時,不會直接斷開,而是發一個GOAWAY幀。
  • 告訴客戶端:“我已經處理到Stream ID=X了,別再發新的請求了。”
  • 已經在傳輸的請求可以完成,新請求會建立新連接。
  • 這樣不會中斷用戶正在加載的頁面。

5、實際效果:一個連接干了以前6個連接的事

在這里插入圖片描述

6、什么情況下HTTP/2長連接會斷開?

雖然想“一直連著”,但現實中有這些情況會導致斷開。
在這里插入圖片描述
斷開連接后,如果還需要通信,會重新建立一個新的HTTP/2連接,和之前那個沒有關系(但Cookie、Token等應用層狀態還在)。

7、HTTP1.1和HTTP2對比

在這里插入圖片描述

打個比方:

  • HTTP/1.1的長連接:像一條單車道高速公路,車可以一輛接一輛快速開,但不能超車。
  • HTTP/2的長連接:像一條上百車道的超級高速公路,所有車(請求)可以同時開,各走各的道(Stream),互不干擾。

8、總結

HTTP/2的長連接則通過多路復用 + 二進制幀實現多個并行請求復用一個TCP連接,效率更高。

雖然HTTP/2改進了應用層的并發,但如果底層TCP出現丟包,仍可能導致整個連接阻塞(這是HTTP/3使用QUIC和UDP的原因)。
現代瀏覽器通常對HTTP/1.1使用多個并行連接(如6~8個)來提升并發,而HTTP/2只需一個連接即可達到更高性能。

HTTP2的特性:
在這里插入圖片描述

向陽前行,Dare To Be!!!

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

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

相關文章

圖解希爾排序C語言實現

1 希爾排序 希爾排序(Shell Sort)是D.L.Shell于1959年提出來的一種排序算法,在這之前排序算法的時間復雜度基本都是O(n),希爾排序算法是突破這個時間復雜度的第一批算法之一。 1.1 基本概念與原理 希爾排序通過將原始列表分割成若…

網絡協議——HTTPS協議

目錄 一、HTTPS是什么 加密是什么 二、HTTPS的工作過程 (一)對稱加密 (二)非對稱加密 (三)在非對稱加密的基礎上,引入證書校驗 證書是什么 證書的內容 用證書解決中間人攻擊 三、總結 …

React 基礎實戰:從組件到案例全解析

React 基礎實戰專欄:從組件到案例全解析 本專欄圍繞 React 核心概念(組件、Props、State、生命周期)展開,通過 6個實戰案例+核心知識點拆解,幫你掌握 React 基礎開發邏輯,每篇聚焦1個實戰場景,搭配完整代碼與原理講解,適合 React 入門者鞏固基礎。 專欄目錄 【組件傳…

ARM芯片架構之CoreSight Channel Interface 介紹

CoreSight Channel Interface(通道接口)詳解1. 概述 Channel Interface 是 ARM CoreSight 架構中用于在不同組件之間傳遞觸發事件的專用接口。它是 Event Interface 的增強版本,支持多通道、雙向通信,以及同步與異步兩種時鐘域連接…

Blender模擬結構光3D Scanner(二)投影儀內參數匹配

關于投影儀外參的設置可參見前一篇文章 Blender模擬結構光3D Scanner(一)外參數匹配-CSDN博客 使用Projectors插件模擬投影儀 Step 1 在Github下載插件(https://github.com/Ocupe/Projectors)。下載zip壓縮包即可,無…

synchronized的作用

目錄 一、核心作用 二、實現原理:基于"對象鎖" 三、使用方式 四、鎖的優化 五、優缺點 六、總結 synchronized 是 Java 中用于解決多線程并發安全問題的核心關鍵字,它的主要作用是實現線程間的同步,確保多個線程在訪問共享資…

機試備考筆記 14/31

2025年8月14日 小結:(17號整理14號的筆記,這輩子真是有了w(゚Д゚)w)昨天摔了跤大的,今天好媽媽在家,松弛。省流:6道中等,明天只學了10分鐘嘻嘻 目錄LeetCode22…

dolphinscheduler中任務輸出變量的問題出現ArrayIndexOutOfBoundsException

一段腳本任務如下:ret/data/dolphinscheduler/loadOraTable.sh "yonbip/yonbip10.16.10.69:1521/orcl" "select t.bondcontractno,t.olcunissuemny from yonbip.bond_contract t " "/dmp/biz" "bip" "2025-08-13"…

OpenCv(二)——邊界填充、閾值處理

目錄 一、邊界填充(Border Padding) 1. 常見填充類型及效果 2.代碼示例 (1)constant邊界填充,填充指定寬度的像素 (2)REFLECT鏡像邊界填充 (3)REFLECT_101鏡像邊界…

Leetcode 15 java

今天復習一下翻轉二叉樹 226. 翻轉二叉樹 給你一棵二叉樹的根節點 root ,翻轉這棵二叉樹,并返回其根節點。 示例 1: 輸入:root [4,2,7,1,3,6,9] 輸出:[4,7,2,9,6,3,1]示例 2: 輸入:root [2…

嵌入式學習的第四十九天-時鐘+EPIT+GPT定時器

一、時鐘1.時鐘系統基本概念(1)PLL (鎖相環, Phase-Locked Loop)作用:PLL是一種反饋控制電路,用于生成穩定的高頻時鐘信號。它通過將輸出時鐘與參考時鐘進行比較和調整,可以產生比輸入參考時鐘頻率高得多的輸出時鐘。倍…

Python Sqlalchemy數據庫連接

Python Sqlalchemy數據庫連接一、連接數據二、模型三、ORM操作一、連接數據 from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker# 1. 連接數據庫 dbHost postgres://用戶名:密碼主機:端口/數據庫名 engine create_engine(dbHost) # create_engi…

【Node.js】ECMAScript標準 以及 npm安裝

目錄 一、 ECMAScript標準 - 默認導出和導入 二、ECMAScript標準 - 命名導出和導入 三、包的概念 五、 npm - 安裝所有依賴 六、 npm - 全局軟件包 Node.js總結 總結不易~ 本章節對我有很大的收獲, 希望對你也是!!! 本節素材…

NPM 、 NPX

NPM vs. NPX 簡單來說,npm 是一個 node 包管理器,npx 是一個 Node 包執行器。 NPX 是一個 Node 包執行器,該 Node 包可以是本地也可以是遠程的。允許開發者在無需安裝的情況下執行任意 Node 包。npm 在安裝nodejs 就自動帶了 npm install -g …

守護品質安全,防偽溯源系統打造全鏈路信任體系

一、引言在當下這個信息透明、品質至上的時代,防偽溯源已經成為眾多品牌保護自身利益、提升消費者信任度的重要手段。為了滿足市場上對高效、可靠的防偽溯源查詢系統的迫切需求,榕壹云精心打造了一款防偽溯源查詢系統。二、項目背景隨著商品市場的不斷擴…

【完整源碼+數據集+部署教程】無人機航拍視角洪水檢測與受災房屋識別圖像分割救援指導系統源碼和數據集:改進yolo11-DCNV2

背景意義 研究背景與意義 隨著全球氣候變化的加劇,極端天氣事件的頻率和強度不斷上升,洪水作為一種常見的自然災害,給人類社會帶來了嚴重的威脅。洪水不僅導致人員傷亡和財產損失,還對基礎設施和生態環境造成了深遠的影響。因此&a…

C# 結構體與類的區別是什么?

結構體是值類型是儲存在棧中獨立儲存的,數據與數據之間不會相互影響,即使將一個結構體賦值給另外一個結構體也不會相互影響。 類是一個模板,實例出來的對象是獨立的不會相互影響,但是將一個對象賦值給另一個對象時 會把指向堆內存中數據的指針賦值給另一個對象.從而發生兩個變量…

Redis GEO

Redis GEO 引言 Redis 是一款高性能的鍵值存儲系統,廣泛應用于緩存、消息隊列等領域。Redis GEO 是 Redis 2.4 版本后新增的一個功能,用于存儲地理位置信息。本文將詳細介紹 Redis GEO 的概念、使用方法以及應用場景。 什么是 Redis GEO? Redis GEO 是 Redis 的一個模塊…

Go從入門到精通系列學習路線規劃

Go從入門到精通系列學習路線規劃 目錄導航 Go從入門到精通系列學習路線規劃首頁說明 第1篇_Go語言初探_環境搭建與HelloWorld 第2篇_Go語言基礎語法_變量常量與數據類型 第3篇_Go語言控制結構_條件判斷與循環 第4篇_Go語言函數詳解 第5篇_Go語言數據結構詳解 第6篇_Go語言結構體…

Grid系統概述

目錄 概念及功能 網格對象(Grid Object) 和世界對象(World Object) 工作流程 概念及功能 TrinityCore 的 Grid 系統是一套復雜的地圖分區管理機制,其核心目標是通過動態管控游戲世界的區域狀態和對象生命周期&#…