01Netty启动流程

Netty笔记

NioEventLoopGroup

  • int nThreads 线程数

  • Executor executor 默认为null

  • SelectorProvider selectorProvider 默认SelectorProvider.provider() jdk

  • SelectStrategyFactory selectStrategyFactory 默认选择策略 有任务是先执行任务

  • RejectedExecutionHandler 拒绝策略默认抛异常

  • nThreads==0–>使用默认线程数(cpu可用核心数*2)

  • 新增参数DefaultEventExecutorChooserFactory EventExecutor选择策略

    • 如果线程数是2^n next-->idx.getAndIncrement() & executors.length - 1
    • 不是2^n –>Math.abs(idx.getAndIncrement() % executors.length)
  • nThreads<=0 抛异常

  • executor==null new ThreadPerTaskExecutor(newDefaultThreadFactory());

    • ThreadPerTaskExecutor Executor的实现
    • 保存了ThreadFactory
    • execute方法就是开启一个线程
    • 开启的线程为FastThreadLocalRunnable,对Runnable的封装(区别在于结束时清空FastThreadLocal)
    • 定义了Thread的名称
  • EventExecutor[] children = new EventExecutor[nThreads]

    • NioEventLoop
    • parent NioEventLoopGroup
    • executor 传参
    • taskQueue && tailTaskQueue MpscQueue
    • rejectedExecutionHandler 传参
    • selectStrategy 传参
    • selector unwrappedSelector SeletorProvider.openSelector 替换过selectedKeys publicSelectedKeys

bind

  • 反射实例化NioServerSocketChannel
    • SelectorProvider.provider().openServerSocketChannel()
    • 生成id
    • 初始化unsafe
    • 初始化pipeline
    • 保存感兴趣事件SelectionKey.OP_ACCEPT
    • ch.configureBlocking(false);设置非阻塞
    • config = new NioServerSocketChannelConfig
  • setChannelOptions 设置Options
  • setAttributes 设置Attributes
  • Pipeline.addLast
    • serverbootstrap.channel()
    • //添加到任务队列
    • 因为目前还没有注册,所以不会回调ChannelAdded,也不会解析initChannel
    • 也不会执行到这行代码开启线程
    • ch.eventLoop().execute( pipeline.addLast(new ServerBootstrapAcceptor))

register

  • 获取到EventLoop

  • 判断该线程是否开启,或者说当前线程是不是EventLoop线程

  • 如果不是 eventLoop.execute(register0())

  • 该execute实际上是将Runnable包装成task放到taskQueue中

  • 同时判断有没有开启线程,没有就开启线程

  • 调用传进来的executor 开启线程

  • 该线程会执行NioEventLoop中的run()

  • register0()

    • 使用java原生channel注册,设置感兴趣事件为0(没有),设置附加对象为当前对象AbstractNioChannel
    • selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this);
    • 回调HandlerAdded(添加到队列)
    • 回调channelRegistered(添加到队列)
    • 回调channelActive&注册感兴趣事件(添加到队列)
  • run()

    • 如果有任务就先执行任务
    • 如果有延时任务就select(time),超时select
    • 没有的话就select(Long.MAX_VALUE)
    • 接下来执行到循环中的代码要么就是有任务,要么就是有感兴趣事件发生,要么就是jdkbug
    • 如果是感兴趣事件发生就轮询获取到SelectionKey 拿到附加对象AbstractNioChannel-》可以拿到unsafe->写数据等
      • ACCEPT
      • ServerSocketChannel.accept()获取到SocketChannel,将其封装成NioSocketChannel
      • 回调handler.channelRead()
      • 会在ServerBootstrapt.ServerBootstrapAcceptor中传递给chiledHandler
        • ServerBootstrapAcceptor中channelRead()
        • child.pipeline().addLast(childHandler);
        • setChannelOptions(child, childOptions, logger);
        • setAttributes(child, childAttrs);
        • childGroup.register(child)
  • bind

    • 调用到unsafe.bind->NioSersocketChannel.dobind()
    • 任务队列 unsafe
    • serverSocketChannel.bind
    • config.getBacklog的值为等待accept的channel数量
    • javaChannel().bind(localAddress, config.getBacklog());

01Netty启动流程
https://jiajun.xyz/2020/10/10/java/netty/01Netty启动流程/
作者
Lambda
发布于
2020年10月10日
许可协议