NioEventLoopGroup创建流程
  1. new NioEventLoopGroup(); nThreads=默认CPU核数的两陪】<br /> new ThreadPerTaskExecutor(newDefaultThreadFactory()) 【线程创建器】<br /> 每次执行任务的时候都会创建一个线程实体<br /> NioEventLoop线程命名规则nioEventLoop-1-xx<br /> for( nThreads ){ newChild() } 【创建NioEventLoop】<br /> newChild()--><br /> 保存线程执行器ThreadPerTaskExecutor<br /> PlatformDependent.<Runnable>newMpscQueue()<br /> 创建一个selector<br /> chooserFactory.newChooser(children); 【线程选择器】

Netty 的线程模型是什么?

这个要看我们如何编码;NioEventLoopGroup默认线程数为cpu核心数的两倍
如果用了两个NioEventLoopGroup,且指定工作线程数不为一,则是主从多线程模型;
如果用了两个NioEventLoopGroup,且指定工作线程数为一,则是主从单线程模型
如果用了一个NioEventLoopGroup,且指定线程数不为一,则是多线程模型
如果用了一个NioEventLoopGroup,且指定线程数为一,则是单线程模型

EventLoop与EventLoopGroup 是什么关系?

NioEventLoopGroup是NioEventLoop的组合,用于管理NioEventLoop
EventLoop接口用于处理连接的生命周期中所发生的事件。一个EventLoop在它的生命周期内只和一个Thread绑定。所有由EventLoop处理的I/O事件都将在它专有的Thread上被处理

ServerBootstrap.bind 服务端启动流程

初始化服务端Channel
bind() 【服务端入口】
initAndRegister() 【初始化并注册】
newChannel() 【创建服务器channel】
反射创建服务端channel (NioServerSocketChannel)
newChannel()
provider.openServerSocketChannel()
AbstractNioChannel() 保存了感兴趣的事件
AbstractChannel() 【创建id,unsafe,pipeline】
ch.configureBlocking(false); 【设置非阻塞模式】
socket()
newSocket() 【通过jdk来创建底层jdk channel】
NioServerSocketChannelConfig() 【tcp参数配置】
init() 【初始化服务器channel】
setChannelOptions() attr();
setChildOptions childAttrs();
ChannelPipeline.addLast() 将ChannelInitializer加入pipeline中,此时pipeline中就是head—>ChannelInitializer—>tail
config handler 【配置服务端pipeline】
add ServerBootStrapAcceptor 【添加连接器】
register【注册selector入口】
AbstractChannel.register(channel) 【入口】
AbstractChannel.this.eventLoop = eventLoop; 【绑定线程】
启动主线程
register0() 【实际注册】
doRegister() 【调用jdk底层注册】
invokeHandlerAddedIfNeeded() pipeline中的结构为head—>ChannelInitializer—>NettyTestHendler—>tail(在注册完时会执行handlerAdded方法,而ChannelInitializer的handlerAdded,就是调用initChannel方法再删除ChannelInitializer)pipeline中的结构变为head—>NettyTestHendler—>ServerBootstrapAcceptor—>tail
fireChannelRegistered 【传播事件】
doBind0()
HeadContext.bind() AbstractUnsafe.bind() 【入口】
NioServerSocketChannel.javaChannel().bind() 【jdk底层绑定】
pipeline.fireChannelActive(); 【传播事件】
readIfIsAutoRead() 更新Ops为接受事件
image.png
image.png

Bootstrap.connect 客户端连接流程

客户端pipeline
新接连接入的时候pipeline中就是head—>ChannelInitializer(启动类我们自己编写的)—>tail
pipeline中的结构变为head—>用户自定义的ChannelHandler—>tail

Channel 与 Socket是什么关系?

Socket:网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket,
Channel:是一个链接,它提供了如下的功能。
1:获取当前链接的状态
2:配置当前链接参数
3:进行read,write,connect,bind等通道支持的操作。
4:该Channel关联的ChannelPipeLine处理所有的IO事件和绑定在这个channel的请求

Channel 与 EventLoop是什么关系?

一个Channel在它的生命周期内只注册于一个EventLoop;
一个EventLoop可能会被分配给一个或多个Channel

Channel 与 ChannelPipeline是什么关系?

一个Channel包含了一个ChannelPipeline,而ChannelPipeline中又维护了一个由ChannelHandlerCOntext组成的双向链表,
这个链表的头是HeadContext,链表的尾是TailContext,并且么个ChannelHandlerContext中又关联着一个ChannelHandler;

何时接受客户端请求?

服务端(reactor线程)启动后就可以接收

何时注册接受 Socket 并注册到对应的 EventLoop 管理的 Selector ?

在channel通道创建和初始化完毕后,会通过group.register()方法将channel通道注册到EventLoop线程池中;
从线程池中轮询获取一个线程EventLoop并与之绑定;而EventLoop线程池会绑定一个selector选择器

1.在哪里创建的服务端socket
2.在哪里accept连接?
Netty基础相关问题
1.默认情况下,netty服务端起多少线程,何时启动?
2.netty是如何解决jdk空轮询bug的?
如何使用 Java NIO 搭建简单的客户端与服务端实现网络通讯?
如何使用 Netty 搭建简单的客户端与服务端实现网络通讯?

粘包与半包和分隔符相关问题
什么是粘包与半包问题?
粘包与半包为何会出现?
如何避免粘包与半包问题?
如何使用包定长 FixedLengthFrameDecoder 解决粘包与半包问题?原理是什么?
如何使用包分隔符 DelimiterBasedFrameDecoder 解决粘包与半包问题?原理是什么?
Dubbo 在使用 Netty 作为网络通讯时候是如何避免粘包与半包问题?
Netty框架本身存在粘包半包问题?
什么时候需要考虑粘包与半包问题?

WebSocket 协议开发相关问题
讲讲如何实现 WebSocket 长连接?
讲讲WebSocket 帧结构的理解?浏览器、服务器对 WebSocket 的支持情况如何使用 WebSocket 接收和发送广本信息?
如何使用 WebSocket 接收和发送二进制信息?

Netty源码分析相关问题

服务端如何进行初始化?
客户端如何进行初始化?
何时创建的 DefaultChannelPipeline ?
服务端channel被反射创建时被创建

  1. <br />