Netty启动过程源码分析

对Netty一些分析,主要是启动过程、线程模型、客户端和服务端TCP连接建立 

netty作为一个优秀的网络通信框架,应该大部分人都接触过,之前看了mina,话说是同一个作者,里面的设计和思想还是比较接近的。不过要涉及到里面原理,可能就不是那么清楚。下面我将自己在工作中接触过,和自己看源码的一些理解记录下来。注:只是个人目前的一个理解程度,这篇文章会比较长,基本都是文字和贴的源码,但如果你读完,对netty多少会有些认识,可能有些地方写的不对,忘指出。

 

主从模型的启动过程

如果一开始看源码,应该是一脸蒙蔽,毕竟这么庞大的东西。首先我是通过几个重要的组件,看里面具体的实现,然后看netty.bind()怎么启动的,看到bind肯定说的是服务端了,客户端应该差不多了,还没这么负载。

学习的时候,如果带着问题去看,应该就比较容易一些。

为什么说Netty是NIO

1:NIO既同步非阻塞,为什么是非阻塞的呢,netty用到多路复用技术。

2:那netty实现NIO主要有哪些组件呢。

//1:这个我觉得是最核心的一个了,看到eventLoop 很容易会想到,这是一个线程池。确实,没错,netty的线程池,是在java的ExecutorService上进行了封装
NioEventLoopGroup();
//2:服务器引导类,这个没什么说的,就是用来引导启动的
ServerBootstrap
//3:channel,这个最终是一个channel接口,这里会设计到netty的线程模型
NioServerSocketChannel
//4:对channel中进行注册
ChannelInitializer

 

3:上面这几个是我自己对netty印象最深的几个组件,当然也是最重要的,下面下看一段简单的代码,然后开始看源码,了解整个的启动过程。

 public void bind(int port) {
        final EventLoopGroup bossGroup = new NioEventLoopGroup();
        final EventLoopGroup workGroup = new NioEventLoopGroup();
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        try {
            serverBootstrap.group(bossGroup, workGroup)
                .channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 1023)
                .childOption(ChannelOption.TCP_NODELAY, true)
                .childOption(ChannelOption.SO_RCVBUF,1024 * 32)
                .childOption(ChannelOption.SO_SNDBUF, 1024 * 32)
                .childOption(ChannelOption.SO_KEEPALIVE,true)
                .childOption(ChannelOption.WRITE_BUFFER_WATER_MARK,new                                          WriteBufferWaterMark(0,128 * 1023))
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        ChannelPipeline pipeline = socketChannel.pipeline();
                        pipeline.addLast(new IdleStateHandler(0, 0, 300));
                    }
                });
​
            ChannelFuture future = serverBootstrap.bind(port).sync();
            logger.debug("websocket port: {}",3322);
            future.channel().closeFuture().sync();  // TODO
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }

这是主从模型,boss是用来对客户端的请求进行分发,work是真正用来工作的线程池。每个线程池数量,看里面源码就能知道,如果自己不定义的话,默认是CPU合数的两倍。**但是不太懂,明明启动的时候,bossGroup就只分配一次serverChannel,那为什么项目中不设置一一个线程呢,难道后面还会再分配,但不清楚[参考](https://blog.csdn.net/u013076044/article/details/103933774)**

在创建服务端的时候实例化了 2 个 EventLoopGroup,1 个 EventLoopGroup 实际就是一个 EventLoop 线程组,负责管理 EventLoop 的申请和释放。

bossGroup 线程组实际就是 Acceptor 线程池,负责处理客户端的 TCP 连接请求,如果系统只有一个服务端端口需要监听,则建议 bossGroup 线程组线程数设置为 1。

workerGroup 是真正负责 I/O 读写操作的线程组,通过 ServerBootstrap 的 group 方法进行设置,用于后续的 Channel 绑定。

NIOEventLoopGroup后面会继承MultithreadEventExecutorGroup,这个的构造方法有对里面线程进行初始化。

​
       if (executor == null) {
            executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
        }
        
        children = new EventExecutor[nThreads];
​
        for (int i = 0; i < nThreads; i ++) {
            boolean success = false;
            try {
                //这个构造,主要看这里,线程的初始化就好。最后反复的实例SingleThreadEventExecutor,
                //这个我之前看过一次源码,里面有个takeTask()方法,用来获取当前队列中的任务,并实现了阻                   塞等待,周期等功能。
                children[i] = newChild(executor, args);
                success = true;
            } catch (Exception e) {
            } finally {
             //这里面应该就是一些监听触发,netty很多逻辑,会通过监听和回调去触发。
            }
        }
​
        chooser = chooserFactory.newChooser(children);
​
        final FutureListener<Object> terminationListener = new FutureListener<Object>() {
            @Override
            public void operationComplete(Future<Object> future) throws Exception {
                if (terminatedChildren.incrementAndGet() == children.length) {
                    te
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值