从源码角度解析Netty的React模式是如何工作的
Netty 支持多种实现方式,比如nio,epoll 等,本文以nio的实现方式进行讲解。
1.EventLoop :
事件循环看,简单来说就是一个死循环监听事件,如果事件来了,处理掉。通常做法就是开启一个独立线程,一直循环。
伪代码:
while (queue.waitForMessage()) {
queue.processNextMessage();
}
2.EventLoopGroup:
一组(多个)事件循环。
3.bossGroup 和 workGroup
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup(); server端bossGroup 是负责 NioServerSocketChannel 处理客户端连接请求的,一个应用程序如果只开了一个端口(严格来说就是没有多个ServerBootstrap公用一个
bossGroup),那么 bossGroup 只需要一个eventLoop 就行了,如果配置大于1也没关系(因为用不到,eventLoop也不会启动)
ServerSocketChannel 创建好后,就绑定到网络端口就开始监听,如果有新的客户端连接进来,那么accept()后就会产生 SocketChannel,一个连接对应一个 SocketChannel 伪代码: ServerSocketChannel ssc = ServerSocketChannel.open();
...
SocketChannel socketChannel = ssc.accept(); 为了提高服务器性能,所有有的 SocketChannel 的相关操作都是在workGroup中完成的,所以 workGroup 里面需要配置适当多个 EnventLoop.
4.源码层面讲解 一个 ServerSocketChannel 只需要一个 EventLoop.
->bind(100).sync(); 绑定端口
-->AbstractBootstrap.doBind 具体绑定动作
---->AbstractBootstrap.initAndRegister config().group().register(channel); 将 serverChannel注册到bossGroup 的某个eventLoop中
------>MultithreadEventLoopGroup.register next().register(channel); next() 方法负责从group 中挑选一个eventLoop ,具体是由 chooser.next()实现;
通俗来讲就是,创建一个serverChannel绑定端口,初始化端口的过程中是从bossGroup中挑选一个 eventLoop,将channel注册到eventLoop中,eventLoop中nio selector,完成channel的注册。
注册的核心代码是:
如果当前线程就是在enventLoop ,调用register 方法就是直接执行register0,否则向线程(池)提交一个任务(eventLoop.execute()),这就是Reactor模式的核心实现逻辑,通过任务完成线程调配。
提交任务时候会干什么呢?
以上完整过程具体来讲就是,main线程开启(创建)一个serverChannel,创建过程中会从bossGroup 中选择一个eventLoop 给该channel, 同时给eventLoop 提交第一个任务(注册),同时会启动eventLoop ,
eventLoop 线程会扫描执行自己任务池里面的任务,其实第一个任务就是注册(将serverChannel注册到selector上),同时也会在自己线程中开始事件循环(接受客户端的连接)。
NioEventLoop 一直在干两件事:a.处理selector 上的 io 事件; b.其他其他线程提交过来的task。
5.上面讲了bossGroup 干的事情,下面将一下workGroup 是如何工作的,其实和bossGroup 一样,因为他们公用的是同一套代码逻辑,
不同点是每一个 SocketChannel (ServerSocketChannel.accept) 初始化时候,都会从workGroup里面选择一个 eventLoop.
ServerBootstrapAcceptor 核心代码:
ServerChannel channelRead 实际上是产生的一个连接,就是一个child channel ,然后从childGroup.rigister 的意思和上面serverChannel的一样,完成注册,其实也是通过提交任务实现的,只不过这里提交的是scheduledTask,这里注册挑选的child eventLoop 可能是已经启动了的(一个eventLoop负责多个child channel 的监听)
这样就实现了bossGroup负责连接, childGroup负责连接后的具体IO读写操作, 一个ServerBootstrap 只有一个enventLoop,childGroup 需要有多个(性能方面的需要)。
从源码角度解析Netty的React模式是如何工作的的更多相关文章
- 从源码角度解析 Springboot 2.6.2 的启动过程
1. 概述 老话说的好:把简单的事情重复做,做到极致,你就成功了. 言归正传,Springboot的启动过程,一直都是面试的高频点,今天我们用当前最新的 Springboot 2.6.2 来聊一聊 S ...
- netty源码解解析(4.0)-11 Channel NIO实现-概览
结构设计 Channel的NIO实现位于io.netty.channel.nio包和io.netty.channel.socket.nio包中,其中io.netty.channel.nio是抽象实 ...
- netty源码解解析(4.0)-10 ChannelPipleline的默认实现--事件传递及处理
事件触发.传递.处理是DefaultChannelPipleline实现的另一个核心能力.在前面在章节中粗略地讲过了事件的处理流程,本章将会详细地分析其中的所有关键细节.这些关键点包括: 事件触发接口 ...
- netty源码解解析(4.0)-17 ChannelHandler: IdleStateHandler实现
io.netty.handler.timeout.IdleStateHandler功能是监测Channel上read, write或者这两者的空闲状态.当Channel超过了指定的空闲时间时,这个Ha ...
- netty源码解解析(4.0)-18 ChannelHandler: codec--编解码框架
编解码框架和一些常用的实现位于io.netty.handler.codec包中. 编解码框架包含两部分:Byte流和特定类型数据之间的编解码,也叫序列化和反序列化.不类型数据之间的转换. 下图是编解码 ...
- 【react】什么是fiber?fiber解决了什么问题?从源码角度深入了解fiber运行机制与diff执行
壹 ❀ 引 我在[react] 什么是虚拟dom?虚拟dom比操作原生dom要快吗?虚拟dom是如何转变成真实dom并渲染到页面的?一文中,介绍了虚拟dom的概念,以及react中虚拟dom的使用场景 ...
- 消息队列高手课,带你从源码角度全面解析MQ的设计与实现
消息队列中间件的使用并不复杂,但如果你对消息队列不熟悉,很难构建出健壮.稳定并且高性能的企业级系统,你会面临很多实际问题: 如何选择最适合系统的消息队列产品? 如何保证消息不重复.不丢失? 如果你掌握 ...
- mybatis 3.x源码深度解析与最佳实践(最完整原创)
mybatis 3.x源码深度解析与最佳实践 1 环境准备 1.1 mybatis介绍以及框架源码的学习目标 1.2 本系列源码解析的方式 1.3 环境搭建 1.4 从Hello World开始 2 ...
- Go netpoll I/O 多路复用构建原生网络模型之源码深度解析
导言 Go 基于 I/O multiplexing 和 goroutine 构建了一个简洁而高性能的原生网络模型(基于 Go 的I/O 多路复用 netpoll),提供了 goroutine-per- ...
随机推荐
- <load-on-startup>1</load-on-startup>的作用
1)load-on-startup元素标记容器是否在启动的时候就加载这个servlet(实例化并调用其init()方法).2)它的值必须是一个整数,表示servlet应该被载入的顺序3)当值为0或者大 ...
- Greenplum 行存、列存,堆表、AO表的原理和选择
转载自: https://github.com/digoal/blog/blob/master/201708/20170818_02.md?spm=a2c4e.11153940.blogcont179 ...
- Qt--解析Json
一.QT5 Json简介 QT4中使用第三方库QJson解析JSON文件. QT5新增加了处理JSON的类,类均以QJson开头,包含在QtCore模块中.QT5新增加六个相关类: QJsonArra ...
- 块状链表 bzoj 3343教主的魔法
//块状链表//分块排序,然后每次查找时在暴力查找头和尾两个块.//中间那些块,因为有序所以只需2分查找即可.我用的是lower_pound();//插入是,也是头和尾暴力插入,中间那些加到一个累计里 ...
- docker安装mysql5.7 数据挂载
docker安装mysql5.7,并数据卷挂载到主机 # docker 中下载 mysql docker pull mysql:5.7 #启动 docker run --name mysql3306 ...
- python下pip 安装 pyautogui报错Command "python setup.py egg_info" failed with error code 1 in C:\Users\Administrator\AppData\Local\Temp\pip-install-svhtepho\pygetwindow\
python装的3.6 64位,使用命令pip install pyautogui 或者pip install -U pyautogui 都失败了 报错如下: Command "python ...
- AxB Proplem(大数乘法)
描述 Redraiment碰到了一个难题,需要请你来帮忙:给你两个整数,请你计算A × B. 输入 数据的第一行是整数T(1 ≤ T ≤ 20),代表测试数据的组数. 接着有T组数据,每组数据只有一行 ...
- 【解决方案】IP代理池设计与解决方案
一.背景 爬虫服务请求量大,为了应对反爬措施,增加爬虫的爬取效率和代理IP使用率,需要设计一个IP代理池,满足以下需求: 定时任务获取第三方代理 及时剔除IP代理池中失效的IP 业务隔离IP 若IP未 ...
- WORD转HTML-python第三方包Mammoth(官方文档翻译)
Mammoth 官方 Mammoth可用于将.docx文档(比如由Microsoft Word创建的)转换为HTML.Mammoth致力于通过文档中的语义信息生成简洁的HTML,而忽略一些其他细节.例 ...
- 简单动态字符串-redis设计与实现
简单动态字符串 Sds (Simple Dynamic String,简单动态字符串)是 Redis 底层所使用的字符串表示, 几乎所有的 Redis 模块中都用了 sds. 本章将对 sds 的实现 ...