Search code examples
grpcgrpc-javabidirectional

Number of streams created in a bidirectional streaming using grpc-java


I'm trying to understand how many streams are created in a single grpc connection whenever I send a request using StreamObserver object in a bidirectional streaming using grpc-java Below is my code context

StreamObserver<Response> responseStreamObserver1 = getResponseObserver();
StreamObserver<Response> responseStreamObserver2 = getResponseObserver();
StreamObserver<Request> streamClientSender1 = stub.sendRequest(responseStreamObserver1);
StreamObserver<Request> streamClientSender2 = stub.sendRequest(responseStreamObserver2);

My questions are:

  1. when I call streamClientSender1.onNext(request) a stream will be created, when I call it again to send another request will the same stream be utilised as long as that stream is alive until max connection age
  2. using two diff objects streamClientSender1 and streamClientSender2 will it create two separate streams when onNext is called on client side
  3. Is there any way to get StreamIDs of the stream created during a call and print it as a verification and as a answer for above questions.

I tried printing the objects on the server and see

  1. If same responseObserver is used for receiving when client sends diff requests with same object
  2. If diff responseObserver are created for receiving when using diff sender objects on the client side

Seems like above two conditions were true. But just wanted to verify if it applies to streams also. in other words, A stream is mapped to an sender object(in above case streamClientSender2 and streamClientSender1) and it can be reused by reusing an object to send or receiving something.


Solution

  • An HTTP/2 stream is created for each RPC. So stub.sendRequest(req) creates the stream and that stream lives for the life of the RPC. (Things are a more complicated if retries are in use, but this is still a fine mental model.)

    1. Calling onNext() simply sends a message on the existing stream
    2. Calling stub.sendRequest() twice creates two streams
    3. gRPC does not expose its stream ids to the user. The user interacts with RPCs

    On server-side, the responseObserver instance doesn't influence how many streams are created. There is simply one stream per RPC. If you choose to use the same responseObserver for two RPCs, then you have two streams that each notify the same object for incoming messages. Sharing StreamObservers across RPCs is an API violation of StreamObserver, because onCompleted() will be called multiple times and the calls to the observer will not be synchronized.