簡體   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