[文档修改](master): Netty文档

更新2
master
土豆兄弟 2 years ago
parent 364fb07790
commit 86e89ffabb

@ -14,13 +14,80 @@
- -
## Netty基本组件 ## Netty基本组件
- Netty对传统 Socket 进行封装
- NioEventLoopChannelByteBufPipelineChannelHandler - NioEventLoopChannelByteBufPipelineChannelHandler
![Netty组件对应](pic/Netty组件对应关系.png)
- NioEventLoop => Thread(监听客户端的连接 + 处理每个连接的读写线程)
- Channel => Socket 对一条连接的封装
- ByteBuf => IO Bytes 每一个Channel上数据流的处理
- Pipeline => Logic Chain 逻辑处理链
- Channel Handler => Logic 每一个逻辑
## Netty服务端启动 ## Netty服务端启动
- 分析服务端启动流程包括服务端Channel的创建初始化以及注册到selector - 分析服务端启动流程包括服务端Channel的创建初始化以及注册到selector
- 服务端的启动在哪里初始化?
- 在哪里accept连接?
- 启动过程
- 创建服务端 Channel -> newChannel()
- 初始化服务端 Channel -> init()
- 注册 selector -> register()
- 端口绑定 -> doBind()
---
- 源码分析1 - 创建服务端Channel
- bind()[用户代码入口] -> initAndRegister()[初始化并注册] -> newChannel()[创建服务端channel]
- 反射创建服务端Channel : NioServerSocketChannel()[构造函数] -> newSocket()[通过jdk来创建底层jdk channel] -> NioServerSocketChannelConfig()[tcp参数配置类] -> AbstractNioChannel() ->
- configureBlocking(false)[阻塞模式] -> AbstractChannel()[创建id, unsafe, pipeline]
- 源码分析2 - 初始化服务端Channel
- init()[初始化入口] -> set ChannelOptions, ChannelAttrs [这个配置用的不多] -> set ChildOptions,ChildAttrs [每次创建的新连接都会把这两个属性配置上去] -> config handler[配置服务端pipeline] ->
- add ServerBootstrapAcceptor[添加连接器,默认添加特殊的Handler]
- 源码分析3 - 注册 selector
- AbstractChannel.register(channel)[入口] -> this.eventLoop = eventLoop[绑定线程] -> register0()[实际注册] -> doRegister()[调用jdk底层注册] -> invokeHandlerAddedIfNeeded()[做一些事件的回调] ->
- fireChannelRegistered()[传播事件]
- 源码分析4 - 端口绑定
- AbstractUnsafe.bind()[入口] -> doBind() -> javaChannel().bind()[jdk底层绑定] -> pipeline.fireChannelActive()[传播事件] -> HeadContext.readIfIsAutoRead()
## NioEventLoop ## NioEventLoop
- 分析Netty reactor 线程处理过程,包括事件监听,事件处理,常规任务处理和定时任务处理 - 分析Netty reactor 线程处理过程,包括事件监听,事件处理,常规任务处理和定时任务处理
- 问题:
- 默认情况下, Netty 服务端启多少线程? 何时启动?
- Netty是如何解决jdk空轮询Bug的?会导致CPU飙升到100%
- Netty是如何保证异步串行无锁化?
---
- NioEventLoop 创建
- new NioEventLoopGroup()[线程组, 默认2*CPU] -> new ThreadPerTaskExecutor()[线程创建器] -> for(){new Child()}[循环构造NioEventLoop对象数组] ->
- chooserFactory.newChooser()[线程选择器:给每个新连接分配NioEventLoop线程]
- 深入剖析 ThreadPerTaskExecutor()
- 每次执行任务都会创建一个线程实体 -> FastThreadLocalThread
- NioEventLoopGroup 线程命名规则 nioEventLoop-1-xx
- 深入剖析 newchild()
- 保存线程执行器 ThreadPerTaskExecutor
- 创建一个 MpscQueue
- 创建一个 selector
- 深入剖析 chooserFactory.newChooser() 创建线程选择器
- chooserFactory.newChooser() -> isPowerOfTwo()[判断是否是2的幂, 如2,4,8,16] ->[TRUE] PowerOfTwoEventExecutorChooser[优化] -> index++ & (length-1) ->
- [FALSE] GenericEventExecutorChooser[普通] -> abs(index++ % length)
- ps: 计算机底层 & 操作比 取模操作高效的多, &操作是二进制的操作
---
- NioEventLoop 启动触发器
- 服务端启动绑定端口
- 新连接接入通过 chooser 绑定一个 NioEventLoop
- 启动流程
- bind() -> execute(task)[入口] -> startThread() -> doStartThread()[创建线程] -> ThreadPerTaskExecutor.execute()[线程执行器进行创建] ->
- thread = Thread.currentThread()[保存创建的线程] -> NioEventLoop.run()[启动]
---
- NioEventLoop 执行逻辑
- NioEventLoop.run() -> for(;;) -> select()[检查是否有io事件] -> processSelectedKeys()[处理io事件] -> runAllTasks()[处理异步任务队列]
---
- select() 方法执行逻辑 - 检测IO事件
- deadline 以及任务穿插逻辑处理
- 阻塞式的 select
- 解决 jdk 空轮训的 bug
## 新连接接入 ## 新连接接入
- 分析新连接接入以及绑定reactor线程绑定到selector的过程 - 分析新连接接入以及绑定reactor线程绑定到selector的过程

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 KiB

Loading…
Cancel
Save