Skip to content

Instantly share code, notes, and snippets.

@coderplay
Last active August 3, 2016 18:41
Show Gist options
  • Save coderplay/9985358 to your computer and use it in GitHub Desktop.
Save coderplay/9985358 to your computer and use it in GitHub Desktop.
Netty 3 & 4 workflow vs Nio Workflow

Netty 3 workflow vs Nio Workflow

Server Side

each thread in the threadpool create a new selector

1. selector = Selector.open()

main@1, prio=5, in group 'main', status: 'RUNNING'
	  at java.nio.channels.Selector.open(Selector.java:227)
	  at org.jboss.netty.channel.socket.nio.SelectorUtil.open(SelectorUtil.java:63)
	  at org.jboss.netty.channel.socket.nio.AbstractNioSelector.openSelector(AbstractNioSelector.java:341)
	  at org.jboss.netty.channel.socket.nio.AbstractNioSelector.<init>(AbstractNioSelector.java:100)
	  at org.jboss.netty.channel.socket.nio.AbstractNioWorker.<init>(AbstractNioWorker.java:52)
	  at org.jboss.netty.channel.socket.nio.NioWorker.<init>(NioWorker.java:45)
	  at org.jboss.netty.channel.socket.nio.NioWorkerPool.createWorker(NioWorkerPool.java:45)
	  at org.jboss.netty.channel.socket.nio.NioWorkerPool.createWorker(NioWorkerPool.java:28)
	  at org.jboss.netty.channel.socket.nio.AbstractNioWorkerPool.newWorker(AbstractNioWorkerPool.java:143)
	  at org.jboss.netty.channel.socket.nio.AbstractNioWorkerPool.init(AbstractNioWorkerPool.java:81)
	  at org.jboss.netty.channel.socket.nio.NioWorkerPool.<init>(NioWorkerPool.java:39)
	  at org.jboss.netty.channel.socket.nio.NioWorkerPool.<init>(NioWorkerPool.java:33)
	  at org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory.<init>(NioServerSocketChannelFactory.java:149)
	  at org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory.<init>(NioServerSocketChannelFactory.java:131)
	  at org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory.<init>(NioServerSocketChannelFactory.java:115)
	  at org.jboss.netty.example.echo.EchoServer.run(EchoServer.java:40)
	  at org.jboss.netty.example.echo.EchoServer.main(EchoServer.java:63)

Start Server

1. serverSocketChannel = ServerSocketChannel.open()

main@1, prio=5, in group 'main', status: 'RUNNING'
	  at java.nio.channels.ServerSocketChannel.open(ServerSocketChannel.java:105)
	  at org.jboss.netty.channel.socket.nio.NioServerSocketChannel.<init>(NioServerSocketChannel.java:55)
	  at org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory.newChannel(NioServerSocketChannelFactory.java:205)
	  at org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory.newChannel(NioServerSocketChannelFactory.java:85)
	  at org.jboss.netty.bootstrap.ServerBootstrap.bindAsync(ServerBootstrap.java:329)
	  at org.jboss.netty.bootstrap.ServerBootstrap.bind(ServerBootstrap.java:266)
	  at org.jboss.netty.example.echo.EchoServer.run(EchoServer.java:53)
	  at org.jboss.netty.example.echo.EchoServer.main(EchoServer.java:63)

2. serverSocketChannel.socket().bind(new InetSocketAddress(port))

New I/O server boss #17@646, prio=5, in group 'main', status: 'RUNNING'
	  at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:203)
	  at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74)
	  at org.jboss.netty.channel.socket.nio.NioServerBoss$RegisterTask.run(NioServerBoss.java:193)
	  at org.jboss.netty.channel.socket.nio.AbstractNioSelector.processTaskQueue(AbstractNioSelector.java:372)
	  at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:296)
	  at org.jboss.netty.channel.socket.nio.NioServerBoss.run(NioServerBoss.java:42)
	  at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
	  at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42)
	  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	  at java.lang.Thread.run(Thread.java:744)

New I/O worker #16@639, prio=5, in group 'main', status: 'RUNNING'
	  at sun.nio.ch.EPollArrayWrapper.epollWait(EPollArrayWrapper.java:-1)
	  at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
	  at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:79)
	  at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:87)
	  at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:98)
	  at org.jboss.netty.channel.socket.nio.SelectorUtil.select(SelectorUtil.java:68)
	  at org.jboss.netty.channel.socket.nio.AbstractNioSelector.select(AbstractNioSelector.java:415)
	  at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:212)
	  at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:89)
	  at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178)
	  at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
	  at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42)
	  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	  at java.lang.Thread.run(Thread.java:744)

New I/O worker #15@638, prio=5, in group 'main', status: 'RUNNING'
	  at sun.nio.ch.EPollArrayWrapper.epollWait(EPollArrayWrapper.java:-1)
	  at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
	  at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:79)
	  at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:87)
	  at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:98)
	  at org.jboss.netty.channel.socket.nio.SelectorUtil.select(SelectorUtil.java:68)
	  at org.jboss.netty.channel.socket.nio.AbstractNioSelector.select(AbstractNioSelector.java:415)
	  at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:212)
	  at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:89)
	  at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178)
	  at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
	  at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42)
	  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	  at java.lang.Thread.run(Thread.java:744)

          ... workers

New I/O worker #1@593, prio=5, in group 'main', status: 'RUNNING'
	  at sun.nio.ch.EPollArrayWrapper.epollWait(EPollArrayWrapper.java:-1)
	  at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
	  at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:79)
	  at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:87)
	  at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:98)
	  at org.jboss.netty.channel.socket.nio.SelectorUtil.select(SelectorUtil.java:68)
	  at org.jboss.netty.channel.socket.nio.AbstractNioSelector.select(AbstractNioSelector.java:415)
	  at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:212)
	  at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:89)
	  at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178)
	  at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
	  at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42)
	  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	  at java.lang.Thread.run(Thread.java:744)

Signal Dispatcher@533 daemon, prio=9, in group 'system', status: 'RUNNING'

Finalizer@534 daemon, prio=8, in group 'system', status: 'WAIT'
	  at java.lang.Object.wait(Object.java:-1)
	  at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)
	  at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)
	  at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:189)

Reference Handler@535 daemon, prio=10, in group 'system', status: 'WAIT'
	  at java.lang.Object.wait(Object.java:-1)
	  at java.lang.Object.wait(Object.java:503)
	  at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)

main@1, prio=5, in group 'main', status: 'RUNNING'
	  at java.util.Arrays.copyOf(Arrays.java:2271)
	  at java.util.zip.ZipCoder.getBytes(ZipCoder.java:89)
	  at java.util.zip.ZipFile.getEntry(ZipFile.java:306)
	  at java.util.jar.JarFile.getEntry(JarFile.java:226)
	  at java.util.jar.JarFile.getJarEntry(JarFile.java:209)
	  at sun.misc.URLClassPath$JarLoader.getResource(URLClassPath.java:840)
	  at sun.misc.URLClassPath.getResource(URLClassPath.java:199)
	  at java.net.URLClassLoader$1.run(URLClassLoader.java:358)
	  at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
	  at java.security.AccessController.doPrivileged(AccessController.java:-1)
	  at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
	  at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
	  at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
	  at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
	  at org.jboss.netty.bootstrap.ServerBootstrap$Binder.channelOpen(ServerBootstrap.java:382)
	  at org.jboss.netty.channel.SimpleChannelUpstreamHandler.handleUpstream(SimpleChannelUpstreamHandler.java:86)
	  at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:564)
	  at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:559)
	  at org.jboss.netty.channel.Channels.fireChannelOpen(Channels.java:170)
	  at org.jboss.netty.channel.socket.nio.NioServerSocketChannel.<init>(NioServerSocketChannel.java:78)
	  at org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory.newChannel(NioServerSocketChannelFactory.java:205)
	  at org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory.newChannel(NioServerSocketChannelFactory.java:85)
	  at org.jboss.netty.bootstrap.ServerBootstrap.bindAsync(ServerBootstrap.java:329)
	  at org.jboss.netty.bootstrap.ServerBootstrap.bind(ServerBootstrap.java:266)
	  at org.jboss.netty.example.echo.EchoServer.run(EchoServer.java:53)
	  at org.jboss.netty.example.echo.EchoServer.main(EchoServer.java:63)

bind twice??

3. selectionKey = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT, serverSocketChannel)

New I/O server boss #17@646, prio=5, in group 'main', status: 'RUNNING'
	  at java.nio.channels.spi.AbstractSelectableChannel.register(AbstractSelectableChannel.java:192)
	  at org.jboss.netty.channel.socket.nio.NioServerBoss$RegisterTask.run(NioServerBoss.java:198)
	  at org.jboss.netty.channel.socket.nio.AbstractNioSelector.processTaskQueue(AbstractNioSelector.java:372)
	  at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:296)
	  at org.jboss.netty.channel.socket.nio.NioServerBoss.run(NioServerBoss.java:42)
	  at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
	  at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42)
	  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	  at java.lang.Thread.run(Thread.java:744)

Service Clients

1. SocketChannel socketChannel = ServerSocketChannel.accpet()

New I/O server boss #17@646, prio=5, in group 'main', status: 'RUNNING'
	  at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:224)
	  at org.jboss.netty.channel.socket.nio.NioServerBoss.process(NioServerBoss.java:100)
	  at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:318)
	  at org.jboss.netty.channel.socket.nio.NioServerBoss.run(NioServerBoss.java:42)
	  at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
	  at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42)
	  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	  at java.lang.Thread.run(Thread.java:744)

Accept n times??

2. selectionKey = socketChannel.register(selector, SelectionKey.OP_READ, socketChannel)

New I/O worker #2@609, prio=5, in group 'main', status: 'RUNNING'
	  at java.nio.channels.spi.AbstractSelectableChannel.register(AbstractSelectableChannel.java:192)
	  at org.jboss.netty.channel.socket.nio.NioWorker$RegisterTask.run(NioWorker.java:151)
	  at org.jboss.netty.channel.socket.nio.AbstractNioSelector.processTaskQueue(AbstractNioSelector.java:372)
	  at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:296)
	  at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:89)
	  at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178)
	  at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
	  at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42)
	  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	  at java.lang.Thread.run(Thread.java:744)

4. socketChannel.read(ByteBuffer byteBuffer)

New I/O worker #2@609, prio=5, in group 'main', status: 'RUNNING'
	  at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:291)
	  at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:64)
	  at org.jboss.netty.channel.socket.nio.AbstractNioWorker.process(AbstractNioWorker.java:108)
	  at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:318)
	  at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:89)
	  at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178)
	  at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
	  at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42)
	  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	  at java.lang.Thread.run(Thread.java:744)

####5. socketChannel.write(ByteBuffer byteBuffer) ####

New I/O worker #2@609, prio=5, in group 'main', status: 'RUNNING'
	  at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471)
	  at org.jboss.netty.channel.socket.nio.SocketSendBufferPool$UnpooledSendBuffer.transferTo(SocketSendBufferPool.java:203)
	  at org.jboss.netty.channel.socket.nio.AbstractNioWorker.write0(AbstractNioWorker.java:201)
	  at org.jboss.netty.channel.socket.nio.AbstractNioWorker.writeFromUserCode(AbstractNioWorker.java:146)
	  at org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink.handleAcceptedSocket(NioServerSocketPipelineSink.java:99)
	  at org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink.eventSunk(NioServerSocketPipelineSink.java:36)
	  at org.jboss.netty.channel.DefaultChannelPipeline.sendDownstream(DefaultChannelPipeline.java:574)
	  at org.jboss.netty.channel.Channels.write(Channels.java:704)
	  at org.jboss.netty.channel.Channels.write(Channels.java:671)
	  at org.jboss.netty.channel.AbstractChannel.write(AbstractChannel.java:248)
	  at org.jboss.netty.example.echo.EchoServerHandler.messageReceived(EchoServerHandler.java:47)
	  at org.jboss.netty.channel.SimpleChannelUpstreamHandler.handleUpstream(SimpleChannelUpstreamHandler.java:70)
	  at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:564)
	  at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:559)
	  at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:268)
	  at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:255)
	  at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:88)
	  at org.jboss.netty.channel.socket.nio.AbstractNioWorker.process(AbstractNioWorker.java:108)
	  at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:318)
	  at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:89)
	  at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178)
	  at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
	  at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42)
	  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	  at java.lang.Thread.run(Thread.java:744)

Netty 4 workflow vs Nio Workflow

Server Side

each thread in the NioEventLoop create a new selector

Both boss and worker NioEventLoop

1. selector = SelectProvider.openSelector()

	at io.netty.channel.nio.NioEventLoop.openSelector(NioEventLoop.java:126)
	at io.netty.channel.nio.NioEventLoop.<init>(NioEventLoop.java:120)
	at io.netty.channel.nio.NioEventLoopGroup.newChild(NioEventLoopGroup.java:87)
	at io.netty.util.concurrent.MultithreadEventExecutorGroup.<init>(MultithreadEventExecutorGroup.java:57)
	at io.netty.channel.MultithreadEventLoopGroup.<init>(MultithreadEventLoopGroup.java:49)
	at io.netty.channel.nio.NioEventLoopGroup.<init>(NioEventLoopGroup.java:61)
	at io.netty.channel.nio.NioEventLoopGroup.<init>(NioEventLoopGroup.java:52)
	at io.netty.channel.nio.NioEventLoopGroup.<init>(NioEventLoopGroup.java:44)
	at io.netty.channel.nio.NioEventLoopGroup.<init>(NioEventLoopGroup.java:36)
	at io.netty.example.echo.EchoServer.run(EchoServer.java:43)
	at io.netty.example.echo.EchoServer.main(EchoServer.java:78)

Start Server

1. serverSocketChannel = ServerSocketChannel.open()

	at io.netty.channel.socket.nio.NioServerSocketChannel.newSocket(NioServerSocketChannel.java:48)
	at io.netty.channel.socket.nio.NioServerSocketChannel.<init>(NioServerSocketChannel.java:62)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
	at java.lang.Class.newInstance(Class.java:374)
	at io.netty.bootstrap.AbstractBootstrap$BootstrapChannelFactory.newChannel(AbstractBootstrap.java:426)
	at io.netty.bootstrap.AbstractBootstrap.initAndRegister(AbstractBootstrap.java:278)
	at io.netty.bootstrap.AbstractBootstrap.doBind(AbstractBootstrap.java:260)
	at io.netty.bootstrap.AbstractBootstrap.bind(AbstractBootstrap.java:256)
	at io.netty.bootstrap.AbstractBootstrap.bind(AbstractBootstrap.java:231)
	at io.netty.example.echo.EchoServer.run(EchoServer.java:60)
	at io.netty.example.echo.EchoServer.main(EchoServer.java:78)

2. selectionKey = serverSocketChannel.register(selector, 0, serverSocketChannel)

main thread start a boss thread

main@1, prio=5, in group 'main', status: 'RUNNING'
	  at java.lang.Thread.start(Thread.java:703)
	  at io.netty.util.concurrent.SingleThreadEventExecutor.startThread(SingleThreadEventExecutor.java:812)
	  at io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:690)
	  at io.netty.channel.AbstractChannel$AbstractUnsafe.register(AbstractChannel.java:414)
	  at io.netty.channel.SingleThreadEventLoop.register(SingleThreadEventLoop.java:60)
	  at io.netty.channel.MultithreadEventLoopGroup.register(MultithreadEventLoopGroup.java:69)
	  at io.netty.bootstrap.AbstractBootstrap.initAndRegister(AbstractBootstrap.java:287)
	  at io.netty.bootstrap.AbstractBootstrap.doBind(AbstractBootstrap.java:260)
	  at io.netty.bootstrap.AbstractBootstrap.bind(AbstractBootstrap.java:256)
	  at io.netty.bootstrap.AbstractBootstrap.bind(AbstractBootstrap.java:231)
	  at io.netty.example.echo.EchoServer.run(EchoServer.java:60)
	  at io.netty.example.echo.EchoServer.main(EchoServer.java:78)

then main thread put REGISTER task into taskQueue

main@1, prio=5, in group 'main', status: 'RUNNING'
	  at io.netty.util.concurrent.SingleThreadEventExecutor.addTask(SingleThreadEventExecutor.java:292)
	  at io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:691)
	  at io.netty.channel.AbstractChannel$AbstractUnsafe.register(AbstractChannel.java:414)
	  at io.netty.channel.SingleThreadEventLoop.register(SingleThreadEventLoop.java:60)
	  at io.netty.channel.MultithreadEventLoopGroup.register(MultithreadEventLoopGroup.java:69)
	  at io.netty.bootstrap.AbstractBootstrap.initAndRegister(AbstractBootstrap.java:287)
	  at io.netty.bootstrap.AbstractBootstrap.doBind(AbstractBootstrap.java:260)
	  at io.netty.bootstrap.AbstractBootstrap.bind(AbstractBootstrap.java:256)
	  at io.netty.bootstrap.AbstractBootstrap.bind(AbstractBootstrap.java:231)
	  at io.netty.example.echo.EchoServer.run(EchoServer.java:60)
	  at io.netty.example.echo.EchoServer.main(EchoServer.java:78)

boss thread poll it and do the real register

        at io.netty.channel.nio.AbstractNioChannel.doRegister(AbstractNioChannel.java:282)
	at io.netty.channel.AbstractChannel$AbstractUnsafe.register0(AbstractChannel.java:438)
	at io.netty.channel.AbstractChannel$AbstractUnsafe.access$100(AbstractChannel.java:373)
	at io.netty.channel.AbstractChannel$AbstractUnsafe$1.run(AbstractChannel.java:417)
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:354)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:349)
	at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:101)
	at java.lang.Thread.run(Thread.java:744)

3. serverSocketChannel.socket().bind(new InetSocketAddress(port))

	at io.netty.channel.socket.nio.NioServerSocketChannel.doBind(NioServerSocketChannel.java:102)
	at io.netty.channel.AbstractChannel$AbstractUnsafe.bind(AbstractChannel.java:478)
	at io.netty.channel.DefaultChannelPipeline$HeadHandler.bind(DefaultChannelPipeline.java:1000)
	at io.netty.channel.DefaultChannelHandlerContext.invokeBind(DefaultChannelHandlerContext.java:456)
	at io.netty.channel.DefaultChannelHandlerContext.bind(DefaultChannelHandlerContext.java:441)
	at io.netty.channel.ChannelDuplexHandler.bind(ChannelDuplexHandler.java:38)
	at io.netty.handler.logging.LoggingHandler.bind(LoggingHandler.java:254)
	at io.netty.channel.DefaultChannelHandlerContext.invokeBind(DefaultChannelHandlerContext.java:456)
	at io.netty.channel.DefaultChannelHandlerContext.bind(DefaultChannelHandlerContext.java:441)
	at io.netty.channel.DefaultChannelPipeline.bind(DefaultChannelPipeline.java:842)
	at io.netty.channel.AbstractChannel.bind(AbstractChannel.java:193)
	at io.netty.bootstrap.AbstractBootstrap$2.run(AbstractBootstrap.java:321)
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:354)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:348)
	at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:101)
	at java.lang.Thread.run(Thread.java:744)

this runnable task is from taskQueue

main@1, prio=5, in group 'main', status: 'RUNNING'
	  at io.netty.util.concurrent.SingleThreadEventExecutor.addTask(SingleThreadEventExecutor.java:292)
	  at io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:691)
	  at io.netty.util.concurrent.DefaultPromise.notifyListener(DefaultPromise.java:607)
	  at io.netty.util.concurrent.DefaultPromise.addListener(DefaultPromise.java:123)
	  at io.netty.channel.DefaultChannelPromise.addListener(DefaultChannelPromise.java:93)
	  at io.netty.channel.DefaultChannelPromise.addListener(DefaultChannelPromise.java:28)
	  at io.netty.bootstrap.AbstractBootstrap.doBind(AbstractBootstrap.java:266)
	  at io.netty.bootstrap.AbstractBootstrap.bind(AbstractBootstrap.java:256)
	  at io.netty.bootstrap.AbstractBootstrap.bind(AbstractBootstrap.java:231)
	  at io.netty.example.echo.EchoServer.run(EchoServer.java:60)
	  at io.netty.example.echo.EchoServer.main(EchoServer.java:78)
nioEventLoopGroup-2-1@1476, prio=10, in group 'main', status: 'RUNNING'
	  at io.netty.util.concurrent.SingleThreadEventExecutor.addTask(SingleThreadEventExecutor.java:292)
	  at io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:688)
	  at io.netty.channel.AbstractChannel$AbstractUnsafe.invokeLater(AbstractChannel.java:724)
	  at io.netty.channel.AbstractChannel$AbstractUnsafe.bind(AbstractChannel.java:485)
	  at io.netty.channel.DefaultChannelPipeline$HeadHandler.bind(DefaultChannelPipeline.java:1000)
	  at io.netty.channel.DefaultChannelHandlerContext.invokeBind(DefaultChannelHandlerContext.java:456)
	  at io.netty.channel.DefaultChannelHandlerContext.bind(DefaultChannelHandlerContext.java:441)
	  at io.netty.channel.ChannelDuplexHandler.bind(ChannelDuplexHandler.java:38)
	  at io.netty.handler.logging.LoggingHandler.bind(LoggingHandler.java:254)
	  at io.netty.channel.DefaultChannelHandlerContext.invokeBind(DefaultChannelHandlerContext.java:456)
	  at io.netty.channel.DefaultChannelHandlerContext.bind(DefaultChannelHandlerContext.java:441)
	  at io.netty.channel.DefaultChannelPipeline.bind(DefaultChannelPipeline.java:842)
	  at io.netty.channel.AbstractChannel.bind(AbstractChannel.java:193)
	  at io.netty.bootstrap.AbstractBootstrap$2.run(AbstractBootstrap.java:321)
	  at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:354)
	  at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:348)
	  at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:101)
	  at java.lang.Thread.run(Thread.java:744)

4. [RE-REGISTER] selectionKey.interestOps(selectionKey.interestops() | SelectionKey.OP_ACCEPT)

	at io.netty.channel.nio.AbstractNioChannel.doBeginRead(AbstractNioChannel.java:309)
	at io.netty.channel.AbstractChannel$AbstractUnsafe.beginRead(AbstractChannel.java:613)
	at io.netty.channel.DefaultChannelPipeline$HeadHandler.read(DefaultChannelPipeline.java:1028)
	at io.netty.channel.DefaultChannelHandlerContext.invokeRead(DefaultChannelHandlerContext.java:618)
	at io.netty.channel.DefaultChannelHandlerContext.read(DefaultChannelHandlerContext.java:599)
	at io.netty.channel.DefaultChannelHandlerContext.read(DefaultChannelHandlerContext.java:28)
	at io.netty.channel.ChannelDuplexHandler.read(ChannelDuplexHandler.java:95)
	at io.netty.channel.DefaultChannelHandlerContext.invokeRead(DefaultChannelHandlerContext.java:618)
	at io.netty.channel.DefaultChannelHandlerContext.read(DefaultChannelHandlerContext.java:599)
	at io.netty.channel.DefaultChannelPipeline.read(DefaultChannelPipeline.java:872)
	at io.netty.channel.AbstractChannel.read(AbstractChannel.java:223)
	at io.netty.channel.DefaultChannelPipeline.fireChannelActive(DefaultChannelPipeline.java:759)
	at io.netty.channel.AbstractChannel$AbstractUnsafe$2.run(AbstractChannel.java:488)
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:354)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:348)
	at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:101)
	at java.lang.Thread.run(Thread.java:744)

Service Clients

1. SocketChannel socketChannel = ServerSocketChannel.accpet()

boss thread loop

nioEventLoopGroup-2-1@1476, prio=10, in group 'main', status: 'RUNNING'
	  at io.netty.channel.socket.nio.NioServerSocketChannel.doReadMessages(NioServerSocketChannel.java:112)
	  at io.netty.channel.nio.AbstractNioMessageChannel$NioMessageUnsafe.read(AbstractNioMessageChannel.java:71)
	  at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:478)
	  at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:447)
	  at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:341)
	  at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:101)
	  at java.lang.Thread.run(Thread.java:744)

boss thread fire a read event after accepted a client. ServerBootstrapAcceptor handle it , creating a new worker thread

nioEventLoopGroup-2-1@1252, prio=10, in group 'main', status: 'RUNNING'
	  at io.netty.util.concurrent.SingleThreadEventExecutor.startThread(SingleThreadEventExecutor.java:806)
	  at io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:690)
	  at io.netty.channel.AbstractChannel$AbstractUnsafe.register(AbstractChannel.java:414)
	  at io.netty.channel.SingleThreadEventLoop.register(SingleThreadEventLoop.java:60)
	  at io.netty.channel.SingleThreadEventLoop.register(SingleThreadEventLoop.java:48)
	  at io.netty.channel.MultithreadEventLoopGroup.register(MultithreadEventLoopGroup.java:64)
	  at io.netty.bootstrap.ServerBootstrap$ServerBootstrapAcceptor.channelRead(ServerBootstrap.java:249)
	  at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337)
	  at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323)
	  at io.netty.handler.logging.LoggingHandler.channelRead(LoggingHandler.java:297)
	  at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337)
	  at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323)
	  at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785)
	  at io.netty.channel.nio.AbstractNioMessageChannel$NioMessageUnsafe.read(AbstractNioMessageChannel.java:90)
	  at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:478)
	  at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:447)
	  at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:341)
	  at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:101)
	  at java.lang.Thread.run(Thread.java:744)

2. selectionKey = socketChannel.register(selector, 0, socketChannel)

boss thread put the task into taskQueue, worker thread poll the task

nioEventLoopGroup-2-1@1476, prio=10, in group 'main', status: 'RUNNING'
	  at io.netty.util.concurrent.SingleThreadEventExecutor.addTask(SingleThreadEventExecutor.java:292)
	  at io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:691)
	  at io.netty.channel.AbstractChannel$AbstractUnsafe.register(AbstractChannel.java:414)
	  at io.netty.channel.SingleThreadEventLoop.register(SingleThreadEventLoop.java:60)
	  at io.netty.channel.SingleThreadEventLoop.register(SingleThreadEventLoop.java:48)
	  at io.netty.channel.MultithreadEventLoopGroup.register(MultithreadEventLoopGroup.java:64)
	  at io.netty.bootstrap.ServerBootstrap$ServerBootstrapAcceptor.channelRead(ServerBootstrap.java:249)
	  at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337)
	  at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323)
	  at io.netty.handler.logging.LoggingHandler.channelRead(LoggingHandler.java:297)
	  at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337)
	  at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323)
	  at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785)
	  at io.netty.channel.nio.AbstractNioMessageChannel$NioMessageUnsafe.read(AbstractNioMessageChannel.java:90)
	  at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:478)
	  at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:447)
	  at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:341)
	  at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:101)
	  at java.lang.Thread.run(Thread.java:744)

worker thread poll the task, and do the real register

nioEventLoopGroup-3-1@1751, prio=10, in group 'main', status: 'RUNNING'
	  at java.nio.channels.spi.AbstractSelectableChannel.register(AbstractSelectableChannel.java:193)
	  at io.netty.channel.nio.AbstractNioChannel.doRegister(AbstractNioChannel.java:285)
	  at io.netty.channel.AbstractChannel$AbstractUnsafe.register0(AbstractChannel.java:438)
	  at io.netty.channel.AbstractChannel$AbstractUnsafe.access$100(AbstractChannel.java:373)
	  at io.netty.channel.AbstractChannel$AbstractUnsafe$1.run(AbstractChannel.java:417)
	  at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:354)
	  at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:348)
	  at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:101)
	  at java.lang.Thread.run(Thread.java:744)

3. [RE-REGISTER] selectionKey.interestOps(selectionKey.interestops() | SelectionKey.OP_READ)

nioEventLoopGroup-3-1@1751, prio=10, in group 'main', status: 'RUNNING'
	  at io.netty.channel.nio.AbstractNioChannel.doBeginRead(AbstractNioChannel.java:320)
	  at io.netty.channel.AbstractChannel$AbstractUnsafe.beginRead(AbstractChannel.java:613)
	  at io.netty.channel.DefaultChannelPipeline$HeadHandler.read(DefaultChannelPipeline.java:1028)
	  at io.netty.channel.DefaultChannelHandlerContext.invokeRead(DefaultChannelHandlerContext.java:618)
	  at io.netty.channel.DefaultChannelHandlerContext.read(DefaultChannelHandlerContext.java:599)
	  at io.netty.channel.DefaultChannelPipeline.read(DefaultChannelPipeline.java:872)
	  at io.netty.channel.AbstractChannel.read(AbstractChannel.java:223)
	  at io.netty.channel.DefaultChannelPipeline.fireChannelActive(DefaultChannelPipeline.java:759)
	  at io.netty.channel.AbstractChannel$AbstractUnsafe.register0(AbstractChannel.java:443)
	  at io.netty.channel.AbstractChannel$AbstractUnsafe.access$100(AbstractChannel.java:373)
	  at io.netty.channel.AbstractChannel$AbstractUnsafe$1.run(AbstractChannel.java:417)
	  at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:354)
	  at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:348)
	  at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:101)
	  at java.lang.Thread.run(Thread.java:744)

4. socketChannel.read(ByteBuffer byteBuffer)

nioEventLoopGroup-3-1@1751, prio=10, in group 'main', status: 'RUNNING'
	  at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:291)
	  at io.netty.buffer.UnpooledUnsafeDirectByteBuf.setBytes(UnpooledUnsafeDirectByteBuf.java:401)
	  at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:869)
	  at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:208)
	  at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:87)
	  at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:478)
	  at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:447)
	  at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:341)
	  at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:101)
	  at java.lang.Thread.run(Thread.java:744)

After that, fire an event to worker io handler

nioEventLoopGroup-3-1@1751, prio=10, in group 'main', status: 'RUNNING'
	  at io.netty.example.echo.EchoServerHandler.channelRead(EchoServerHandler.java:36)
	  at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337)
	  at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323)
	  at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785)
	  at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:100)
	  at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:478)
	  at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:447)
	  at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:341)
	  at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:101)
	  at java.lang.Thread.run(Thread.java:744)

####5. socketChannel.write(ByteBuffer byteBuffer) ####

nioEventLoopGroup-3-1@1751, prio=10, in group 'main', status: 'RUNNING'
	  at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:3xx)
	  at io.netty.buffer.UnpooledUnsafeDirectByteBuf.getBytes(UnpooledUnsafeDirectByteBuf.java:381)
	  at io.netty.buffer.AbstractByteBuf.readBytes(AbstractByteBuf.java:717)
	  at io.netty.channel.socket.nio.NioSocketChannel.doWriteBytes(NioSocketChannel.java:214)
	  at io.netty.channel.nio.AbstractNioByteChannel.doWrite(AbstractNioByteChannel.java:178)
	  at io.netty.channel.socket.nio.NioSocketChannel.doWrite(NioSocketChannel.java:231)
	  at io.netty.channel.AbstractChannel$AbstractUnsafe.flush0(AbstractChannel.java:680)
	  at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.flush0(AbstractNioChannel.java:260)
	  at io.netty.channel.AbstractChannel$AbstractUnsafe.flush(AbstractChannel.java:649)
	  at io.netty.channel.DefaultChannelPipeline$HeadHandler.flush(DefaultChannelPipeline.java:1038)
	  at io.netty.channel.DefaultChannelHandlerContext.invokeFlush(DefaultChannelHandlerContext.java:674)
	  at io.netty.channel.DefaultChannelHandlerContext.flush(DefaultChannelHandlerContext.java:655)
	  at io.netty.example.echo.EchoServerHandler.channelReadComplete(EchoServerHandler.java:41)
	  at io.netty.channel.DefaultChannelHandlerContext.invokeChannelReadComplete(DefaultChannelHandlerContext.java:366)
	  at io.netty.channel.DefaultChannelHandlerContext.fireChannelReadComplete(DefaultChannelHandlerContext.java:348)
	  at io.netty.channel.DefaultChannelPipeline.fireChannelReadComplete(DefaultChannelPipeline.java:791)
	  at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:118)
	  at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:478)
	  at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:447)
	  at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:341)
	  at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:101)
	  at java.lang.Thread.run(Thread.java:744)

Client Side

IO 线程模型的思考

在netty4中, 一个SocketChannel应该对应一组pipeline chain. 如果pipeline chain里面某个handler逻辑比较耗时, 那最好把这种耗时的工作到到线程池里做。这叫做io任务与user任务分离。但这种分离会带来额外的context switch. 理想的情况是一个线程把io和user任务全部做完. 但user任务耜时长短不一, 使用这种方法会使某些user任务耗时长的线程一直很慢. 如果像netty4那样一个线程对应一个channel, 那么这个channel就一直很慢.

如果一个channel对应的这组 upstream io->user->down stream io 整个pipeline比较慢. 可以不可以让一个channel对应多组pipeline? 这样会造成GC问题?

Grizzly的Leader-Follower IO策略(见 https://grizzly.java.net/iostrategies.html), 就是upstream io->user->down stream io 全由一个线程处理, Channel如果还有io事件就转给别的线程处理。这样有效地减少了context switch, 但如果每次转的时候都需要实例化一组pipeline, 会带来GC问题。如果Channel共享pipeline, 用来减少GC, 这时候会有数据共享问题. 谁也无法保证用户不在某个Handler里存一些状态. 相反, 这就是netty4设计成一个Channel对应一组pipeline的原因.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment