Thanks for your reply. My point is really about the enqueuing of new requests. I imagine that callbacks from the CompletionQueue will come slower, if the server is laggy. I'm interested in what happens before.
So what exactly happens if the client loops like a crazy and enqueue millions of requests ? There are 3 possible outcomes: 1) at some point, the enqueuing fails because an internal buffer saturates. 2) the process dies with an out of memory (well, same as the previous case, in a sense, but more difficult to recover). 3) PrepareAsyncSayHello (or StartCall) blocks the caller until some resource becomes available. Choose your poison. What happens ? What is the design pattern to implement backpressure on the client with the c++ interface ? Shall I control manually how much flying request I have ? In golang, for instance, I presume the client goroutine is suspended if the outgoing tcp stream is full (so this implements the 3rd outcome and is the perfect semantic) On Monday, March 16, 2020 at 6:43:21 PM UTC+1, Vijay Pai wrote: > > There is a queue, but it is not hidden. Notice that the last argument in > the actual start of the RPC is a CompletionQueue. Starting an operation > records some state about it in the CQ, in addition to actually creating a > set of operations that are activated in the gRPC C++ library. Operations > will take longer to actually complete if they're under pressure and that > will be seen when your CompletionQueue::Next calls (not shown in your code > snippet, but which is in the AsyncCompleteRPC function executed on a > different thread) dribble out one tag at a time. That's the API function > that blocks the application based on actual progress. > > The channel connectivity state functions refer entirely to the > connectivity state diagram at > https://github.com/grpc/grpc/blob/master/doc/connectivity-semantics-and-api.md > . > Failure states there mean true connectivity failures ("Sorry, sister, > there's been a real problem."), not just backpressure. > > Regards, > Vijay > > > On Mon, Mar 9, 2020 at 3:25 AM Frédéric De Jaeger <[email protected] > <javascript:>> wrote: > >> Hi >> >> Sorry for the noob question, I've just started grpc. I'm a bit puzzled >> on how the backpressure can be done on the client side. >> >> For instance, consider the canonical example `greeter_async_client2.cc`: >> >> for (int i = 0; i < 100; i++) { >> std::string user("world " + std::to_string(i)); >> greeter.SayHello(user); // The actual RPC call! >> } >> >> >> >> This enqueues 100 requests to be sent (and everything is processed >> asynchronously, fine). >> >> Suppose the server/network is slow and the client wants to enqueue faster >> than what the server can process, what will happen ? >> >> My understanding of the sample code is that none of the API in `SayHello` >> blocks the caller: >> >> // stub_->PrepareAsyncSayHello() creates an RPC object, returning >> // an instance to store in "call" but does not actually start the >> RPC >> // Because we are using the asynchronous API, we need to hold on to >> // the "call" instance in order to get updates on the ongoing RPC. >> call->response_reader = >> stub_->PrepareAsyncSayHello(&call->context, request, &cq_); >> >> // StartCall initiates the RPC call >> call->response_reader->StartCall(); >> >> // Request that, upon completion of the RPC, "reply" be updated >> with the >> // server's response; "status" with the indication of whether the >> operation >> // was successful. Tag the request with the memory address of the >> call object. >> call->response_reader->Finish(&call->reply, &call->status, (void >> *)call); >> >> >> >> Request will then accumulate somewhere in a hidden queue (bad), or some >> request will be dropped (also bad), or one of these API actually blocks >> (still bad, for an async API). Maybe some request fails with a specific >> error ? (grpc::StatusCode::UNAVAILABLE ?) >> >> I suppose there is a way to notify the client that he should not enqueue >> new requests (or that he can now start pushing new requests). >> `ChannelInterface::NotifyOnStateChange` looks a good candidate, except that >> I could not find a value from `grpc_connectivity_state` that would >> represent "*stop pushing new requests, bro, I'm busy*". Could it be >> classified as GRPC_CHANNEL_TRANSIENT_FAILURE ? >> >> Thanks for your help >> >> >> -- >> You received this message because you are subscribed to the Google Groups >> "grpc.io" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to [email protected] <javascript:>. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/grpc-io/09f26845-a393-4a30-9d6a-2bf8d9e07e03%40googlegroups.com >> >> <https://groups.google.com/d/msgid/grpc-io/09f26845-a393-4a30-9d6a-2bf8d9e07e03%40googlegroups.com?utm_medium=email&utm_source=footer> >> . >> > -- You received this message because you are subscribed to the Google Groups "grpc.io" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/grpc-io/ae441f4d-9fb7-438a-a669-68d1393aeda0%40googlegroups.com.
