[英]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.