gRPC源码/transport/流控

蓝白狂想 · · 2035 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

流控

代码

https://github.com/messixukej...
在liangzhiyang/annotate-grpc-go基础上补充了部分注释

发送流控

HTTP/2 流量控制的目标,在流量窗口初始值的约束下,给予接收端以全权,控制当下想要接受的流量大小。

  • 算法:

    • 两端(收发)保有一个流量控制窗口(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

有疑问加站长微信联系(非本文作者)

本文来自:Segmentfault

感谢作者:蓝白狂想

查看原文:gRPC源码/transport/流控

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2035 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传