Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the startup process of Netty Client?

2025-02-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly explains "what is the startup process of Netty Client". Interested friends may wish to take a look at it. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn what the Netty Client startup process is like.

Uncover the secrets of Client startup process 1. The entrance to exploring secrets: netty-client demo

Here we use EchoClient in netty-exmaple as an example:

Public final class EchoClient {public static void main (String [] args) throws Exception {EventLoopGroup group = new NioEventLoopGroup (); try {Bootstrap b = new Bootstrap () B.group (group) .channel (NioSocketChannel.class) .option (ChannelOption.TCP_NODELAY, true) .handler (new ChannelInitializer () {@ Override public void initChannel (SocketChannel ch) throws Exception {ChannelPipeline p = ch.pipeline (); p.addLast (new EchoClientHandler () }}); ChannelFuture f = b.connect (HOST, PORT). Sync (); f.channel (). CloseFuture (). Sync ();} finally {group.shutdownGracefully ();}

There is nothing unique about the code, and we combed through some routines of Netty network programming in our last article, so I won't repeat them here. (for children who have forgotten, you can check the Netty series of articles to find it.)

The client code above is simple, but it shows everything you need for Netty client initialization:

Either the EventLoopGroup:Netty server or the client must specify EventLoopGroup, and the client specifies NioEventLoopGroup

Bootstrap: Netty client startup class, which is responsible for client startup and initialization process

Channel () type: specify the type of Channel. Since this is the client, NioSocketChannel is used, and the server will use NioServerSocketChannel.

Handler: set the processor of the data

Bootstrap.connect (): how the client connects to the netty service

2. NioEventLoopGroup process parsing

Let's start with NioEventLoopGroup, parsing line by line of code, and first look at its class structure:

The above is a rough class structure, and EventLoop inherits from EventLoopGroup, so we can imagine the general structure of the class. Some of the core logic here will be in MultithreadEventExecutorGroup, including the creation and initialization of EventLoopGroup, etc.

Then start with the NioEventLoopGroup constructor and follow it step by step (the code only shows the key parts, leaving out a lot of code that you don't need to care about for the time being, and the following code follows this principle):

EventLoopGroup group = new NioEventLoopGroup (); public NioEventLoopGroup () {this (0);} public NioEventLoopGroup (int nThreads, Executor executor, final SelectorProvider selectorProvider) {this (nThreads, executor, selectorProvider, DefaultSelectStrategyFactory.INSTANCE);} protected MultithreadEventLoopGroup (int nThreads, Executor executor, Object... Args) {super (nThreads = = 0? DEFAULT_EVENT_LOOP_THREADS: nThreads, executor, args);}

Here, you pass it all the way down by calling the this () and super () methods, during which some default properties are constructed, passed all the way to the MultithreadEventExecutorGroup class, and then look west.

2.1 、 MultithreadEventExecutorGroup

The above constructor has an important argument passed: DEFAULT_EVENT_LOOP_THREADS, which defaults to the number of CPU cores * 2.

Why pass this parameter? As we said earlier, EventLoopGroup can be understood as a thread pool, MultithreadEventExecutorGroup has a thread array EventExecutor [] children attribute, and the DEFAULT_EVENT_LOOP_THREADS passed is the length of the array.

Let's take a look at the construction method in MultithreadEventExecutorGroup:

Protected MultithreadEventExecutorGroup (int nThreads, Executor executor, EventExecutorChooserFactory chooserFactory, Object... Args) {if (executor = = null) {executor = new ThreadPerTaskExecutor (newDefaultThreadFactory ());} children = new EventExecutor [nThreads]; for (int I = 0; I

< nThreads; i ++) { children[i] = newChild(executor, args); } // ... 省略} 这段代码执行逻辑可以理解为: 通过ThreadPerTaskExecutor构造一个Executor执行器,后面会细说,里面包含了线程执行的execute()方法 接着创建一个EventExecutor数组对象,大小为传递进来的threads数量,这个所谓的EventExecutor可以理解为我们的EventLoop,在这个demo中就是NioEventLoop对象 最后调用 newChild 方法逐个初始化EventLoopGroup中的EventLoop对象 上面只是大概说了下MultithreadEventExecutorGroup中的构造方法做的事情,后面还会一个个详细展开,先不用着急,我们先有个整体的认知就好。 再回到MultithreadEventExecutorGroup中的构造方法入参中,有个EventExecutorChooserFactory对象,这里面是有个很亮眼的细节设计,通过它我们来洞悉Netty的良苦用心。 2.1、亮点设计:DefaultEventExecutorChooserFactory EventExecutorChooserFactory这个类的作用是用来选择EventLoop执行器的,我们知道EventLoopGroup是一个包含了CPU * 2个数量的EventLoop数组对象,那每次选择EventLoop来执行任务是选择数组中的哪一个呢? 我们看一下这个类的具体实现,红框中都是需要重点查看的地方:

DefaultEventExecutorChooserFactory is a selector factory class that calls the next () method inside for the purpose of polling for selection.

The length of the array is length, execute for the nth time, which element in the array is the remainder of length.

Back to the implementation of the code, the optimization here is to first determine whether the length of the array is the n power of 2 through the isPowerOfTwo () method, the way of judgment is very ingenious, using val &-val = = val, here I do not explain too much, there are many excellent solutions to judge the n power of 2 on the Internet, I will not play tricks. (please refer to https://leetcode-cn.com/problems/power-of-two/solution/2de-mi-by-leetcode/)

Of course, I think there is an algorithm that is easier to understand: X & (x-1) = = 0 you can understand it by looking at the figure below, so we won't extend it here:

BUT!!! Why take great pains to judge that the length of the array is 2 to the n power?

I wonder if my friends still remember HashMap by Daming Lake. Generally speaking, we require that the length of the HashMap array should be the n power of 2, because the method of finding the array position in the key value: (n-1) & hash n is the array length, where the performance can be improved by bit operation if the array length is the n power of 2. When length is the n power of 2, the following formula is equivalent:

N & (length-1) n% length

Remember that the length of the array is CPU * 2 by default, while the general number of server CPU cores is 2, 4, 8, 16, and so on, so this small optimization is very practical. If you think about it carefully, the initialization of the array length is also very particular.

The advantage of bit operation here is that it is much more efficient than and operation, and Netty has optimized this small detail, which is really great.

2.3.Thread executor: ThreadPerTaskExecutor

Then take a look at the ThreadPerTaskExecutor thread executor, which creates a thread entity each time a task is executed.

Public final class ThreadPerTaskExecutor implements Executor {private final ThreadFactory threadFactory; public ThreadPerTaskExecutor (ThreadFactory threadFactory) {if (threadFactory = = null) {throw new NullPointerException ("threadFactory");} this.threadFactory = threadFactory;} @ Override public void execute (Runnable command) {threadFactory.newThread (command). Start ();}}

The threadFactory passed in is DefaultThreadFactory, where the NioEventLoop thread naming convention is constructed as nioEventLoop-1-xxx, so we won't take a closer look at this. The execute () method is called when the thread executes, and a FastThreadLocalThread thread is created here, depending on the code:

Public class DefaultThreadFactory implements ThreadFactory {@ Override public Thread newThread (Runnable r) {Thread t = newThread (FastThreadLocalRunnable.wrap (r), prefix + nextId.incrementAndGet ()); return t;} protected Thread newThread (Runnable r, String name) {return new FastThreadLocalThread (threadGroup, r, name);}}

Here a thread is created through newThread (), and then the thread object data is initialized, which is eventually called into Thread.init ().

2.4.initialization of EventLoop

Let's move on to the MultithreadEventExecutorGroup construction method:

Protected MultithreadEventExecutorGroup (int nThreads, Executor executor, EventExecutorChooserFactory chooserFactory, Object... Args) {children = new EventExecutor [nThreads]; for (int I = 0; I < nThreads; I + +) {children [I] = newChild (executor, args); / /. Omit some code}}

The last part of the above code is the newChild method, which is an abstract method whose task is to instantiate the EventLoop object. If we trace its code, we can see that this method is implemented in the NioEventLoopGroup class, and its content is simple:

@ Overrideprotected EventLoop newChild (Executor executor, Object... Args) throws Exception {return new NioEventLoop (this, executor, (SelectorProvider) args [0], ((SelectStrategyFactory) args [1]). NewSelectStrategy (), (RejectedExecutionHandler) args [2]);} NioEventLoop (NioEventLoopGroup parent, Executor executor, SelectorProvider selectorProvider, SelectStrategy strategy, RejectedExecutionHandler rejectedExecutionHandler) {super (parent, executor, false, DEFAULT_MAX_PENDING_TASKS, rejectedExecutionHandler); if (selectorProvider = null) {throw new NullPointerException ("selectorProvider") } if (strategy = = null) {throw new NullPointerException ("selectStrategy");} provider = selectorProvider; final SelectorTuple selectorTuple = openSelector (); selector = selectorTuple.selector; unwrappedSelector = selectorTuple.unwrappedSelector; selectStrategy = strategy;}

You just instantiate a NioEventLoop object and return it. The provider and event poller selector are saved in the NioEventLoop constructor, a MpscQueue queue is created in its parent class, and then the thread executor executor is saved.

In retrospect, MultithreadEventExecutorGroup maintains an array of EventExecutor [] children internally, and the implementation mechanism of Netty's EventLoopGroup is actually based on MultithreadEventExecutorGroup.

Whenever Netty needs an EventLoop, the next () method is called to get an available EventLoop object from the EventLoopGroup array. Among them, the implementation of the next method is completed through NioEventLoopGroup.next (), which is calculated by the polling algorithm explained above.

Finally, summarize the initialization process of the whole EventLoopGroup:

EventLoopGroup (actually MultithreadEventExecutorGroup) internally maintains an array of type EventExecutor children, and the length of the array is nThreads

If we specify the thread pool size when we instantiate NioEventLoopGroup, then nThreads is the specified value, and vice versa, the number of processor cores * 2

The newChild abstract method is called in MultithreadEventExecutorGroup to initialize the children array.

The abstract method newChild is implemented in NioEventLoopGroup, which returns an instance of NioEventLoop.

NioEventLoop attribute:

SelectorProvider provider attribute: get a SelectorProvider through SelectorProvider.provider () in the NioEventLoopGroup constructor

Selector selector attribute: a selector object is obtained by calling selector = provider.openSelector () in the NioEventLoop constructor.

2.5 、 NioSocketChannel

In Netty, Channel is an abstraction of Socket, and every time Netty establishes a connection, there is an instance of Channel corresponding to it.

We set channel (NioSocketChannel.class) in the beginning Demo, and the class structure of NioSocketChannel is as follows:

Then analyze the code, and when we call b.channel (), we actually enter the AbstractBootstrap.channel () logic, and then look at the code in AbstractBootstrap:

Public B channel (Class

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report