19

I tried profiling a gRPC java server. And i see the below set of thread pools majorly.

  • grpc-default-executor Threads : Created 1 for each incoming request.
  • grpc-default-worker-ELG Threads: May be to listen on the incoming gRPC requests & assign to the above "grpc-default-executor" thread.

Overall, is gRPC java server, Netty style or Jetty/Tomcat style? Or it can configured to run as both ways?

Venkata Naresh
  • 377
  • 1
  • 2
  • 9

2 Answers2

12

gRPC Java server is exposed closer to Jetty/Tomcat style, except that it is asynchronous. That is, in normal Servlets each request consumes a thread until it is complete. While newer Servlet versions let you detach from the dedicated thread and continue work asynchronously (freeing the thread for other use) that is more uncommon. In gRPC you are free to work in either style. Note that gRPC uses a cachedThreadPool by default to reuse threads; on server-side it's a good idea to replace the default executor with your own, generally fixed-size, pool via ServerBuilder.executor().

Internally gRPC Java uses the Netty-style. That means fully non-blocking. You may use ServerBuilder.directExecutor() to run on the Netty threads. Although in that case you may want to specify the NettyServerBuilder.bossEventLoopGroup(), workerEventLoopGroup(), and for compatibility channelType().

Eric Anderson
  • 24,057
  • 5
  • 55
  • 76
  • 5
    Is there a document from gRPC that talks in detail about this? – user3833308 Apr 18 '19 at 22:06
  • On another note, if we use gRPC as netty style where a new thread spawns for asynchronous completion of the request, how does the client know that the request has finished? How does the onMessage(), isHalfClosed() and other functions get called? Just trying to understand the basics here. Thanks. – stargazer May 15 '19 at 15:55
  • Those callbacks will always occur. By default they run on a cached thread pool, which creates new threads if there are none already available. But you can specify other Executors to use, including directExecutor() which runs the callbacks directly on Netty's thread. – Eric Anderson May 15 '19 at 16:03
  • My question revolves around how will those callbacks occur and how will the client thread know that the request has been completed when gRPC spawns a new thread and disassociates the request from the thread listening on the server port? Please correct me if I am wrong here. – stargazer May 15 '19 at 18:09
  • The RPC is completed when `ClientCall.Listener.onClose()`/`StreamObserver.onCompleted()` is called. There's no interaction with "thread listening on server port". And there is no such assocation such that you would "disassociate the request from the thread...". You may need to create a separate question. – Eric Anderson May 15 '19 at 18:37
  • @user3833308 Found related documentation here: https://grpc.io/docs/what-is-grpc/core-concepts/#synchronous-vs-asynchronous (says complete ref doc coming soon) – Weishi Z Sep 23 '21 at 04:54
1

As far as I know you can specify using the directExecutor() when building the GRPC server / client that will ensure all work is done in the IO thread and so threads will be shared. The default is to not do this for safety reasons as you will need to be very careful about what you do if you are in the IO Thread (like you should never block there).

Norman Maurer
  • 23,104
  • 2
  • 33
  • 31