20
votes

I am studying the Netty 4.0.0.Alpha5 code in order to find out how threading is handled. I also read the introduction to the new threading model of Netty 4 at http://netty.io/wiki/new-and-noteworthy-in-4.0.html#wiki-h2-34.

As I understand it, the goals are:

  • Thread affinity, stick a Channel to a single Thread (EventLoop). I guess this approach was taken to reduce cache misses and to improve the situation on NUMA hardware.

So, I am wondering whether my interpretation is right or not. And if I am right, then the following question arises:

  • Having a possibly long running ChannelHandler (e.g. a database operation) in the ChannelPipeline might block the EventLoop (Thread) and will therefore block all other Channels assigned to the same EventLoop (Thread). Is this interpretation true?
  • Trying to avoid that problem I could use a EventExecutor for the long running ChannelHandler, but according to the documentation (see link above) a Channel is again stuck to a single Thread within its EventExectuor and might therefore again block other Channels which are assigned the same Thread (within the EventExecutor). Did I miss something or is this true?

I am just trying to understand why the things are the way they are and to get some information about the design intentions of Netty 4.

2

2 Answers

8
votes

True to the both question. By assigning a handler to a non-I/O event group, you can prevent an I/O thread from getting blocked by long running operations such as database access. You can specify an EventExecutorGroup with large size depending on what the handler does. It's not very different from what usual thread pool does. If thread pool is busy, any attempt to execute a long running task will be queued.

2
votes

Your two points are also true with Netty 3.

Netty 3 had a concept of boss and worker threads. A boss thread was responsible for accepting new connections, which it would then offload to a worker thread. The amount of worker threads was configurable when creating your NioServerSocketChannelFactory.

Now Netty 4 has replaced these boss and worker threads by respectively parent event loop and child event loop. But the core idea has remained the same: in order to get rid of the thread-per-connection model you must allocate more than one connection to a thread.
So when you create a server there will be a fixed pool of N threads dedicated to handling connections. If the number of connections is below N, then there won't be more than one connection per thread. On the other hand, if you have more than N connections, some threads will manage more than one connection. This is done in a round-robin fashion, check out MultithreadEventExecutorGroup.next()