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

An example Analysis of run method of NioEventLoop

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

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

This article mainly introduces the relevant knowledge of NioEventLoop's run method case analysis, the content is detailed and easy to understand, the operation is simple and fast, and it has a certain reference value. I believe you will have something to gain after reading this NioEventLoop run method case analysis article. Let's take a look.

Netty event loop main logic

The main logic of Netty event loop is in the processSelectedKeys function in NioEventLoop.run.

The protected void run () {/ / main loop keeps reading IO events and task, because EventLoop is also juc's ScheduledExecutorService implementation for (;;) {try {switch (selectStrategy.calculateStrategy (selectNowSupplier, hasTasks () {case SelectStrategy.CONTINUE: continue Case SelectStrategy.SELECT: select (wakenUp.getAndSet (false)); if (wakenUp.get ()) {selector.wakeup () } / / fall through default:} cancelledKeys = 0; needsToSelectAgain = false; / / IO event as a percentage of total execution time * / final int ioRatio = this.ioRatio If (ioRatio = = 100) {try {processSelectedKeys ();} finally {/ / Ensure we always run tasks. RunAllTasks ();}} else {final long ioStartTime = System.nanoTime (); try {processSelectedKeys ();} finally {/ / Ensure we always run tasks. Final long ioTime = System.nanoTime ()-ioStartTime; runAllTasks (ioTime * (100-ioRatio) / ioRatio);} catch (Throwable t) {handleLoopException (t);} / / Always handle shutdown even if the loop processing threw an exception. Try {if (isShuttingDown ()) {closeAll (); if (confirmShutdown ()) {return;} catch (Throwable t) {handleLoopException (t);}

When the processSelectedKeys function executes, it determines whether to perform the optimized version, that is, to determine whether the SelectedSelectionKeySet is empty.

Whether optimization is enabled depends on whether the environment variable io.netty.noKeySetOptimization is set. False means to enable it by default.

Private static final boolean DISABLE_KEYSET_OPTIMIZATION = SystemPropertyUtil.getBoolean ("io.netty.noKeySetOptimization", false)

The principle is to set the selectKeys property in the selector bound by eventLoop to SelectedSelectionKeySet by reflection. The advantage is that there is no need to iterate through selector.selectedKeys ().

Initialize EventLoop

When the injection timing is to initialize the EventLoop

Private SelectorTuple openSelector () {12 / / injection logic 40 Object maybeException = AccessController.doPrivileged (new PrivilegedAction () {@ Override public Object run () {try {Field selectedKeysField = selectorImplClass.getDeclaredField ("selectedKeys"); Field publicSelectedKeysField = selectorImplClass.getDeclaredField ("publicSelectedKeys") Throwable cause = ReflectionUtil.trySetAccessible (selectedKeysField); if (cause! = null) {return cause;} cause = ReflectionUtil.trySetAccessible (publicSelectedKeysField); if (cause! = null) {return cause } selectedKeysField.set (unwrappedSelector, selectedKeySet); publicSelectedKeysField.set (unwrappedSelector, selectedKeySet); return null;} catch (NoSuchFieldException e) {return e;} catch (IllegalAccessException e) {return e }); .78} handle read events

The processing of read events is mainly in processSelectedKey, which deals with read, write and connection events respectively.

Private void processSelectedKeysOptimized () {for (int I = 0; I)

< selectedKeys.size; ++i) { final SelectionKey k = selectedKeys.keys[i]; // null out entry in the array to allow to have it GC'ed once the Channel close // See https://github.com/netty/netty/issues/2363 selectedKeys.keys[i] = null; final Object a = k.attachment(); if (a instanceof AbstractNioChannel) { //分别处理每个channel的事件 processSelectedKey(k, (AbstractNioChannel) a); } else { @SuppressWarnings("unchecked") NioTask task = (NioTask) a; processSelectedKey(k, task); } if (needsToSelectAgain) { // null out entries in the array to allow to have it GC'ed once the Channel close // See https://github.com/netty/netty/issues/2363 selectedKeys.reset(i + 1); selectAgain(); i = -1; } } } private void processSelectedKey(SelectionKey k, AbstractNioChannel ch) { final AbstractNioChannel.NioUnsafe unsafe = ch.unsafe(); if (!k.isValid()) { final EventLoop eventLoop; try { eventLoop = ch.eventLoop(); } catch (Throwable ignored) { // If the channel implementation throws an exception because there is no event loop, we ignore this // because we are only trying to determine if ch is registered to this event loop and thus has authority // to close ch. return; } // Only close ch if ch is still registered to this EventLoop. ch could have deregistered from the event loop // and thus the SelectionKey could be cancelled as part of the deregistration process, but the channel is // still healthy and should not be closed. // See https://github.com/netty/netty/issues/5125 if (eventLoop != this || eventLoop == null) { return; } // close the channel if the key is not valid anymore unsafe.close(unsafe.voidPromise()); return; } try { int readyOps = k.readyOps(); // We first need to call finishConnect() before try to trigger a read(...) or write(...) as otherwise // the NIO JDK channel implementation may throw a NotYetConnectedException. if ((readyOps & SelectionKey.OP_CONNECT) != 0) { // remove OP_CONNECT as otherwise Selector.select(..) will always return without blocking // See https://github.com/netty/netty/issues/924 int ops = k.interestOps(); ops &= ~SelectionKey.OP_CONNECT; k.interestOps(ops);          //处理了连接事件 unsafe.finishConnect(); } // Process OP_WRITE first as we may be able to write some queued buffers and so free memory. if ((readyOps & SelectionKey.OP_WRITE) != 0) { // Call forceFlush which will also take care of clear the OP_WRITE once there is nothing left to write //将要写入的buffer flush掉          ch.unsafe().forceFlush(); } // Also check for readOps of 0 to workaround possible JDK bug which may otherwise lead // to a spin loop if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {         //回调 pipeline 上所有的 ChannelInboundHandler 的 fireChannelRead 和 channelReadComplete 函数 unsafe.read(); } } catch (CancelledKeyException ignored) { unsafe.close(unsafe.voidPromise()); } }注意 NioServerSocketChannel 和 NioSocketChannel 都是 同样的 处理逻辑, 不同的是 前者 只关注 OP_ACCEPT 和 OP_READ事件, 后者 关注 OP_READ、OP_WRITE、OP_CONNECT事件 当NioServerSocketChannel 发生 OP_ACCEPT事件时 会 触发 AbstractNioChannel.NioUnsafe.read ->

NioSctpServerChannel.doReadMessages (List)-> ServerBootstrapAcceptor.channelRead

Register the received NioSocketChannel with childEventLoop.

This is the end of the article on "run method example Analysis of NioEventLoop". Thank you for reading! I believe you all have a certain understanding of the knowledge of "run method case Analysis of NioEventLoop". If you want to learn more, you are welcome to follow the industry information channel.

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

Development

Wechat

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

12
Report