標籤:netty 源碼
周末簡單看了下netty5的源碼,只看懂了個大概,記錄下成果,方便下次再看的時候回憶.
上服務端代碼:
public void run() throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast( new ObjectEncoder(), new ObjectDecoder(ClassResolvers.cacheDisabled(null)), new ObjectEchoServerHandler(), new MyServerHandler()); } }); // Bind and start to accept incoming connections. b.bind(port).sync().channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } }EventLoopGroup類有4個相關類容易搞混:
EventExecutor EventExecutorGroup, EventLoop, EventLoopGroup,
EventExecutor 繼承自EventExecutorGroup , EventExecutorGroup 繼承自ScheduledExecutorService(java內建的線程池服務類), EventExecutor 是一個特殊的EventExecutorGroup,提供了檢測一個線程是否在eventLoop中被執行之類的方法.
EventLoopGroup 也繼承自EventExecutorGroup, 並提供EventLoop的產生方法next(),
EventLoop繼承自EventLoopGroup, EventLoop的英文解釋是:Will handle all the I/O-Operations for a Channel once it was registered,即處理channel的io操作,
ServerBootstrap 類主要用於建立NioServerSocketChannel類,並初始化. 主要看它的 bind()方法,如下:
private ChannelFuture doBind(final SocketAddress localAddress) { final ChannelFuture regFuture = initAndRegister(); final Channel channel = regFuture.channel(); if (regFuture.cause() != null) { return regFuture; } final ChannelPromise promise; if (regFuture.isDone()) { promise = channel.newPromise(); doBind0(regFuture, channel, localAddress, promise); } else { // Registration future is almost always fulfilled already, but just in case it's not. promise = new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE); regFuture.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { doBind0(regFuture, channel, localAddress, promise); } }); } return promise; }
上面代碼主要是兩個過程,一個註冊生產 channel,第二個是將channel綁定到指定連接埠,
建立並註冊方法如下:
final ChannelFuture initAndRegister() { Channel channel; try { channel = createChannel(); } catch (Throwable t) { return VoidChannel.INSTANCE.newFailedFuture(t); } try { init(channel); } catch (Throwable t) { channel.unsafe().closeForcibly(); return channel.newFailedFuture(t); } ChannelPromise regFuture = channel.newPromise(); channel.<span style="color:#ff0000;">unsafe().register(regFuture);</span> if (regFuture.cause() != null) { if (channel.isRegistered()) { channel.close(); } else { channel.unsafe().closeForcibly(); } } // If we are here and the promise is not failed, it's one of the following cases: // 1) If we attempted registration from the event loop, the registration has been completed at this point. // i.e. It's safe to attempt bind() or connect() now beause the channel has been registered. // 2) If we attempted registration from the other thread, the registration request has been successfully // added to the event loop's task queue for later execution. // i.e. It's safe to attempt bind() or connect() now: // because bind() or connect() will be executed *after* the scheduled registration task is executed // because register(), bind(), and connect() are all bound to the same thread. return regFuture; }
上面標紅的代碼,註冊操作實際由unsafe這個工具類來完成, 主要也是向ServerSocketChannel 這個類進行註冊,和java NIO註冊類似.源碼如下:
protected void doRegister() throws Exception { boolean selected = false; for (;;) { try { selectionKey = javaChannel().register(eventLoop().selector, 0, this); return; } catch (CancelledKeyException e) { if (!selected) { // Force the Selector to select now as the "canceled" SelectionKey may still be // cached and not removed because no Select.select(..) operation was called yet. eventLoop().selectNow(); selected = true; } else { // We forced a select operation on the selector before but the SelectionKey is still cached // for whatever reason. JDK bug ? throw e; } } } }
channel 類與 unsafe類區別: channel 類主要給基於netty開發的程式員進行讀寫操作,但是netty內部跟 NIo的IO操作主要通過unsafe這個類進行.
通過分析channel的類繼承關係會發現, channel部分抽象類別內部同時也包含相應unsafe類的實現, 是NioServerSocketChannel類的繼承結構.
AbstractNioMessageChannel 到 AbstractChannel 類內部都有 unsafe內部類作為實際操作IO類.