日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

如何定位并修复 HttpCore5 中的 HTTP2 流量控制问题

發布時間:2025/3/20 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何定位并修复 HttpCore5 中的 HTTP2 流量控制问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作者:風起

開篇吹一波阿里云性能測試服務?PTS [1] ,PTS 在 2021 年 5 月份已經上線了對 HTTP2 協議的支持(底層依賴 httpclient5),在壓測時會通過與服務端協商的結果來決定使用 HTTP1.1 或者 HTTP2 協議。

背景

寫這篇文章的原因是某天某個客戶找過來,問我們是不是不支持 HTTP2,因為他在 XX 云上購買了 2 個域名,其中一個開啟了 HTTP2,而在 PTS 壓測過程中,支持 HTTP2 的接口總是報錯:

起初懷疑是 HTTP2 支持的問題,通過在本地強制使用 HTTP2 協議,訪問淘寶主頁,發現是沒問題的,懷疑是用戶在 XX 云上的配置問題,但緊接著通過在本地 Postman、curl 以及壓測引擎強制使用 HTTP1.1 協議時都能夠正常訪問該網頁,意識到大概率是 PTS 引擎側的問題。

通過本地 debug,看到是因為請求 URL 時,客戶端窗口大小被調整為大于 2^32 -1 導致的異常。

那正好借這個機會看下這里的窗口大小指的是什么。

HTTP2 流控

提到窗口,就要提到 HTTP2 相比于 HTTP1.1 支持的新特性:流控(Flow Control),其實 HTTP1.1 依賴于傳輸層 TCP 的滑動窗口一樣可以實現流控,那么為什么 HTTP2 要在應用層再實現一個流控呢?原因在于 HTTP2 引入了流和多路復用,通過流控可以達到使多個流協同的效果。

一些流控的基本概念:

  • 流控是針對連接而言的,不是針對端到端的,而是在兩端中的每一跳;主要指有代理的情況下,代理與兩端都存在流控
  • 流控是基于WINDOW_UPDATE 幀的,接收者可以通過流控控制發送者的速度
  • 流控既可以作用于 stream 也可以作用于 connection
  • 對于連接與所有新開啟的流而言,流控窗口大小默認都是 65535,且最大值為 2^32 - 1
  • 流控無法禁用
  • 為了便于理解,先簡單列一下 HTTP2 幀的類型:

    • DATA:攜帶請求或響應中的數據
    • HEADERS:用于新建一個流(請求或響應),包含對應的 Headers
    • PRIORITY:用于配置流的優先級
    • RST_STREAM:強制結束某個流,僅用于某一端取消流,并不適用于正常流的結束
    • SETTINGS:H2 建聯的一些配置
    • PUSH_PROMISE:服務端推送響應到客戶端
    • PING:向遠端發送一條 PING,遠端必須返回該 PING
    • GOAWAY:用于某一端將要結束連接
    • WINDOW_UPDATE:更新流控窗口大小
    • CONTINUATION:如果 headers 過大,單個 HEADERS 幀難以攜帶,通過該幀發送額外的 headers

    接下來,我們重點看下流控相關的幀,主要是 SETTING 與 WINDOW_UPDATE,在連接建立時會通過 SETTINGS 幀來調整對方的窗口大小,之后在傳輸過程中,窗口大小會隨著數據的發送逐漸減小,直到收到對方發送的 WINDOW_UPDATE 幀,從而更新窗口大小。SETTINGS 幀主要包含以下內容:

    • SETTINGS_HEADER_TABLE_SIZE:HPACK(一種header壓縮算法) header 表的最大長度,默認值 4096
    • SETTINGS_ENABLE_PUSH:客戶端發向服務端的配置,若設置為 true,客戶端將允許服務端推送響應,默認值 true
    • SETTINGS_MAX_CONCURRENT_STREAMS:同時打開的 stream 最大數量,通常意味著同一時刻能夠同時響應的請求數量,默認無限
    • SETTINGS_INITIAL_WINDOW_SIZE:流控的初始窗口大小,默認值 65535
    • SETTINGS_MAX_FRAME_SIZE:對端能夠接受幀的最大長度,默認值16384
    • SETTINGS_MAX_HEADER_LIST_SIZE:對端能夠接受的 header 列表最大長度,默認不限制

    流控的實現如上所述,每發送一批 DATA 幀,即將窗口大小減小。需要注意的是流控僅針對 DATA 幀。

    前面提到流控既可以作用于 stream 又可以作用于 connection,那具體是怎么執行的呢?connection 的流控與 上述 stream 流控邏輯類似,每次發送 DATA 幀,connection 與 stream 窗口都會減小,但不同的是,WINDOW_UPDATE 要么單獨作用于 stream,要么單獨作用于 connection(streamid 為 0 時,表示作用于 connection)。

    問題定位

    那么回到開篇的問題,我們以 URL ?https://www.sysgeek.cn/??為例,通過在本地做代碼 debug 發現,最終拋異常的原因在于接收到 WINDOW_UPDATE 幀后,更新后窗口大小值大于 2^32 - 1 導致拋異常:

    而從這里的代碼可以看出,524288 是當前窗口大小,而delta是對方告知的 WINDOW_UPDATE 大小,通過分析,發現 524288 這個值不同于默認值 65535,那繼續看這個值是什么時間改動的:

    發現是接收 SETTINGS 指令后,初始化窗口大小時修改的,但這里與?RFC 7540 [2] 的描述(connection 窗口大小僅在接收到 WINDOW_UPDATE 后才可能修改)是沖突的:

    因此我們斷定是 httpcore5 的源代碼有 bug,在刪除標記的這行代碼后,請求可以正常執行了。

    遺憾的是在準備給 httpcore5 提 PR 的過程中發現這個 bug 已經在 commit 中被修復了。

    參考資料

    [1] PTS:

    https://help.aliyun.com/document_detail/145501.html

    [2] RFC 7540:

    https://datatracker.ietf.org/doc/html/rfc7540#section-6.9.2

    ? ??https://datatracker.ietf.org/doc/html/rfc7540#section-5.2??

    ? ??https://undertow.io/blog/2015/04/27/An-in-depth-overview-of-HTTP2.html??

    ? ??https://laike9m.com/blog/rfc7540-bi-ji-wu-flow-control,106/??

    點擊??此處??,前往 PTS 官網查看更多~

    總結

    以上是生活随笔為你收集整理的如何定位并修复 HttpCore5 中的 HTTP2 流量控制问题的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。