baidu / sofa-pbrpc

A light-weight RPC implement of google protobuf RPC framework.
Other
2.13k stars 655 forks source link

关于RpcServerOptions中max_pending_buffer_size的疑问 #207

Closed scottzzq closed 6 years ago

scottzzq commented 6 years ago

RpcServerOptions中max_pending_buffer_size是应用层缓冲区大小吗?如果需要给Client回复的数据包大于设定的这个值会有什么影响? 谢谢!

qinzuoyan commented 6 years ago

max_pending_buffer_size的定义

int max_pending_buffer_size; // max buffer size of the pending send queue for one connection.
                             // in MB, should >= 0, 0 means no buffer, default 100.

首先从为什么需要这个参数说起:server端收到client端发过来的request后,会调用合适的Service来处理,处理得到的结果需要发回给client端。由于发送的网络通道不一定空闲,所以会先将Message放到一个缓冲的buffer_queue里面。负责发送数据的网络会一批一批地从buffer_queue里面获取需要发送的数据。就可能出现发送的速度赶不上Message产生的速度,这样Message就会在buffer_queue里面不断累积,如果累积太多就产生好几个坏处:1. 内存暴涨;2. 排队时间较长,client端不能及时收到结果超时。所以提供了一个参数用于控制buffer_queue的上限,这就是max_pending_buffer_size,单位是MB。 如果buffer_queue达到了上限会怎样呢?它不是直接拒绝放入buffer_queue,而是从源头着手,暂停接收请求数据(参见RpcServerMessageStream::try_start_receive()函数)。只要不接收请求了,就不会产生新的回复的Message了,这样间接控制buffer_queue的大小。而之前已经接收的请求,该怎么处理还怎么处理,产生的Message还是能放入buffer_queue里面,最终被发送出去。等到buffer_queue低于上限后,会重新开始接收请求。

所以你的问题:如果需要给Client回复的数据包大于设定的这个值会有什么影响?影响就是,buffer_queue里面最多可以缓冲一条数据,在这条数据发送出去之前,暂时不会接收新的请求。但是并不会将这条数据丢弃,只要产生了,就会正常发送。

你什么时候需要调整这个参数?

  1. 程序内存使用太大。如果连接数很多,buffer_queue又用满的情况下,每条连接数都使用了100MB,那么总内存就会很多。你可以减小这个参数,少使用一些内存。不过由于buffer_queue不是预分配的,所以在QPS不大,buffer_queue较空的情况下,也不会占用很多内存。
  2. QPS很大,buffer_queue长期比较满,发送的Message排队时间很大,造成延迟较大。在你确定是因为在buffer_queue中排队很久的情况下,你可以尝试减小这个参数,看看能不能改善延迟。

RpcClientOptions里面也有一个同样的参数,稍有区别的是,如果buffer_queue达到上限,不是暂停接收请求(因为是client端),而是拒绝用户发起新的请求。此时用户如果发起RPC请求的话,会返回RPC_ERROR_SEND_BUFFER_FULL的错误。

希望我的回答足够清楚了。

scottzzq commented 6 years ago

感谢 @qinzuoyan 细致的解答,终于搞清楚这个参数的含义了。

qinzuoyan commented 6 years ago

@scottzzq 不客气,刚刚上面回复有一些更新,你刷新看看。