Netty服务端基本启动流程源码刨析

前言: 希望看这篇文章之前对Java Nio编程比较熟悉,并有用过Netty开发简单代码

服务端代码

先大致说一下NioEventLoopGroup组件的作用,可以把它看是作内部维护了一个NioEventLoop数组的对象,它的构造方法的参数用来指定维护数组的大小。NioEventLoop继承自Executor可以理解为一个NioEventLoop是一个单线程线程池。

ServerBootStrap作为一个封装Java Nio 的一个启动类接下来我们分析这个启动类

首先bootstrap.group(boss,eventExecutors)这段代码内部为SerBootStrap属性赋值,分别赋值给Group和childGroup。Group即boss线程组主要负责通过Java Nio建立连接 ,childGroup主要负责监听Group传递过来的Channel。

channel方法内部是根据类对象创建一个channelFactory工厂,用来通过反射创建NioServerSocketChannel,这里的Channel完全是Netty自己的类不是JavaNio自带的类

重点在bind方法内部

内部调用doBind方法,接下来注意initAndRegister方法

通过工厂方法创建channel,由于NioServerSocketChannel继承了AbstractChannel,先看父类构造方法都做了什么

unsafe类不是Java中的操作内存的Unsafe类,这里的unsafe类是用来读取和写入消息进行的封装,pipeline可以理解为是一个链表,每个节点是ChannelHandler和上下文信息封装而成

NioServerSockerChannel构造方法内还创建了Java Nio的ServerSocketChannel

这里代码图片就不粘贴了可以自己动手看,其内部就是把ServerSocketChannel赋值给NioServerSocketChannel的一个属性,如果后续代码中NioServerSocketChannel调用javaChannel()方法返回的就是这个属性即Java原生ServerSocketChannel。

Config内部等于保存了NioServerSocketChannel的引用,以及初始化了ByteBuf内存分配器

至此 channelFactory创建channel的方法结束

此时NioServerSocketChannel内部只是保留了对ServerSocketChannel的引用,并未对ServerSocketChannel注册事件等等

接下来注意Init方法

可以看到它主要做了一些参数信息的设置以及添加了一个HandlerContext,这里等于说是一个头节点和一个这个节点以及一个尾节点构成pipleline。这里留意一下execute方法,参数currentChildGroup就是开头的NioEventLoopGroup(child),这里的currentChildHandler是我们最开始片段的Handler,以及Options都是最开始专门为ChildHandler设置的

这里Init方法结束,接下来看initAndRegister方法中的Register方法

这里的config是上一步的config对象,这里的group是最开始创建的Boss线程组 NioEventLoopGroup,进入register方法内部

 public ChannelFuture register(Channel channel) {
        return next().register(channel);
    }

next()方法主要是从线程组中挑出一个NioEventLoop即只有一个线程的线程池,再次深入register方法

我们发现这里的promise封装了NioServerSocketChannel和从Group中挑出的线程池

接下来是重中之重涉及到线程的开启和切换

Unsafe的register方法

这里的inEventLoop其实是判断当前线程是否是NioEventLoop中的线程,NioEventLoop中的线程采用懒惰加载,第一次为null所以判断结果为false。

我们可以看到他向单线程线程池(NioEventLoop)任务队列中提交了一个普通任务

接着调用startThread方法,直接看其内部的doStartThread方法

看左下角当前线程是NioEventLoopGroup中的一个线程,并把此线程赋值给Thread属性(懒加载),接着进入SingleThreadEventExecutor.this.run()方法,这里的this.run指的是NioEventLoop的run方法

这里我要引入一张图片来解释run方法的功能

我们现在只处在BossGroup中,注意下面的圆圈这里就是这段代码的功能我们一句一句看

这里的selectStrategy.calculateStrategy(selectNowSupplier, hasTasks());方法是判断普通任务队列(非定时任务)是否有待完成的任务,这里显然是有的上面已经说了提交了一个任务register0,但是这里面的作用是如果有任务就调用selectNow方法,看返回的是否有事件发生。

因为NioEventLoop毕竟是线程池除了要监听channel事件还要处理普通任务和定时任务

如果没有普通任务返回的就是枚举类SELECT

long curDeadlineNanos = nextScheduledTaskDeadlineNanos();计算的是定时任务的最小时间,这里是为了下面调用Select.select(time)有限时间监听channel事件。正如之前所说:NioEventLoop毕竟是线程池除了要监听channel事件还要处理普通任务和定时任务

上面主要是解决定时任务的情况方法就是有限时间的等待,由于我们只提交了register0任务继续向下看,看它是如何处理普通任务和channel中发生事件的

这段代码要留意selectCnt++,ioRatio,processSelectedKeys(),ranTasks = runAllTasks(ioTime * (100 - ioRatio) / ioRatio)

首先 processSelectedKeys()是为了处理Channel中有注册事件发生,我们代码中目前还没有连接事件

所以就看runAllTask方法

其内部就是从队列中拿到之前提交的task任务

看!该执行我们之前提交的任务了

看此方法内部 doRegister方法

这里任务的提交以及register方法都是在NioServerSocketChannel的父类中完成

selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this);

这段代码就是把Netty中的NioServerSocketChannel当作附件给添加到Java Nio中ServerSocketChannel,并把它注册到selector中

同时调用HandlerContext的initChannel方法,把任务提交向pipleLine中添加一个HandlerContext

到这里启动流程基本就这些,事件的处理selectCnt++,ioRatio,processSelectedKeys(),下篇文章继续

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/493780.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

快速上手Spring Cloud 十:Spring Cloud与微前端

快速上手Spring Cloud 一:Spring Cloud 简介 快速上手Spring Cloud 二:核心组件解析 快速上手Spring Cloud 三:API网关深入探索与实战应用 快速上手Spring Cloud 四:微服务治理与安全 快速上手Spring Cloud 五:Spring …

强化基础-Java-泛型

什么是泛型? 泛型其实就参数化类型,也就是说这个类型类似一个变量是可变的。 为什么会有泛型? 在没有泛型之前,java中是通过Object来实现泛型的功能。但是这样做有下面两个缺陷: 1 获取值的时候必须进行强转 2 没有…

Learn OpenGL 26 视差贴图

什么是视差贴图 视差贴图(Parallax Mapping)技术和法线贴图差不多,但它有着不同的原则。和法线贴图一样视差贴图能够极大提升表面细节,使之具有深度感。它也是利用了视错觉,然而对深度有着更好的表达,与法线贴图一起用能够产生难…

商标跨类异议与跨类保护!

有个朋友对普推知产老杨说收到某邮件,名下商标让某公司抢注了现在公告期,让赶紧提出来异议去处理下,怎么会有这样的事,相同的名称基本上在同类别相关产品是无法公告和获得初审的。 经详细检索分析后,发现不是这样一回…

【Linux】理解父子进程(系统调用创建进程,fork函数,写时拷贝)

目录 fork函数 返回值 内存分配 父子进程是操作系统一个重要的概念,特别是在多任务处理和并发编程中,在Linux中,每个进程都有一个唯一的进程ID,并且每个进程都有可能创建其他进程。当一个进程创建了一个新的进程时,…

【Linux】进程>环境变量地址空间进程调度

主页:醋溜马桶圈-CSDN博客 专栏:Linux_醋溜马桶圈的博客-CSDN博客 gitee:mnxcc (mnxcc) - Gitee.com 目录 1.环境变量 1.1 基本概念 1.2 常见环境变量 1.3 查看环境变量方法 1.4 和环境变量相关的命令 1.5 环境变量的组织方式 1.6 通…

最“原始”的收音机长啥样?

同学们大家好,今天我们继续学习杨欣的《电子设计从零开始》,这本书从基本原理出发,知识点遍及无线电通讯、仪器设计、三极管电路、集成电路、传感器、数字电路基础、单片机及应用实例,可以说是全面系统地介绍了电子设计所需的知识…

vs code

vs code 下载安装 https://code.visualstudio.com/https://code.visualstudio.com/ 下载完后,下一步下一步就安装完了,安装好后可以下载各种好用的插件

【前端面试3+1】03深拷贝浅拷贝、let和var、css盒模型、【有效括号】

一、深拷贝浅拷贝 深拷贝和浅拷贝都是用于复制对象或数组的概念,但它们之间有着重要的区别: 1. 浅拷贝: 浅拷贝是指在拷贝对象或数组时,只会复制一层对象的属性或元素,而不会递归地复制嵌套的对象或数组。因此&#xf…

2024年第十二届计算机与通信管理国际会议(ICCCM 2024)即将召开!

2024年第十二届计算机与通信管理国际会议(ICCCM 2024)将2024年7月19-21日在日本鹿儿岛召开。会议由鹿儿岛大学主办。此次会议旨在为业界建立一个广泛、有效的交流合作平台,让我们及时了解行业发展动态、掌握最新技术,拓宽研究视野…

修改Jupyter Notebook的默认路径,以及在PowerShell中自定义其启动路径

修改Jupyter Notebook的默认路径,以及在PowerShell中自定义其启动路径 设置 Jupyter Notebook 配置文件,修改默认路径要在PowerShell中设置自定义的启动脚本,以确保Jupyter Notebook能够自动定位到当前路径设置后的效果 在使用Jupyter Notebo…

【C语言】编译和链接

文章目录 一、编译环境和运行环境二、翻译环境2.1 预处理2.2 编译2.2.1 词法分析2.2.2 语法分析2.2.3 语义分析 2.3 汇编2.4 链接 三、运行环境 一、编译环境和运行环境 在ANSIC的任何一种实现中,存在两个不同的环境。 第1种是翻译环境,在这个环境中源代…

C++ STL教程

C STL教程 文章目录 C STL教程1.1 std::vector1.1.1vector的定义1.1.2vector容器的初始化1.1.3vector容器内元素的访问和修改1.1.4vector中的常用函数 1.2 std::string1.2.1string的定义1.2.2string的初始化1.2.3string中元素的访问和修改1.2.4string中连接字符串1.2.5string中…

阿里云服务器安装MySQL(宝塔面板)

只写关键步骤 1. 创建一个云服务器实例 2 修改密码,登录服务器 3. 安装宝塔面板 进入https://www.bt.cn/new/index.html 进入宝塔面板地址 4. 安装Mysql 5. 创建数据库(可导入数据库) 6. 测试连接数据库 打开Navicat(或其他数据…

[Qt] QString::fromLocal8Bit 的使用误区

QString::fromLocal8Bit 是一个平台相关的函数。默认情况下在 Windows 下 就是 gbk 转 utf-8 ,在 Linux就应该是无事发生。因为Linux平台默认的编码方式就是 utf-8 可以通过 void QTextCodec::setCodecForLocale(QTextCodec *c)来修改 Qt默认的编码方式。如下 第一输出乱码的…

DreamPolisher、InternLM2 、AniArtAvatar、PlainMamba、AniPortrait

本文首发于公众号:机器感知 DreamPolisher、InternLM2 、AniArtAvatar、PlainMamba、AniPortrait DreamPolisher: Towards High-Quality Text-to-3D Generation via Geometric Diffusion We present DreamPolisher, a novel Gaussian Splatting based method wit…

kubernetes负载均衡资源-Ingress

一、Ingress概念 1.1 Ingress概念 使用NodePort类型的Service可以将集群内部服务暴露给集群外部客广端,但使用这种类型Service存在如下几个问题。 1、一个端口只能一个服务使用,所有通过NodePort暴露的端口都需要提前规划;2、如果通过NodePort暴露端口过多,后期维护成本太…

中国土壤厚度空间分布数据

土壤层次分为覆盖层 林溶层 淀积层 母质层,其中在林溶层中的最上面那层就是我们通常说的土壤厚度在这一层中,这一层也被称为腐殖层,是肥力性质最好的一层,植物根系和微生物也集中在这一层。至于覆盖层在森林土壤中比较常见&#x…

【LeetCode: 2580. 统计将重叠区间合并成组的方案数 + 合并区间】

🚀 算法题 🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介:硕风和炜,…

计算机组成原理 3 运算器

定点补码加/减法运算 补码加减法的实现 补码加法 : [X + Y] 补 [X] 补 + [Y] 补 和的补码 补码的和 补码减法 : [X−Y] 补 [X] 补 + [−Y] 补 [X] 补 −[Y] 补 差的补码 补码的差 求补公式 : [−…