In my opinion, Netty’s kernel mainly includes the following three parts:

The main responsibilities of each core module are as follows:

  • Memory management improves efficient memory management, including memory allocation and memory reclamation.

  • Netcom channel replicates network communication, for example, realizes the encapsulation of low-level JAVA apis such as NIO and OIO, and simplifies network programming model.

  • Threading model

    Provides an efficient thread collaboration model.

If you think back to the interview process in the past, the interviewer would often ask: What is Netty’s threading model?

Reactor model, I’m sure you can blurt it out, and then what? And then there is no?

What problems does threading model solve in network communication? How is it solved in Netty, and why is Netty’s threading model so efficient? Allow me to explain.

Tips: In order to ensure the rigor of the article, the field of inquiry is locked in: Netty NIO related.

1. Principal/slave multiple Reactor model


The principal/slave multiple Reactor model is a very classic threading programming model in the industry, and its schematic diagram is shown as follows:

Let’s start with a quick look at some of the key players in the image above:

  • Acceptor

    The request receiver, in practice, acts like a server and is not really responsible for the establishment of the connection request, but simply delegates its request to the Main Reactor thread pool, acting as a forwarding agent.

  • Main Reactor Main Reactor thread group, which connects events and forwards I/O requests to the SubReactor thread pool. Of course, in some scenarios, such as client permission control, the responsibility of permission verification can be placed in the Main Reactor thread pool, that is, the Main Reactor can register channel read and write events, read data packets related to client permission verification, and perform permission verification. After the permission is verified, the 2 channels are registered with the IO thread.

  • Sub Reactor Main The Sub Reactor usually listens for client connections and forwards channel reads and writes to a thread in the Sub Reactor thread pool (load balancing), which is responsible for reading and writing data. Read (OP_READ) and write events (OP_WRITE) of channels are usually registered in NIO.

To better understand the Reactor model, let’s take a look at the key actions that network communication typically involves:

The common steps of a network interaction are as follows:

  • The server starts and listens on a specific port, such as port 80 for the Web application.

  • The client initiates a TCP three-way handshake to establish a connection with the server. The NIO SocketChannel object is created after the connection is successfully established.

  • The server reads data from the nic through NioSocketChannel.

  • The server decodes requests from the binary stream according to the communication protocol.

  • Perform service operations based on the request. For example, the Dubbo server receives information about a query user whose ID is 1.

  • Returning service execution results to the client usually involves protocol coding and compression.

The threading model needs to solve the following problems: how to use multithreaded programming to improve performance for connection monitoring, network reading and writing, coding, decoding and business execution.

How does the Reactor model solve the above problems?

  1. Connection establishment (OP_ACCEPT) is the responsibility of the Main Reactor thread pool. Once a NioSocketChannel is created, it is forwarded to the SubReactor.

  2. The SubReactor thread pool is mainly responsible for read and write of the network (read byte streams from the network and send byte streams to the network), that is, register OP_READ and OP_WRITE, and bind one SubReactor thread to the same channel.

  3. Encoding, decoding, business execution, then specific case specific analysis

    Usually encoding and decoding in IO thread of execution, the execution of business logic will often use extra thread pool, but not absolute, a good framework parameters is usually used for customization options, such as ping pong, this kind of heartbeat packets, directly in the IO thread of execution, no need to forwarded to the thread pool, avoid thread overhead.

Warm tip: In network programming, the thread used for network reading and writing is usually called IO thread.

2. Netty’s threading model


Netty’s threading model is based on the Reactor model.

Netty connection events (OP_ACCEPT) are implemented by the Main Reactor thread Group (Boss Group), which usually requires only one thread to be set up.

Network read and write operations are implemented by the Work Group (Sub Reactor) thread Group, the number of threads is 2 * CPU Core by default, a Channel is bound to one Work thread, a Work thread can be bound to multiple channels.

In Netty, encoding and decoding operations are encapsulated as channelHandlers. Are these handlers executed in the IO thread pool?

By default ChannelHandler is executed in an IO thread, so how do you change the default behavior? The key codes are as follows:

Key point: You can specify which thread pool to execute in when adding event handlers to the event chain, or IO threads if you do not specify it.

Interviewer: There is usually a thread pool for business operations. How do I write the response to the NETWORK card through the IO thread after the business is finished?

After calling the write method of the Channel object, the business thread will not write the data to the network immediately, but only put the data into a queue to be written (cache). Then, after executing the event selection, the IO thread will get the write task from the cache to write the data to the network. Data is written to the NIC through a series of Channel handlers (Netty event propagation mechanism) before reaching the NIC.

Finally, I will introduce the general workflow of IO threads in Netty.

IO thread processing key points:

  • Each IO thread performs the above operations serially, that is, for all channels registered in a Selector, only one channel’s events are processed at a time. ** This is the root reason why NIO has no advantage when dealing with large file transfers.

  • After processing all the ready events, the I/O thread also obtains tasks from the Task Queue. For example, the service thread mentioned above needs to write the returned results to the network after executing services. All network read and write operations in Netty can only run in the I/O thread. Therefore, the service thread needs to encapsulate the response result with write into a Task and put it into the Task queue of the I/O thread.

  • Event propagation mechanism, can refer to the author recently published article: Netty event propagation mechanism in detail

3, summarize


Getting back to the subject, if we were to meet an interviewer in the middle of an interview who asked “What is Netty’s threading model?” We should be able to take it in stride.

I think it can be expanded from the following aspects.

  1. Netty’s threading model is based on the Reactor model. Normally one thread handles the OP_ACCEPT event, and an I/O thread with twice the number of CPU cores handles the read and write event.

  2. A channel’s IO operations are bound to one IO thread, and one IO thread can register multiple channels.

  3. In a network communication usually includes network data reading and writing, coding, decoding, business processing. By default, encoding, decoding, and so on run in IO threads, but other thread pools can be specified.

  4. For example, heartbeat packets can be directly processed in the I/O thread and then forwarded to the service thread pool to avoid thread switching.

  5. Events for all channels in an IO thread are processed sequentially.


This article is introduced here, please light up to see, like, forward, message is the biggest encouragement to me.

TOP3 hottest articles of the year

Here’s some advice from a 10-year IT veteran for new employees

How can programmers increase influence

How to read source code efficiently