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)
- 如果线程数是2^n
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启动流程/