[ ![avatar](/assets/img/avatar.png) ](/)

[ Miigon's blog ](/)

My ideas, thoughts and experiences

  * [ __ HOME  ](/)
  * [ __ CATEGORIES  ](/categories/)
  * [ __ TAGS  ](/tags/)
  * [ __ ARCHIVES  ](/archives/)
  * [ __ ABOUT  ](/about/)

__ [ __ ](https://github.com/Miigon) [ __ ](https://twitter.com/) [ __
](javascript:location.href = 'mailto:' +
\['miigon.pg','gmail.com'\].join\('@'\)) [ __ ](/feed.xml)

[ Home ](/) [StackOverflow] Difference between synchronous and asynchorous
gRPC API  __

Post

__ __ Cancel

#  [StackOverflow] Difference between synchronous and asynchorous gRPC API

Posted _Aug 20, 2021_ Updated _Sep 7, 2021_

By _[ Miigon ](https://github.com/Miigon) _

_8 min_ read

> * * *
>
> This is from [ one of my answers on StackOverflow
> ](https://stackoverflow.com/a/68771426/7509248) .
>
> ##  Original question:  __
>
> I am working on a service based on gRPC, which requires high throughput. But
> currently my program suffers low throughput when using C++ synchronous gRPC.
>
> I’ve read through gRPC documentations, but don’t find explicit explanation
> on the difference between sync/async APIs. Except async has control over
> completion queue, while it’s transparent to sync APIs.
>
> I want to know whether synchronous gRPC sends messages to TCP layer, and
> wait for its “ack”, thus the next message would be blocked? Meanwhile async
> APIs would send them asynchronously without latter messages waiting?

**TLDR: Yes, async APIs would send the messages asynchronously without latter
messages waiting, while synchronous APIs will block the whole thread while one
message is being sent/received.**

gRPC uses [ CompletionQueue
](https://grpc.github.io/grpc/cpp/classgrpc_1_1_completion_queue.html) for
it’s asynchronous operations. You can find the official tutorial here:
https://grpc.io/docs/languages/cpp/async/

CompletionQueue is an event queue. “event” here can be the completion of a
request data reception or the expiry of an alarm(timer), etc. (basically, the
completion of any asynchronous operation.)

Using [ the official gRPC asynchronous APIs example
](https://github.com/grpc/grpc/blob/v1.38.0/examples/cpp/helloworld/greeter_async_server.cc)
as example, focus on the ` CallData ` class and ` HandleRpcs() ` :

__ __

`

    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    

|

    
    
      void HandleRpcs() {
        // Spawn a new CallData instance to serve new clients.
        new CallData(&service_, cq_.get());
        void* tag;  // uniquely identifies a request.
        bool ok;
        while (true) {
          // Block waiting to read the next event from the completion queue. The
          // event is uniquely identified by its tag, which in this case is the
          // memory address of a CallData instance.
          // The return value of Next should always be checked. This return value
          // tells us whether there is any kind of event or cq_ is shutting down.
          GPR_ASSERT(cq_->Next(&tag, &ok));
          GPR_ASSERT(ok);
          static_cast<CallData*>(tag)->Proceed();
        }
      }
      
  
---|---  
`

HandleRpcs() is the main loop of the server. It’s an infinite loop which
continuously gets the next event from the completion queue by using `
cq->Next() ` , and calls it’s ` Proceed() ` method (our custom method to
process client request of different states).

The ` CallData ` class (instance of which represents a complete processing
cycle of a client request):

__ __

`

    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64