[英]How to do server-side backpressure in gRPC?
我只是发现在C++中,在使用AsyncService的时候,即使我没有请求新的请求,gRPC还是会从网络中读取数据。 这导致我的系统中大量使用 memory。
详细场景:
我有一个客户端会向服务器发送大量请求。
在服务器端,我没有请求任何请求。 服务器在cq_->Next(&tag, &ok)
中阻塞,但一直在消耗 memory。 导致我的系统出现 OOM。
所以我的问题是,当我不请求新请求时,如何防止服务器从网络读取数据? 即如何做服务器端背压,所以我可以保存 memory??
有人可以帮我吗? 谢谢!
我做了一个简单的例子给大家复现这个问题,代码基于gRPC官方代码库的v1.46.3
标签。 我只是修改了示例,使服务器不请求任何请求,并使客户端发送更多请求。 检查此提交以了解我修改的内容。
git clone -b v1.46.3_reproduce_oom --depth 1 https://github.com/lixin-wei/grpc.git && cd grpc
git submodule update --init
bazel build //examples/cpp/helloworld:all
./bazel-bin/examples/cpp/helloworld/greeter_async_server
./bazel-bin/examples/cpp/helloworld/greeter_async_client2
ps -aux | grep greeter_async_server
ps -aux | grep greeter_async_server
,您会注意到服务器中 memory 的使用量在增加。 服务器代码是examples/cpp/helloworld/greeter_async_server.cc
,客户端代码是examples/cpp/helloworld/greeter_async_client.cc
。
一种选择是使用ResourceQuota
来限制整个服务器的缓冲区 memory 使用。 您指定的大小不是绝对的系统 memory 限制,因为并非 gRPC 核心/C++ 中的所有 memory 都被跟踪,但它会导致 ZCD69B4957F06CD818D7ZBF3D61980E291 的总使用量上限。
在服务器中,您可以添加:
// Set a maximum memory cap
grpc::ResourceQuota quota("greeter_callback_server");
quota.Resize(30*1024*1024); // 30MB
builder.SetResourceQuota(quota);
在达到 memory 上限后,将错误代码添加到客户端 output,客户端将看到类似
RPC failed with: Received RST_STREAM with error code 11
在我的系统上,当服务器进程达到 ~140MB RES memory 时会发生这种情况。
编辑:另一个选项是使用GRPC_ARG_MAX_CONCURRENT_STREAMS
通道参数设置服务器愿意接受的最大并发流数。 每个一元调用都是一个单独的 RPC,并作为单独的 stream 处理。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.