Before reading Netty’s source code, let’s take a quick look at the three core classes.

EventLoop

An EventLoop maintains a task queue internally, and an EventLoop holds a multiplexer Selector. EventLoop constantly fetches the task execution from the task queue, and also keeps an eye on whether the Selector has an available connection. If any connections are available, EventLoop will also handle them.

protected void run() {
    int selectCnt = 0;
    for(; ;) {if (ioRatio == 100) {
            try {
                if(strategy > 0) {// Look at the Selector connection state processSelectedKeys(); }} finally {// ranTasks = runAllTasks(); }}else if(strategy > 0) { final long ioStartTime = System.nanoTime(); try { processSelectedKeys(); } finally { // Ensure we always run tasks. final long ioTime = System.nanoTime() - ioStartTime; ranTasks = runAllTasks(ioTime * (100 - ioRatio) / ioRatio); }}else {
            ranTasks = runAllTasks(0); // This will run the minimum number of tasks
        }
    }
}
Copy the code

The code above is the run method of NioEventLoop, an implementation of EventLoop. Some other code has been removed for ease of reading. As you can see from the above code, EventLoop keeps an eye on the connection between the task queue and the Selector in an infinite loop.

EventLoopGroup

The EventLoopGroup, as its name implies, is a collection of Eventloops. This class holds multiple Eventloops internally, and its main function is to evenly distribute the received tasks to the internally held Eventloops.

Channel

A Channel is an encapsulation of JDK sockets by Netty. A Channel holds a Socket inside it. A Channel also holds a ChannelPipeline object inside the Channel. The ChannelPipeline object concatenates our Socket processing logic.

I/O Request via {Channel} or {ChannelHandlerContext} | +---------------------------------------------------+---------------+ | ChannelPipeline | | | \|/ | | +---------------------+ +-----------+----------+ | | | Inbound Handler N | | Outbound Handler 1 | | | + -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- + + -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- + | | | / \ | | | | \ | / | | + -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- + +-----------+----------+ | | | Inbound Handler N-1 | | Outbound Handler 2 | | | +----------+----------+ +-----------+----------+ | | /|\ . | | . . | | ChannelHandlerContext.fireIN_EVT() ChannelHandlerContext.OUT_EVT()| | [ method call] [method call] | | . . | | . \|/ | | +----------+----------+ +-----------+----------+ | | | Inbound Handler 2 | | Outbound Handler M-1 | | | +----------+----------+ +-----------+----------+ | | /|\ | | | | \|/ | | +----------+----------+ +-----------+----------+ | | | Inbound Handler 1 | | Outbound Handler M | | | + -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- + + -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- + | | | / \ | | + -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + | \ | / +---------------+-----------------------------------+---------------+ | | | | | [ Socket.read() ] [ Socket.write() ] | |  +-------------------------------------------------------------------+Copy the code

This is the ChannelPipeline comment, I think it is enough image.

So the purpose of the Channel object is to concatenate the processing logic of our stream, and then make the receiving Socket run according to the concatenated logic.


Now that we know what these three key classes do, we can try to sketch the flow of the Netty framework in combination with the server-side code from the previous article.

  1. First, a separate EventLoop(boss) receives the network connection and passes the connection to the EventLoopGroup(worker).
  2. The EventLoopGroup(worker) then evenly allocates network connections to the internally held EventLoop for processing.
  3. EventLoop will keep an eye on the read/write events of the connection after the connection is acquired. If there is a ready read/write event, it will follow the Pipline inside the Channel for chain processing.

Below we will start from the source code, look at Netty’s internal process is exactly how.