为了账号安全,请及时绑定邮箱和手机立即绑定

go 中 gRPC 客户端流控制如何工作?

go 中 gRPC 客户端流控制如何工作?

Go
狐的传说 2023-07-10 15:08:12
我想知道 Go 中的客户端流 gRPC 服务中的流量控制是如何工作的。stream.SendMsg()具体来说,我有兴趣知道何时会调用客户端块中的函数?根据文档:SendMsg() 会阻塞,直到:有足够的流量控制来调度 m 的传输,或者......那么流的流控机制规范是怎样的呢?例如,如果负责从流中读取消息的服务器端代码读取消息的速度不够快,那么什么时候会调用 SendMsg() 块?服务器是否实现了某种反压机制来告诉客户端它还没有准备好接收更多数据?与此同时,在反压信号之前已经成功发送的所有消息都在哪里排队呢?
查看完整描述

2 回答

?
千万里不及你

TA贡献1784条经验 获得超9个赞

仅当有足够的流控制窗口时消息才会成功发送,否则 SendMsg() 将阻塞。

接收端发出的信号不是增加反压,而是释放反压。这就像说“现在我准备好接收另外 1MB 的消息,发送它们”。


查看完整回答
反对 回复 2023-07-10
?
慕的地6264312

TA贡献1817条经验 获得超6个赞

这是流量控制的另一种解释

HTTP/2 流量控制是一项防止应用程序被数据淹没的功能。使用流量控制时:

  • 每个 HTTP/2 连接和请求都有一个可用的缓冲区窗口。缓冲窗口是应用程序一次可以接收多少数据。

  • 如果缓冲区窗口已满,则流控制将激活。激活后,发送应用程序将暂停发送更多数据。

  • 一旦接收应用程序处理完数据,缓冲区窗口中的空间就可用。发送应用程序恢复发送数据。

接收大消息时,流量控制可能会对性能产生负面影响。如果缓冲区窗口小于传入消息有效负载,或者客户端和服务器之间存在延迟,则可以以开始/停止突发的方式发送数据。

流量控制性能问题可以通过增加缓冲区窗口大小来解决。

  • WithInitialWindowSize客户端:通过拨号选项WithInitialConnWindowSize设置窗口

// WithInitialWindowSize returns a DialOption which sets the value for initial

// window size on a stream. The lower bound for window size is 64K and any value

// smaller than that will be ignored.

func WithInitialWindowSize(s int32) DialOption {

    return newFuncDialOption(func(o *dialOptions) {

        o.copts.InitialWindowSize = s

    })

}


// WithInitialConnWindowSize returns a DialOption which sets the value for

// initial window size on a connection. The lower bound for window size is 64K

// and any value smaller than that will be ignored.

func WithInitialConnWindowSize(s int32) DialOption {

    return newFuncDialOption(func(o *dialOptions) {

        o.copts.InitialConnWindowSize = s

    })

}

InitialWindowSize服务器端:通过服务器选项InitialConnWindowSize设置窗口


// InitialWindowSize returns a ServerOption that sets window size for stream.

// The lower bound for window size is 64K and any value smaller than that will be ignored.

func InitialWindowSize(s int32) ServerOption {

    return newFuncServerOption(func(o *serverOptions) {

        o.initialWindowSize = s

    })

}


// InitialConnWindowSize returns a ServerOption that sets window size for a connection.

// The lower bound for window size is 64K and any value smaller than that will be ignored.

func InitialConnWindowSize(s int32) ServerOption {

    return newFuncServerOption(func(o *serverOptions) {

        o.initialConnWindowSize = s

    })

}

建议

  • 如果 gRPC 服务经常接收大于 96 KB(Kestrel 的默认流窗口大小)的消息,则考虑增加连接和流窗口大小。

  • 连接窗口大小应始终等于或大于流窗口大小。流是连接的一部分,发送者受到两者的限制。


查看完整回答
反对 回复 2023-07-10
  • 2 回答
  • 0 关注
  • 96 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信