Netty系列之:NIO和netty详解( 二 )

ServerBootstrap可以接受一个EventLoopGroup或者两个EventLoopGroup,EventLoopGroup被用来处理所有的event和IO,对于ServerBootstrap来说,可以有两个EventLoopGroup,对于Bootstrap来说只有一个EventLoopGroup 。两个EventLoopGroup表示acceptor group和worker group 。
EventLoopGroup只是一个接口,我们常用的一个实现就是NioEventLoopGroup,如下所示是一个常用的netty服务器端代码:
EventLoopGroup bossGroup = new NioEventLoopGroup();EventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap b = new ServerBootstrap();b.group(bossGroup, workerGroup).channel(NIOServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {@Overridepublic void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(new FirstServerHandler());}}).option(ChannelOption.SO_BACKLOG, 128).childOption(ChannelOption.SO_KEEPALIVE, true);// 绑定端口并开始接收连接ChannelFuture f = b.bind(port).sync();// 等待server socket关闭f.channel().closeFuture().sync();这里和NIO相关的有两个类,分别是NioEventLoopGroup和NioServerSocketChannel,事实上在他们的底层还有两个类似的类分别叫做NioEventLoop和NioSocketChannel,接下来我们分别讲解一些他们的底层实现和逻辑关系 。
NioEventLoopGroupNioEventLoopGroup和DefaultEventLoopGroup一样都是继承自MultithreadEventLoopGroup:
public class NioEventLoopGroup extends MultithreadEventLoopGroup 他们的不同之处在于newChild方法的不同,newChild用来构建Group中的实际对象,NioEventLoopGroup来说,newChild返回的是一个NioEventLoop对象,先来看下NioEventLoopGroup的newChild方法:
protected EventLoop newChild(Executor executor, Object... args) throws Exception {SelectorProvider selectorProvider = (SelectorProvider) args[0];SelectStrategyFactory selectStrategyFactory = (SelectStrategyFactory) args[1];RejectedExecutionHandler rejectedExecutionHandler = (RejectedExecutionHandler) args[2];EventLoopTaskQueueFactory taskQueueFactory = null;EventLoopTaskQueueFactory tailTaskQueueFactory = null;int argsLength = args.length;if (argsLength > 3) {taskQueueFactory = (EventLoopTaskQueueFactory) args[3];}if (argsLength > 4) {tailTaskQueueFactory = (EventLoopTaskQueueFactory) args[4];}return new NioEventLoop(this, executor, selectorProvider,selectStrategyFactory.newSelectStrategy(),rejectedExecutionHandler, taskQueueFactory, tailTaskQueueFactory);}这个newChild方法除了固定的executor参数之外,还可以根据NioEventLoopGroup的构造函数传入的参数来实现更多的功能 。
这里参数中传入了SelectorProvider、SelectStrategyFactory、RejectedExecutionHandler、taskQueueFactory和tailTaskQueueFactory这几个参数,其中后面的两个EventLoopTaskQueueFactory并不是必须的 。
最后所有的参数都会传递给NioEventLoop的构造函数用来构造出一个新的NioEventLoop 。
在详细讲解NioEventLoop之前,我们来研读一下传入的这几个参数类型的实际作用 。
SelectorProvider
SelectorProvider是JDK中的类,它提供了一个静态的provider()方法可以从Property或者ServiceLoader中加载对应的SelectorProvider类并实例化 。
另外还提供了openDatagramChannel、openPipe、openSelector、openServerSocketChannel和openSocketChannel等实用的NIO操作方法 。
【Netty系列之:NIO和netty详解】SelectStrategyFactory
SelectStrategyFactory是一个接口,里面只定义了一个方法,用来返回SelectStrategy:
public interface SelectStrategyFactory {SelectStrategy newSelectStrategy();}什么是SelectStrategy呢?
先看下SelectStrategy中定义了哪些Strategy:
int SELECT = -1;int CONTINUE = -2;int BUSY_WAIT = -3;SelectStrategy中定义了3个strategy,分别是SELECT、CONTINUE和BUSY_WAIT 。
我们知道一般情况下,在NIO中select操作本身是一个阻塞操作,也就是block操作,这个操作对应的strategy是SELECT,也就是select block状态 。
如果我们想跳过这个block,重新进入下一个event loop,那么对应的strategy就是CONTINUE 。
BUSY_WAIT是一个特殊的strategy,是指IO 循环轮询新事件而不阻塞,这个strategy只有在epoll模式下才支持,NIO和Kqueue模式并不支持这个strategy 。
RejectedExecutionHandler
RejectedExecutionHandler是netty自己的类,和
java.util.concurrent.RejectedExecutionHandler类似,但是是特别针对SingleThreadEventExecutor来说的 。这个接口定义了一个rejected方法,用来表示因为SingleThreadEventExecutor容量限制导致的任务添加失败而被拒绝的情况:
void rejected(Runnable task, SingleThreadEventExecutor executor);EventLoopTaskQueueFactory
EventLoopTaskQueueFactory是一个接口,用来创建存储提交给EventLoop的taskQueue:


推荐阅读