繁体   English   中英

如何在 gRPC 中做服务端背压?

[英]How to do server-side backpressure in gRPC?

我只是发现在C++中,在使用AsyncService的时候,即使我没有请求新的请求,gRPC还是会从网络中读取数据。 这导致我的系统中大量使用 memory。

详细场景:

我有一个客户端会向服务器发送大量请求。

在服务器端,我没有请求任何请求。 服务器在cq_->Next(&tag, &ok)中阻塞,但一直在消耗 memory。 导致我的系统出现 OOM。

所以我的问题是,当我不请求新请求时,如何防止服务器从网络读取数据? 即如何做服务器端背压,所以我可以保存 memory??

有人可以帮我吗? 谢谢!

编辑:复制

我做了一个简单的例子给大家复现这个问题,代码基于gRPC官方代码库的v1.46.3标签。 我只是修改了示例,使服务器不请求任何请求,并使客户端发送更多请求。 检查此提交以了解我修改的内容。

  1. git clone -b v1.46.3_reproduce_oom --depth 1 https://github.com/lixin-wei/grpc.git && cd grpc
  2. git submodule update --init
  3. bazel build //examples/cpp/helloworld:all
  4. 在一个 session 中,启动服务器:./bazel-bin/examples/cpp/helloworld/ ./bazel-bin/examples/cpp/helloworld/greeter_async_server
  5. 在另一个 session 中,启动客户端:./bazel-bin/examples/cpp/helloworld/ ./bazel-bin/examples/cpp/helloworld/greeter_async_client2
  6. 继续运行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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM