gRPC源碼/transport/流控

流控

代碼

https://github.com/messixukej...
在liangzhiyang/annotate-grpc-go基礎上補充了部分註釋git

發送流控

HTTP/2 流量控制的目標,在流量窗口初始值的約束下,給予接收端以全權,控制當下想要接受的流量大小。github

  • 算法:算法

    • 兩端(收發)保有一個流量控制窗口(window)初始值。
    • 發送端每發送一個DATA幀,就把window遞減,遞減量爲這個幀的大小,要是window小於幀大小,那麼這個幀就必須被拆分。若是window等於0,就不能發送任何幀。
    • 接收端能夠發送 WINDOW_UPDATE幀給發送端,發送端以幀內指定的Window Size Increment做爲增量,加到window上。
// 用於發送流控。 將當前可用的quota(字節數)寫入c,有數據發送須要時,從c中獲取。acquire到的大小即爲可支持的最大發送量。
// acquire 將quota所有獲取出來,根據實際使用量,將未使用的從新add回pool。
type quotaPool struct{
    c chan int
    mu    sync.Mutex
    quota int
}

http2Client.Write消耗quota,client跟stream有各自的控制。
handleWindowUpdate補充quota。

接收流控

//用於接收流控。onData經過判斷pendingData、pendingUpdate之和是否超過limit來進行流控。
type inFlow struct{
    /// The inbound flow control limit for pending data./    
    limit uint32

    mu sync.Mutex
    // pendingData is the overall data which have been received but not been consumed by applications.
    //接收可是未被應用消費的數據,對應onData。
    pendingData uint32

    // The amount of data the application has consumed but grpc has not sent window update for them. Used to reduce window update frequency.
    //對應onRead 
    pendingUpdate uint32
}

pendingData:handleData->onData增長pendingData->s.write(可供io.ReadFull讀取)

pendingUpdate:io.ReadFull(s1, p)->Stream.Read讀取數據->windowHandler->updateWindow->onRead減小pendingData,按照1/4limit量還清空pendingUpdate->windowUpdate->framer.writeWindowUpdate更新發送端窗口大小->發送端處理handleWindowUpdate(id=0更新client,非0更新對應stream)
->進而增長髮送端quota
相關文章
相關標籤/搜索