debug方式深入理解netty源码-server端服务启动

本文以debug方式详细解析了Netty服务器端启动的源码流程,从NioEventLoopGroup的初始化,到ServerBootstrap的配置,再到NioServerSocketChannel的注册和绑定端口,展示了Netty如何优雅地处理服务器启动过程。通过理解这些步骤,有助于深入掌握Netty的工作原理。
摘要由CSDN通过智能技术生成

转载请注明来源

前言

Netty是什么,能做什么,业务场景啥的我就不写了,其实实际上是我这半吊子都没有的水平,啥也说不出来,写文章主要是做个笔记,巩固自己这段时间学习netty的心得,并把自己这个时间点对netty的理解写下来。
本章以debug方式跟踪代码,把netty在server端启动这个过程的流程,执行了什么逻辑给展示出来。

正文

   这里选取了一个Time服务器的代码(有兴趣的可以自行去找官方的demo)作为debug演示,代码如下:
    TimeServer.java

    public class TimeServer {
   

    private final int port = 8080;

    public void run() throws InterruptedException {
        /**
        * bossGroup 和 workerGroup是两个独立的Reactor线程池,
        * bossGroup负责客户端请求的accept操作,workerGroup负责处
        * 理I/O相关的读写操作或者处理其它任务     
        */
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .localAddress(new InetSocketAddress(port))
                    .childHandler(new ChannelInitializer<SocketChannel>() {

                        @Override
                        protected void initChannel(SocketChannel ch)
                                throws Exception {
                            ch.pipeline().addLast(new TimeServerHandler());

                        }
                    }).option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true);
            ChannelFuture f = b.bind().sync();
            f.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully().sync();
            workerGroup.shutdownGracefully().sync();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        new TimeServer().run();
    }

}

NioEventLoopGroup

这里从NioEventLoopGroup的初始化开始,NioEventLoopGroup主要负责管理eventLoop的生命周期,eventLoop数量默认为处理器个数的两倍。
debug开始,经过了NioEventLoopGroup的几个内部构造函数,来到了调用父类构造函数的位置:

public NioEventLoopGroup(int nEventLoops, Executor executor, final SelectorProvider selectorProvider) {
        super(nEventLoops, executor, selectorProvider);
    }

跳入父类MultithreadEventLoopGroup构造函数中:
这里写图片描述
虽然还是执行的是父类构造函数,但是我们可以看到这个参数 DEFAULT_EVENT_LOOP_THREADS 即默认的eventLoop个数为8个(本机是4核处理器),正如上面讲的eventLoop数量默认为处理器个数的两倍,继续跳入父类MultithreadEventExecutorGroup构造函数中(MultithreadEventExecutorGroup是核心,管理eventLoop的生命周期),

private MultithreadEventExecutorGroup(int nEventExecutors,
                                          Executor executor,
                                          boolean shutdownExecutor,
                                          Object... args) {
        if (nEventExecutors <= 0) {
            throw new IllegalArgumentException(
                    String.format("nEventExecutors: %d (expected: > 0)", nEventExecutors));
        }

        if (executor == null) {
            executor = newDefaultExecutorService(nEventExecutors);
            shutdownExecutor = true;
        }
        //children:EventExecutor数组,保存eventLoop
        //chooser:从children中选取一个eventLoop的策略
        children = new EventExecutor[nEventExecutors];
        //根据数组的大小,采取不同的策略初始化chooser
        if (isPowerOfTwo(children.length)) {
  //判断是否是2的幂次方
            chooser = new PowerOfTwoEventExecutorChooser();
        } else {
            chooser = new GenericEventExecutorChooser();
        }

        for (int i = 0; i < nEventExecutors; i ++) {
            boolean success = false;
            try {
                //初始化eventExecutor
                children[i] = newChild(executor, args);
                success = true;
            } catch (Exception e) {
                // TODO: Think about if this is a good exception type
                throw new IllegalStateException("failed to create a child event loop", e);
            } finally {
                if (!success) {
                    for (int j = 0; j < i; j ++) {
                        children[j].shutdownGracefully();
                    }

                    for (int j = 0; j < i; j ++) {
                        EventExecutor e = children[j];
                        try {
                            while (!e.isTerminated()) {
                                e.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS);
                            }
                        } catch (InterruptedException interrupted) {
                            // Let the caller handle the interruption.
                            Thread.currentThread().interrupt();
                            break;
                        }
                    }
                }
            }
        }

        final boolean shutdownExecutor0 = shutdownExecutor;
        final Executor executor0 = executor;
        final FutureListener<Object> terminationListener = new FutureListener<Object>() {
            @Override
            public void operationComplete(Future<Object> future) throws Exception {
                if (terminatedChildren.incrementAndGet() == children.length) {
                    terminationFuture.setSuccess(null);
                    if (shutdownExecutor0) {
                        // This cast is correct because shutdownExecutor0 is only try if
                        // executor0 is of type ExecutorService.
                        ((ExecutorService) executor0).shutdown();
                    }
                }
            }
        };

        for (EventExecutor e: children) {
            e.terminationFuture().addListener(terminationListener);
        }

        Set<EventExecutor> childrenSet = new LinkedHashSet<EventExecutor>(children.length);
        Collections.addAll(childrenSet, children);
        readonlyChildren = Collections.unmodifiableSet(childrenSet);
    }

这里我对几个重要的地方都做了相应的注释,方便理解。
程序继续执行,在children[i] = newChild(executor, args);处进入newChild方法,这里实际上是跳入了子类NioEven

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值