There are three main threadpools that gRPC Java uses in Server mode:

* Boss Event Loop Group  (a.k.a. bossEventLoopGroup() )
* Worker Event Loop Group ( a.k.a. workerEventLoopGroup() )
* Application Executor (a.k.a. executor() )

The Boss group can be the same as the worker group.  It's purpose is to 
accept calls from the network, and create Netty channels (not gRPC 
Channels) to handle the socket.   Effectively, this is the thread pool that 
calls listen() and accept().   

Once the Netty channel has been created it gets passes to the Worker Event 
Loop Group.  This is the threadpool dedicating to doing socket read() and 
write() calls.  This is often called the "network thread".   In addition to 
doing the direct reads and writes, it can also do small amounts of 
processing, such as turn a collection of bytes into an HTTP/2 request, or 
do SSL / TLS encryption.  The main thing to know about this group is that 
it must never block.  That is, it cannot call wait(), or sleep(), or await 
results from a Future, or things like that.  The reason is that doing this 
prevents the worker thread (the "event loop") from servicing other requests.


The last thread group is the application executor, also called the "app 
thread".  This is where the gRPC stubs do their main work.  It is for 
handling the callbacks that bubble up from the network thread.  For 
example, when a packet comes in, the worker thread decrypts it, decodes the 
HTTP/2 code, and then notifies the app thread that data has arrived.  It 
immediately goes back to doing other network work.  The App thread notices 
that there is data available, and converts the data into (usually) a 
Protobuf, and then invokes your stub.   

Note that the Application executor could have no threads at all.  This 
would make the network thread immediately do the work of handling the 
request.   On the builder this is the directExecutor() function.   The 
reason for using this is that it saves a thread hop from worker event loop 
to the app thread, or about 15 microseconds.  In very latency sensitive 
environments this is a good idea.  However, it makes it very easy to 
accidentally do blocking work, which is deadlock prone.   It is rarely 
correct to do.


As for usages:   Most people should use either reuse the same boss event 
loop group as the worker group.   Barring this, the boss eventloop group 
should be a single thread, since it does very little work.  For the app 
thread, users should provide a fixed size thread pool.  By default, we use 
an unbounded cached threadpool, but this is just for safety.  It is not the 
most efficient, and can be dangerous in some circumstances.  It just 
happens to be the safest default, given no other information.       


On Tuesday, October 3, 2017 at 12:43:30 PM UTC-7, Pierre wrote:
>
> Hello,
>
> What is the difference between setting an executor(Threadpool) and setting 
> a workerEventLoopGroup(EventLoopThreadPool) on NettyServerBuilder.
>
>
> If I understand, all the IO operations (accept connexions, read/send 
> packet...) are done by the bossEventLoopGroup thread.
>
>
> But what about the RPC call themself ? Are they done by executor 
> threadpool or workerEventLoop threads ?
>

-- 
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 post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/grpc-io.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/grpc-io/d534e68e-857a-47fa-8ad3-d68db9871e13%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to