Thread Model in Netty
1. Netty's Thread Model

Model explanation:
- Netty abstracts two thread pools: BossGroup and WorkerGroup. BossGroup is specifically responsible for accepting client connections, while WorkerGroup is specifically responsible for network read/write operations.
- Both BossGroup and WorkerGroup are of type NioEventLoopGroup.
- NioEventLoopGroup is equivalent to an event loop thread group. This group contains multiple event loop threads, and each event loop thread is a NioEventLoop.
- Each NioEventLoop has a selector for monitoring network communication of SocketChannels registered on it.
- Each Boss NioEventLoop thread internally executes 3 steps in a loop:
- Handle accept events, establish connections with clients, and generate NioSocketChannel
- Register NioSocketChannel to a selector on some worker NIOEventLoop
- Process tasks in the task queue, i.e., runAllTasks
- Each worker NIOEventLoop thread executes the following steps in a loop:
- Poll all NioSocketChannels registered on its selector for read/write events
- Handle I/O events, i.e., read/write events, and process business logic in the corresponding NioSocketChannel
- runAllTasks processes tasks in the TaskQueue. Some time-consuming business processing can be placed in the TaskQueue for slow processing, so it doesn't affect data flow processing in the pipeline.
- When each worker NIOEventLoop processes NioSocketChannel business, it uses a pipeline. The pipeline maintains many handler processors to process data in the channel.
2. Netty Module Components
2.1 Bootstrap, ServerBootstrap
Bootstrap means bootstrapping. A Netty application typically starts with a Bootstrap, whose main function is to configure the entire Netty program and connect various components. In Netty, the Bootstrap class is the startup bootstrap class for client programs, and ServerBootstrap is the startup bootstrap class for servers.
2.2 Future, ChannelFuture
As mentioned earlier, all IO operations in Netty are asynchronous, so you can't immediately know whether a message was processed correctly. However, you can wait for it to complete or directly register a listener. The specific implementation is through Future and ChannelFutures, which can register a listener that automatically triggers when the operation succeeds or fails.
2.3 Channel
Channel is Netty's component for network communication, capable of performing network I/O operations. Channel provides users with:
- Current network connection channel status (e.g., is it open? Is it connected?)
- Network connection configuration parameters (e.g., receive buffer size)
- Asynchronous network I/O operations (such as establishing connections, reading/writing, binding ports). Asynchronous calls mean any I/O call will return immediately without guaranteeing that the requested I/O operation has completed when the call ends.
- Calls immediately return a ChannelFuture instance. By registering listeners to ChannelFuture, you can get callback notifications when I/O operations succeed, fail, or are cancelled.
- Support for associating I/O operations with corresponding handlers.
Different protocols and different blocking types of connections have different Channel types corresponding to them. Here are some commonly used Channel types:
- NioSocketChannel - Asynchronous client TCP Socket connection
- NioServerSocketChannel - Asynchronous server-side TCP Socket connection
- NioDatagramChannel - Asynchronous UDP connection
- NioSctpChannel - Asynchronous client Sctp connection
- NioSctpServerChannel - Asynchronous Sctp server-side connection. These channels cover UDP and TCP network IO as well as file IO.
2.4 Selector
Netty implements I/O multiplexing based on Selector objects. Through Selector, one thread can monitor Channel events from multiple connections. When a Channel is registered with a Selector, the Selector's internal mechanism can automatically and continuously query (Select) whether these registered Channels have ready I/O events (such as readable, writable, network connection completed, etc.). This allows the program to efficiently manage multiple Channels with a single thread.
2.5 NioEventLoop
NioEventLoop maintains a thread and task queue, supporting asynchronous task submission. When the thread starts, it calls NioEventLoop's run method to execute I/O tasks and non-I/O tasks:
I/O tasks are events ready in selectionKey, such as accept, connect, read, write, etc., triggered by the processSelectedKeys method.
Non-I/O tasks are tasks added to taskQueue, such as register0, bind0, etc., triggered by the runAllTasks method.
2.6 NioEventLoopGroup
NioEventLoopGroup mainly manages the lifecycle of eventLoops. It can be understood as a thread pool that internally maintains a group of threads. Each thread (NioEventLoop) is responsible for handling events on multiple Channels, while a Channel only corresponds to one thread.
2.7 ChannelHandler
ChannelHandler is an interface that handles I/O events or intercepts I/O operations and forwards them to the next handler in its ChannelPipeline (business processing chain).
ChannelHandler itself doesn't provide many methods because this interface has many methods that need to be implemented. For convenience, you can extend its subclasses:
ChannelInboundHandler for handling inbound I/O events
ChannelOutboundHandler for handling outbound I/O operations
Or use the following adapter classes:
ChannelInboundHandlerAdapter for handling inbound I/O events
ChannelOutboundHandlerAdapter for handling outbound I/O operations
2.8 ChannelHandlerContext
Saves all context information related to the Channel and associates with a ChannelHandler object.
2.9 ChannelPipeline
Saves a List of ChannelHandlers for processing or intercepting inbound events and outbound operations of a Channel. ChannelPipeline implements an advanced form of intercepting filter pattern, allowing users to have complete control over how events are handled and how ChannelHandlers in the Channel interact with each other.
In Netty, each Channel has one and only one ChannelPipeline corresponding to it. Their composition relationship is as follows:

A Channel contains a ChannelPipeline, and ChannelPipeline maintains a doubly-linked list composed of ChannelHandlerContexts. Each ChannelHandlerContext is associated with a ChannelHandler.
Read events (inbound events) and write events (outbound events) are in a doubly-linked list. Inbound events are passed from the head of the list to the last inbound handler, while outbound events are passed from the tail of the list to the first outbound handler. The two types of handlers don't interfere with each other.
3. ByteBuf Detailed Explanation
Structurally, ByteBuf consists of a byte array. Each byte in the array is used to store information.
ByteBuf provides two indexes: one for reading data and one for writing data. These two indexes move through the byte array to locate positions where information needs to be read or written.
When reading from ByteBuf, its readerIndex will increment according to the number of bytes read. Similarly, when writing to ByteBuf, its writerIndex will also increment according to the number of bytes written.

Note that the extreme case is when readerIndex has just read to where writerIndex has written. If readerIndex exceeds writerIndex, Netty will throw an IndexOutOfBoundsException.