Grpc-07-滑动窗口

回顾一下 tcp 的滑动窗口

那么这一章需要解决的问题是:

  1. tcp 有了滑动窗口为什么 grpc-go又需要滑动窗口,它们两者有什么区分,为什么两者都需要用到滑动窗口
  2. grpc-go 的滑动窗口原理是什么
  3. grpc-go 的滑动窗口是如何实现的

滑动窗口的目的是,计算出下次发送数据帧的最大字节数

  • 客户端的帧发送器在发送数据帧时存在一些发送指标,服务器端在接收数据帧的不同阶段,也存在一些指标

    • 发送指标是如何定义的 TODO?
  • 服务器在接收数据帧时,会根据自己的接收数据帧、存储数据帧、读取数据帧的速度,向客户端发送窗口更新帧或者设置帧;

    • 计算原理是什么 ? 窗口更新帧与设置帧的区别? TODO
  • 客户端接收到服务器端发送过来的设置帧或者窗口更新帧后,会更新本地的发送指标

  • 发送指标的更新,会影响到客户端下次发送数据帧的最大字节数

  • 最大字节数的计算,服务器端会通过发送窗口更新帧或者设置帧来动态的影响客户端计算数据帧大小的参数,从而影响下次发送的最大字节数

每个链接、每个流、每个客户端的指标都是如何定义的? TODO

滑动窗口原理

gRPC-go滑动窗口整体处理流程

客户端

  • 构建好数据帧dataFrame
  • 通过发送参数指标,计算本次发送的最大字节数maxSize
  • 数据帧截取器,从数据帧里截取指定的字节数maxSize,交由帧发送器
  • 帧发送器将截取的字节,转换成http2原生的帧,发送给服务器端

服务端

  • 帧接收器接收到数据帧,交由帧分发器处理
  • 帧分发器根据帧的类型,交由数据处理器handleData处理,数据处理器handleData:
    • 抽样级别流控:对本地的接收参数进行更新(如b.sampelCount,b.sample,b.bwMax,b.bdp),触发阈值条件后,会向客户端发送窗口更新帧outgoingWindowUpdate,其中设置streamID=0,或者发送设置帧outgoingSettings
    • 链接级别流控:对本地的接收参数进行更新(如f.unacked,f.limit),触发阈值条件后,会向客户端发送窗口更新帧outgoingWindowUpdate,其中设置streamID=0
    • 流级别流控:对本地的接收参数进行更新(如f.pendingData,f.pendingUpdate,f.limit,f.delta),触发阈值条件后,会向客户端发送窗口更新帧outgoingWindowUpdate,其中设置streamID=0
    • 将数据帧存储到go语言原生自带的缓存bytes.Buffer里
    • 构建recvMsg结构体,将bytes.Buffer存储到recvMsg里;(recvMsg就是对bytes.Buffer封装)
    • 将recvMsg存储到recvBuffer里:存储逻辑是
      • i.若recvMsg类型的通道里,没有数据的话,就直接将recvMsg存储到该通道里
      • ii.若recvMsg类型的通道里,已经有数据了的话,就将recvMsg添加到类型为recvMsg的切片的尾部
  • 接收数据并解压recvAndDecompress:
    • a)读取数据前,先对本地的窗口参数进行调整,如f.delta;满足触发阈值条件的话,就向客户端发送窗口更新帧outgoingWindowUpdate,其中streamID非0;
    • b)recvBufer读取器:
      i.从recvBuffer的通道里获取数据recvMsg
      ii.数据获取到后,recvBuffer缓存中,将切片的第一个数据,加载到通道里;(因为通道里刚才已经消费了数据,需要重新添加上)
      iii.从recvMsg里获取到bytes.Buffer对象
      iv.将bytes.Buffer里的数据读取到字节切片里
      c)读取完成数据后,更新流级别参数,如f.pendingData,f.pendingUpdate若满足触发阈值条件的话,就向客户端发送窗口更新帧outgoingWindowUpdate,其中streamID非0;
      d)对切片里的数据进行解压,对解压后的数据,交由handle方法
      e)handle方法:就是grpc服务器内部,真正执行客户端请求的方法入口
      i.对解压后的数据,进行反序列化,得到请求方法的具体参数值
      ii.真正的执行客户端的请求方法,得到执行结果
      f)将执行结果封装到数据帧里,存储到controlBuf缓存里
      g)帧发送器,从帧缓存里获取到数据帧,发送给客户端

参考文档

  1. https://blog.csdn.net/u011582922/article/details/118887625