先看个流程图
服务端启动做了哪些事情
//创建EventLoopGroup,初始化所有的EventLoop,初始化线程工具 EventLoopGroup bossEventLoopGroup = new NioEventLoopGroup(2); executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());//创建channel,初始化channel的pipelinechannel = channelFactory.newChannel();//为channel的pipeline绑定ChannelHandler----使用EventLoop(与channel关联的)异步执行 p.addLast(new ChannelInitializer() { @Override public void initChannel(final Channel ch) throws Exception { final ChannelPipeline pipeline = ch.pipeline(); ChannelHandler handler = config.handler(); if (handler != null) { pipeline.addLast(handler); } ch.eventLoop().execute(new Runnable() { @Override public void run() { pipeline.addLast(new ServerBootstrapAcceptor( ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs)); } }); } });//选择EventLoopGroup的一个EventLoop的selector,将channel注册上去ChannelFuture regFuture = config().group().register(channel);//将channel注册到一个绑定的EventLoop的selector----使用EventLoop(与channel关联的)异步执行eventLoop.execute(new Runnable() { @Override public void run() { register0(promise); }});//绑定Channel到指定的端口-----使用EventLoop(与channel关联的)异步执行private static void doBind0( final ChannelFuture regFuture, final Channel channel, final SocketAddress localAddress, final ChannelPromise promise) { channel.eventLoop().execute(new Runnable() { @Override public void run() { if (regFuture.isSuccess()) { channel.bind(localAddress, promise).addListener(ChannelFutureListener.CLOSE_ON_FAILURE); } else { promise.setFailure(regFuture.cause()); } } }); } 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
EventLoop的execute方法
//EventLoop的execute方法public void execute(Runnable task) { if (task == null) { throw new NullPointerException("task"); } //判断当前EventLoop持有线程有没有启动 boolean inEventLoop = inEventLoop(); //启动过,直接添加到任务队列 if (inEventLoop) { addTask(task); } else { //没启动,先启动EventLoop唯一的线程,然后添加任务 startThread(); addTask(task); if (isShutdown() && removeTask(task)) { reject(); } } if (!addTaskWakesUp && wakesUpForTask(task)) { wakeup(inEventLoop); }}123456789101112131415161718192021222324
EventLoop的轮训方法
//轮训处理方法protected void run() { for (;;) { try { switch (selectStrategy.calculateStrategy(selectNowSupplier, hasTasks())) { try { processSelectedKeys(); } finally { final long ioTime = System.nanoTime() - ioStartTime; runAllTasks(ioTime * (100 - ioRatio) / ioRatio); } //省去...... //1.轮训方法会去task队列获取任务//2.channel的pipeline绑定ChannelHandler,会在这里触发回调//3.channel注册到一个绑定的EventLoop的selector,会在这里触发回调 //4.Channel到指定的端口绑定,会在这里触发回调 //5.上面2-4都是初始化异步做的事情,都丢到channel关联的EventLoop去做 123456789101112131415161718
总结
1.启动流程中做的事情还是 创建selector,channel,绑定端口,轮训selector 其实和我们使用jdk nio编写一个网络编程是没本质区别的,只不过是做了组件化 的封装,扩展性更强2.netty的EventLoop其实就像一个有一个线程的线程池,去轮训处理绑定在当前 EventLoop的所有channel的所有提交的任务,EventLoop也有拒绝策略,线程 工厂,任务队列等,只不过没有回收策略,这和他是一个具有NIO编程的强功能性 相关,注定是个长任务,而且也就一个线程,所以没必要