Netty源码三:NioEventLoop创建与run方法
1.入口

会调用到父类SingleThreadEventLoop的构造方法
2.SingleThreadEventLoop

继续调用父类SingleThreadEventExecutor的构造方法
3.SingleThreadEventExecutor

到这里完整的总结一下:
- 将线程执行器保存到每一个SingleThreadEventExcutor里面去
- 创建了MpscQueue,具体为什么,因为在NioEventLoop里面重写了newTaskQueue方法

- 等父类调用完毕,最后回到NioEventLoop里面,最重要的一件事:创建Selector
最后那一张图完整的总结一下:
4.NioEventLoop.run
4.1 调用入口
这里还是要回顾一下这个方法是什么时候调用的?
Netty在启动的时候,在调用config().group().register(channel) ,使用bossGroup做channel注册的时候,它会使用EventExecutorChooser找一个NioEventLoop然后去做注册,最终会调用到这个abstractChannel.register方法
一般来说,我们启动的时候,运行到这里,eventLoop会返回false,所以会调用到eventLoop.execute里面的方法,在这里我们就能找到这个NioEventLoop.run的调用地方


也就说在使用NioEventLoop将channel注册到selector的时候,会判断是不是eventloop线程调用,如果不是就会使用SingleThreadEventExecutor.execute执行,它会将NioEventLoop.run方法包装成一个runnable,然后创建一个线程并启动,然后就调用到NioEventLoop里面了
4.2 run方法
/*** todo select() 检查是否有IO事件* todo ProcessorSelectedKeys() 处理IO事件* todo RunAllTask() 处理异步任务队列*/
@Override
protected void run() {for (; ; ) {try {// todo hasTasks() true代表 任务队列存在任务switch (selectStrategy.calculateStrategy(selectNowSupplier, hasTasks())) {case SelectStrategy.CONTINUE:continue;case SelectStrategy.SELECT:// todo 轮询IO事件, 等待事件的发生, 本方法下面的代码是处理接受到的感性趣的事件, 进入查看本方法select(wakenUp.getAndSet(false));// wakenUp.compareAndSet(false, true)' is always evaluated// before calling 'selector.wakeup()' to reduce the wake-up// overhead. (Selector.wakeup() is an expensive operation.)//// However, there is a race condition in this approach.// The race condition is triggered when 'wakenUp' is set to// true too early.//// 'wakenUp' is set to true too early if:// 1) Selector is waken up between 'wakenUp.set(false)' and// 'selector.select(...)'. (BAD)// 2) Selector is waken up between 'selector.select(...)' and// 'if (wakenUp.get()) { ... }'. (OK)//// In the first case, 'wakenUp' is set to true and the// following 'selector.select(...)' will wake up immediately.// Until 'wakenUp' is set to false again in the next round,// 'wakenUp.compareAndSet(false, true)' will fail, and therefore// any attempt to wake up the Selector will fail, too, causing// the following 'selector.select(...)' call to block// unnecessarily.//// To fix this problem, we wake up the selector again if wakenUp// is true immediately after selector.select(...).// It is inefficient in that it wakes up the selector for both// the first case (BAD - wake-up required) and the second case// (OK - no wake-up required).if (wakenUp.get()) {selector.wakeup();}// fall throughdefault:}cancelledKeys = 0;needsToSelectAgain = false;final int ioRatio = this.ioRatio; // todo 默认50// todo 如果ioRatio==100 就调用第一个 processSelectedKeys(); 否则就调用第二个if (ioRatio == 100) {try {// todo 处理 处理发生的感性趣的事件processSelectedKeys();} finally {// Ensure we always run tasks.// todo 用于处理 本 eventLoop外的线程 扔到taskQueue中的任务runAllTasks();}} else {// todo 因为ioRatio默认是50 , 所以来else// todo 记录下开始的时间final long ioStartTime = System.nanoTime();try {// todo 处理IO事件processSelectedKeys();} finally {// Ensure we always run tasks.// todo 根据处理IO事件耗时 ,控制 下面的runAllTasks执行任务不能超过 ioTime 时间final long ioTime = System.nanoTime() - ioStartTime;// todo 这里面有聚合任务的逻辑runAllTasks(ioTime * (100 - ioRatio) / ioRatio);}}} catch (Throwable t) {handleLoopException(t);}// Always handle shutdown even if the loop processing threw an exception.try {if (isShuttingDown()) {closeAll();if (confirmShutdown()) {return;}}} catch (Throwable t) {handleLoopException(t);}}}
�
这里注释其实说得挺清楚,最后总结一下:
- select(wakenUp.getAndSet(false)):轮训io事件发生,当timeout或者有事件会break
- processSelectedKeys:处理io事件
- 运行taskQueue里面的任务
4.3 processSelectedKeys
在真正执行的时候,最终会走到processSelectedKeysOptimized,netty对底层selectKeys容器进行过优化,用数组代替了keyset
这里我为了debug,使用telnet localhost 8899, 接着就会进入到processSelectedKeysOptimized中
在走进processSelectedKey方法之后,最终会走到unsafe.read方法
�
�
5.AbstractNioMessageChannel

接着会调用到子类NioServerSocketChannel的doReadMessage(readBuf), 调用完子类之后,会通过pipline.fireChannelRead, 意思就是对于server端来说可读了,但是注意这时候传的是子类中创建的NioSocketChannel,说白了给server端一个NioSocketChannel,就是要创建新连接了。最终会调用到ServerBootstrapAcceptor的ChannelRead,具体看后面的ServerBootStrapAcceptor类
�
6.NioServerSocketChannel

这里主要做了几件事:
- SocketUtils.accpet接受连接,并创建jdk底层的socketChannel
- new NioSocketChannel:将jdk封装成NioSocketChannel,这里和创建NioServerSocketChannel的时候一样,不断的调用父类,同时创建NioServerChannel的pipline,!!!这里注意,这里会设置感兴趣的事件为read

7.ServerBootstrap#ServerBootstrapAcceptor
ServerBootstrapAcceptor是ServerBootstrap的内部类
之前AbstractNioMessageChannel里面的
,最终会调用到ServerBootstrapAcceptor的channelRead方法
简单的总结一下做了几件事:
- 给sockeChannel(也是这里的child)设置childHandler
- 使用childGroup.register 来完成socketChannel到Selector的注册,这里和SocketServerChannel到Selector的注册逻辑是一样的,都是从EventLoopGroup中选一个EventLoop(里面有Selector),然后调用jdk的register(eventloop.getSelector, 0, NioSocketChannel(netty对于socketChannel的包装))
8.AbstractChannel
childGroup.register -> MultithreadEventLoopGroup.register -> SingleThreadEventLoop.register -> AbstractChannel.register

AbstractChannel.abstractUnsafe.register 
这一刻代码之前都讲过,就是把创建socketChannel注册到EventLoop上的Selector上去
AbstractChannel.register0():
- doRegister: 完成了SocketChannel到Selector的注册
- pipeline.invokeHandlerAddedIfNeeded: 这里会调用之前我们设置MyServerInitializer.initChannel(), 会往SocketChannel的pipeline中加入一系列读写用到的Handler
�
9.总结
最后那一张图总结一下:
相关文章:
Netty源码三:NioEventLoop创建与run方法
1.入口 会调用到父类SingleThreadEventLoop的构造方法 2.SingleThreadEventLoop 继续调用父类SingleThreadEventExecutor的构造方法 3.SingleThreadEventExecutor 到这里完整的总结一下: 将线程执行器保存到每一个SingleThreadEventExcutor里面去创建了MpscQu…...
【讲座分享】| 复旦大学张奇教授——《自然语言发表论文如何打怪升级?NLP顶会论文发表》
文章目录 1 基础关1.1 基础书籍1.2 提高书籍1.3 课程链接1.4 编程实战 2 阅读关2.1 分层过滤2.2 集团作战,信息获取2.3 论文如何泛读 3 动机 方向关3.1 快速发论文3.2 好的研究 4 写作关4.1 论文写作流程4.2 从读者角度出发4.3 每一部分怎么写4.3.1 Abstract摘要4.3…...
面试八股文(3)
文章目录 1.HashSet如何检查重复2.comparable和Comparator区别3.ConcurrentHashMap和Hashtable区别4.线程和进程5.并发与并行的区别6.为什么使用多线程7.使用多线程可能带来问题8.线程的生命周期和状态9.什么是上下文切换10.线程死锁11.产生死锁四个条件12.如何避免死锁 1.Hash…...
Kubernetes WebHook 入门 -- 入门案例: apiserver 接入 github
博客原文 文章目录 k8s 集群配置介绍Admission WebhookWebHook 入门实践: github 认证接入web 服务器Dockerfile 镜像制作amd64x86_64构造镜像检验镜像 Makefilewebhook 接入 apiserverwebhook.yamlapiserver 挂载 webconfig在 github 中创建认证 token将 token 添加到 kubecon…...
办公软件巨头CCED、WPS面临新考验,新款办公软件异军突起
办公软件巨头CCED、WPS的成长经历 众所周知,CCED和WPS在中国办公软件领域树立了两大知名品牌的地位。然而,它们的成功并非一朝一夕的成就,而是历经了长时间的发展与积淀。 在上世纪80年代末至90年代初,CCED作为中国大陆早期的一款…...
unity角色触摸转向
1、挂载脚本到角色的父物体A上 2 、以屏幕左边的触摸为移动,右边为转向操作 3、加载角色时,将角色的父物体设置为A,须将角色的位置和角度置0 using System; using System.Collections; using System.Collections.Generic; using UnityEngin…...
世界顶级汽车品牌源代码遭泄露 详解源代码凭据安全解决方案
源代码凭据安全,您别忽视 !!! 一、事件回顾 2024年1月29日,RedHunt 实验室的研究员Lohit爆料:某世界顶级的豪华汽车品牌源代码面临泄露风险!人为错误致GitHub令牌事故引发重大安全担忧。 RedHunt Labs在一次互联网扫描时&#x…...
Mysql-备份与恢复
目录 一、备份表 1.无需备份表结构 2.备份表结构 3.mysqldump方式备份表 二、备份库 一、备份表 1.无需备份表结构 CREATE TABLE a_bak as select * from a;#备份表(不包含表结构)TRUNCATE TABLE a;#清空表 INSERT INTO a SELECT * FROM a_bak;#插…...
基于STM32的UART/USART数据传输的错误检测和纠错机制研究
在STM32的UART/USART数据传输过程中,为了确保数据的可靠性,通常需要使用错误检测和纠错机制。常见的错误检测和纠错技术包括奇偶校验、循环冗余校验(CRC)、硬件流控制和重发机制等。本文将重点介绍这些技术在STM32上的应用&#x…...
「优选算法刷题」:计算布尔二叉树的值
一、题目 给你一棵 完整二叉树 的根,这棵树有以下特征: 叶子节点 要么值为 0 要么值为 1 ,其中 0 表示 False ,1 表示 True 。非叶子节点 要么值为 2 要么值为 3 ,其中 2 表示逻辑或 OR ,3 表示逻辑与 AND…...
A系统数据表同步到B系统数据表
一、 事务操作 (小量数据) 事务操作通常用于确保数据的一致性和完整性。以下是一些常见的应用场景: 银行转账:当从一个账户向另一个账户转账时,需要确保两个操作(从一个账户扣款和向另一个账户存款&#x…...
Qt实现类似ToDesk顶层窗口 不规则按钮
先看效果: 在进行多进程开发时,可能会遇到需要进行全局弹窗的需求。 因为平时会使用ToDesk进行远程桌面控制,在电脑被控时,ToDesk会在右下角进行一个顶层窗口的提示,效果如下: 其实要实现顶层窗口…...
发布4-运行JRT程序
到了本章节,你需要准备好JDK17的环境和idea环境。并且安装好选择的数据库软件。这章将正式开始JRT的程序开发。 首先获取程序,我会给下载地址 下载后解压会得到下图目录的文件结构,DBFile放IRIS和PG的数据库文件,JRTClient放打包…...
利用VPN设备漏洞入侵!新型勒索软件CACTUS攻击手法分析
近期,亚信安全应急响应中心截获了利用VPN设备已知漏洞传播的新型勒索软件CACTUS,该勒索于2023年3月首次被发现,一直保持着活跃状态。CACTUS勒索软件通过Fortinet VPN的已知漏洞进行入侵(黑客首先获取到VPN账号,再通过V…...
第7章 SpringBoot安全管理
学习目标 了解SpringSecurity安全管理的功能 掌握SpringSecurity的安全配置 掌握SpringSecurity自定义用户认证的实现方法 掌握SpringSecurity自定义用户授权管理的实现方法 掌握如何使用SpringSecurity实现页面控制 实际开发中,一些应用通常要考虑到安全性问题。例如,对于一…...
【QT+QGIS跨平台编译】之二十二:【FontConfig+Qt跨平台编译】(一套代码、一套框架,跨平台编译)
文章目录 一、FontConfig介绍二、文件下载三、文件分析四、pro文件五、编译实践 一、FontConfig介绍 FontConfig 是一个用于配置和定制字体的库,广泛应用于基于X Window系统的操作系统中,尤其是在Linux和Unix-like系统中。它为应用程序提供了一种统一的…...
echarts中绘制3D三维地球
简介 echarts中的三维地球,需要用到世界地图json数据,我把json文件放到我的资源中,有需要的自行下载。 安装插件 // 安装echats npm install echarts --save npm install echarts-gl --save 项目中引用 1,引入安装的echarts…...
go grpc高级用法
文章目录 错误处理常规用法进阶用法原理 多路复用元数据负载均衡压缩数据 错误处理 gRPC 一般不在 message 中定义错误。毕竟每个 gRPC 服务本身就带一个 error 的返回值,这是用来传输错误的专用通道。gRPC 中所有的错误返回都应该是 nil 或者 由 status.Status 产…...
Redis实现登录的优化
目录 1 前言 2 实现步骤 2.1 软件环境准备 2.1.1 Redis的安装 2.1.2 在pom.xml中添加依赖 2.1.3 在application.yml中进行相关配置 2.2 StringRedisTemplate的常用方法 2.2.1 获取operations 2.2.2 主要方法 2.3 令牌主动失效机制 2.3.1 登录时将令牌存入Redis 2.…...
ROS方向第二次汇报(5)
文章目录 1.本方向内学习内容:1.1.自定义msg:1.1.1.定义msg文件:1.1.2.编辑配置文件: 1.2.自定义srv:1.2.1.定义srv文件:1.2.2.编辑配置文件: 1.3.服务通信案例实现:1.3.1.服务端实现…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...
【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...
FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...
redis和redission的区别
Redis 和 Redisson 是两个密切相关但又本质不同的技术,它们扮演着完全不同的角色: Redis: 内存数据库/数据结构存储 本质: 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能: 提供丰…...
