Netty核心源码解析(一)

news2024/11/26 4:46:39
  1. Netty是什么?
    1. Netty是Jboss提供的一个Java 开源框架,主要针对TCP协议的高并发场景
    2. Netty本质是对Java NIO做了封装的网络通信框架,主要作用是Java NIO基本接口的封装,提供了网络通信中线程同步,编解码,粘包拆包,闪断重连等问题的封装,方便我们利用API方便的开发;
    3. 提供了完整的ssl/tsl支持;
    4. 另外Netty解决了NIO中的selector空轮训的Bug;
    5. Netty 线程模型为多reactor多线程模型-1+n+m,但是Netty提供了灵活配置,也可以实现单reactor单线程,单reactor多线程模型;
  2. Netty的启动流程
    1. 先上代码
public class HelloServer {
    public static void main(String[] args) {
        NioEventLoopGroup bossGroup=new NioEventLoopGroup(1);
        NioEventLoopGroup workGroup=new NioEventLoopGroup();
        new ServerBootstrap()
                //1、绑定线程池组
                .group(bossGroup,workGroup) 
                //2、定义主reactor线程处理Handler
                .handler(new LoggingHandler(LogLevel.DEBUG))
                //3、选择服务器的ServerSocketChannel实现
                .channel(NioServerSocketChannel.class)
                //4、boss:负责处理连接;worker:处理读写,决定了worker(child)能执行哪些操作(handler)
                .childHandler(
                        //5、Channel代表和客户端进行数据读写的通道,Initializer初始化器,负责添加别的handler
                        new ChannelInitializer<NioSocketChannel>() {
                            @Override
                            protected void initChannel(NioSocketChannel ch) throws Exception {
                                //添加具体的handler
                                ch.pipeline().addLast(new StringDecoder()); //17、将ByteBuf转换为字符串,然后给下一个处理器
                                ch.pipeline().addLast(new ChannelInboundHandlerAdapter() { //自定义handler
                                    @Override //读事件
                                    //18、执行channelRead()方法,打印hello
                                    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                        System.out.println("WorkGroup thread name----"+Thread.currentThread().getName());
                                        System.out.println(msg);
                                        System.out.println(ctx.pipeline().names());
                                    }
                                });

                            }
                        })
                //6、绑定监听端口
                .bind(8888);
    }
}
  1. Netty提供了启动引导类ServerBootstrap,使用Builder模式来帮助构建启动Netty服务器程序,提供了灵活的配置需求;
  2. 基本说明--
    1. Netty启动过程就是加载配置项--主从reactor执行线程池组,socketchannel的Handler,监听端口;
    2. 然后创建serversocketchannel注册到主reactor线程上,监听新连接事件,将新的连接分发到从reactor线程的eventloop中;
    3. 这里Netty对serversocketchannel提供了默认的Handler实现对新连接创建socketchannel并分发给从reactor的逻辑;
    4. 首先通过group方法指定了主从reactor线程池组,bossGroup对应主reactor线程,负责监听端口处理连接请求,新连接请求将创建socketchannel并分发注册到workerGroup中的eventloop上,由workerGroup中的eventloop监听IO事件并调用相应的Handler来处理IO事件;
    5. 每一个eventloop对应一个单例线程池,对应一个selector对象,接受一个或多个channel注册,监听读写事件;
    6. Netty启动并初始化的核心逻辑在体现在bind()方法中,bind方法创建serversocketchannel并注册到bossGroup中的eventloop上,并为serversocketchannel提供默认用来创建新连接的Handler----ServerBootstrapAcceptor
    7. 总体来说,网络通信的基本过程为---
      1. 创建serversocketchannel监听端口,处理connect事件
      2. 创建socketchannel监听连接,处理IO事件
      3. 而Netty启动则完成了第一步;
  3. Netty中的核心类型说明
    1. NioEventLoop

Netty启动首先创建了两个nioeventloopgroup对象,这两个对象字面理解就是两个nioEventLoop数组,所以核心是NioEventLoop,看一下源码--

public final class NioEventLoop extends SingleThreadEventLoop {
    private Selector selector;
    private SelectedSelectionKeySet selectedKeys;
    private final SelectorProvider provider;
    private final SelectStrategy selectStrategy;
    //注册socketchannel到selector
    public void register(final SelectableChannel ch, final int interestOps, final NioTask<?> task);
    //重新构建selector--JDK NIO中的selector的空轮训Bug解决方案
    public void rebuildSelector();
    //eventloop运行主逻辑
    protected void run();
}

NioEventLoop可以说是Netty的reactor核心逻辑的实现,主要继承了抽象类SingleThreadEventLoop,单线程处理NIO事件循环通知;而SingleThreadEventLoop的继承和实现关系如下:

 代码实例中只写了极少一部分体现核心逻辑的方法和实例属性,主要为了概念上说明NioEventLoop的工作机制,具体详细的实现在后续专门说明;

NioEventLoop的工作原理-

  1. EventLoop核心是一个线程处理事件循环;
  2. NioEventLoop则是运行selector方法,完成对注册在selector上的channel的网络事件监听,这也就是reactor模型的基本实现----IO多路复用和事件监听;
  3. 另外NioEventLoop继承了SingleThreadEventLoop,除了监听selector之外还可以监听通过父类的execute()方法提交的任务和schedule方法提交的定时任务;
  4. rebuildSelector()方法是NioEventLoop对JDK中的selector空轮训的Bug实现的解决方案----空轮训次数超过默认512次后重新构建一个新的selector对象;
  5. register()方法用于在新连接建立后向EventLoop中的selector注册连接对应的socketchannel;
  6. run()方法则是一个死循环,对selector和注册的其他异步任务进行轮训,监听到事件发生时则执行对应的Handler来处理事件;

        2.NioEventLoopGroup

 NioEventLoopGroup 是一个线程数组,继承了MultithreadEventLoopGroup,

主要提供了对NioEventLoop 初始化的参数,用来创建NioEventLoop实例,默认创建CPU核数*2个线程(EventLoop)--

 另外MultithreadEventLoop继承了EventExecutorChooser选择器的实现,选择器用来做任务分发----NioEventLoopGroup 是一个线程池,当向NioEventLoopGroup注册一个新的channel的时候具体分发给哪一个EventLoop的selector来监听该channel上的IO事件;这里对选择器的实现机制不多做解释,大概对NioEventLoopGroup的主要功能逻辑做一个说明;

        3.ChannelHandler

channelHandler是事件处理器的实现,netty中通过责任链模式实现对事件的层层处理,责任链模式的主体对象是pipeline,相当于一个双向链表,分别对应出站(从服务端到客户端)和入站(从客户端向服务端)方向的事件处理,这里出站和入战是相对的,对本netty服务来说,接收外部的其他服务请求即为入站,反之主动向其他netty服务发出请求即为出站,简单理解为接收数据即为入站,发送数据即为出站;当事件发生的时候,EventLoop就会调用对应的channel的Handler来处理具体的逻辑--底层的ByteBuffer的读写,上层业务逻辑处理等等;

 

总结:netty通过EventLoop单线程执行selector来监听注册在其上的网络IO事件和用户在Handler中提交的异步任务,然后对不同的事件调用不同的Handler来处理;而netty的主体功能此时就体现出来了,第一,实现了reactor线程模型,第二,封装很多网络通信中底层数据的处理逻辑,用户可以通过简单的调用或者继承即可实现相应的功能,从而屏蔽了网络通信底层逻辑的复杂性;

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

小龟带你敲排序之冒泡排序

冒泡排序 一. 定义二.题目三. 思路分析&#xff08;图文结合&#xff09;四. 代码演示 一. 定义 冒泡排序&#xff08;Bubble Sort&#xff0c;台湾译为&#xff1a;泡沫排序或气泡排序&#xff09;是一种简单的排序算法。它重复地走访过要排序的数列&#xff0c;一次比较两个元…

Kettle系列(一)下载安装与基础配置

Kettle系列&#xff08;一&#xff09;下载安装与基础配置 说明一、下载二、目录结构三、基础配置&#xff08;1&#xff09;环境变量&#xff08;2&#xff09;kettle配置 四、连接mysql8五、连接其他数据库六、总结 说明 更新时间&#xff1a;2023/08/13 17:47 本文记录了wi…

openGauss学习笔记-38 openGauss 高级数据管理-游标

文章目录 openGauss学习笔记-38 openGauss 高级数据管理-游标38.1 语法格式38.2 参数说明38.3 示例 openGauss学习笔记-38 openGauss 高级数据管理-游标 为了处理SQL语句&#xff0c;存储过程进程分配一段内存区域来保存上下文联系。游标是指向上下文区域的句柄或指针。借助游…

【Pytroch】基于决策树算法的数据分类预测(Excel可直接替换数据)

【Pytroch】基于决策树算法的数据分类预测&#xff08;Excel可直接替换数据&#xff09; 1.模型原理2.数学公式3.文件结构4.Excel数据5.下载地址6.完整代码7.运行结果 1.模型原理 决策树是一种常用的机器学习算法&#xff0c;用于分类和回归任务。它通过树状结构表示数据的决策…

Opencv4基于C++的 实时人脸检测

文章目录: 一&#xff1a;环境配置搭建(VS2015Opencv4.6) 二&#xff1a;下资源文件 第一种&#xff1a;本地生成 第二种 直接下载 三&#xff1a;代码展示 窗口布局 main.cpp test.h test.cpp 效果图◕‿◕✌✌✌&#xff1a;opencv人脸识别效果图(请叫我真爱粉) 一&…

运算器组成实验

1.实验目的及要求 实验目的 1、熟悉双端口通用寄存器组的读写操作。 2、熟悉运算器的数据传送通路。 3、验证运算器74LS181的算术逻辑功能。 4、按给定数据&#xff0c;完成指定的算术、逻辑运算。 实验要求 1、做好实验预习。掌握运算器的数据传送通路和ALU的功能特性&…

7.3.tensorRT高级(2)-future、promise、condition_variable

目录 前言1. 生产者消费者模式2. 问答环节总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程&#xff0c;之前有看过一遍&#xff0c;但是没有做笔记&#xff0c;很多东西也忘了。这次重新撸一遍&#xff0c;顺便记记笔记。 本次课程学习 tensorRT 高级-future、promise…

【算法——双指针】LeetCode 1089 复写零

千万不要被这道题标注着“简单”迷惑了&#xff0c;实际上需要注意的细节很多。 题目描述&#xff1a; 解题思路&#xff1a; 正序遍历&#xff0c;确定结果数组的最后一个元素所在的位置&#xff1b;知道最后一个元素的位置后倒序进行填充。 先找到最后一个需要复写的数 先…

C++ 泛型编程:函数模板

文章目录 前言一、什么是泛型编程二、函数模板三、函数模板的使用四、多参数函数模板五&#xff0c;示例代码&#xff1a;总结 前言 当需要编写通用的代码以处理不同类型的数据时&#xff0c;C 中的函数模板是一个很有用的工具。函数模板允许我们编写一个通用的函数定义&#…

php从静态资源到动态内容

1、从HTML到PHP demo.php:后缀由html直接改为php,实际上当前页面已经变成了动态的php应用程序脚本 demo.php: 允许通过<?php ... ?>标签,添加php代码到当前脚本中 php标签内部代码由php.exe解释, php标签之外的代码原样输出,仍由web服务器解析 <!DOCTYPE html>…

Qt中将信号封装在一个继承类中的方法

QLabel标签类对应的信号如下&#xff1a; Qt中标签是没有双击&#xff08;double Click&#xff09;这个信号的&#xff1b; 需求一&#xff1a;若想双击标签使其能够改变标签中文字的内容&#xff0c;那么就需要自定义一个“双击”信号&#xff0c;并将其封装在QLabel类的派生…

使用vscode写vue文件代码有时不提示

背景&#xff1a; 安装了volar插件&#xff0c;但是在vue文件中导入js文件代码不提示&#xff0c;准确来说是有时提示有时不提示 解决方案&#xff1a; 插件冲突&#xff0c;卸载 JavaScript (ES6) code snippets 插件&#xff0c;这个插件在vue文件中适配不是很好。 很有可能…

【正版系统】2023热门短剧SAAS版开源 | 小程序+APP+公众号H5

当我们在刷百度、D音、K手等各种新闻或短视频时经常会刷到剧情很有吸引力的短剧广告&#xff0c;我们点击广告链接即可进入短剧小程序&#xff0c;小程序运营者通过先免费看几集为诱耳然后在情节高潮时弹出充值或开VIP会员才能继续看的模式来赚钱&#xff0c;以超级赘婿、乡村小…

电影数据可视化综合分析

数据可视化&分析实战 1.1 沈腾参演电影数据获取 1.2 电影数据可视化分析 目录 数据可视化&分析实战前言1. 数据认知2. 数据可视化2.1 解决matplotlib不能绘制中文字符的问题2.2 折线图2.3 柱状图绘制2.4 箱线图绘制2.5 饼图 3. Na值处理及相关性分析3.1 相关性分析3.2…

2023.08.13 学习周报

文章目录 摘要文献阅读1.题目2.要点3.问题4.解决方案5.本文贡献6.方法6.1 特征选择6.2 时间序列平稳性检测与数据分解6.3 基于GRU神经网络的PM2.5浓度预测 7.实验7.1 网络参数7.2 实验结果7.3 对比实验 8.讨论9.结论10.展望 PINNS模型1.自动微分2.全连接神经网络3.PINNs模型的P…

NavMeshPlus 2D寻路插件

插件地址:h8man/NavMeshPlus&#xff1a; Unity NavMesh 2D Pathfinding (github.com) 我对Unity官方是深恶痛觉,一个2D寻路至今都没想解决,这破引擎早点倒闭算了. 这插件是githun的开源项目,我本身是有写jps寻路的,但是无法解决多个单位互相阻挡的问题(可以解决但是有性能问…

Yolov5(一)VOC划分数据集、VOC转YOLO数据集

代码使用方法注意修改一下路径、验证集比例、类别名称&#xff0c;其他均不需要改动&#xff0c;自动划分训练集、验证集、建好全部文件夹、一键自动生成Yolo格式数据集在当前目录下&#xff0c;大家可以直接修改相应的配置文件进行训练。 目录 使用方法&#xff1a; 全部代码…

Window停止更新操作

在这里插入图片描述

Android平台RTMP推送或GB28181设备接入端如何实现采集audio音量放大?

我们在做Android平台RTMP推送和GB28181设备对接的时候&#xff0c;遇到这样的问题&#xff0c;有的设备&#xff0c;麦克风采集出来的audio&#xff0c;音量过高或过低&#xff0c;特别是有些设备&#xff0c;采集到的麦克风声音过低&#xff0c;导致播放端听不清前端采集的aud…

1216. 验证回文字符串 III;764. 最大加号标志;1135. 最低成本联通所有城市

1216. 验证回文字符串 III 核心思想&#xff1a;动态规划&#xff0c;这题需要一个思路的转换&#xff0c;删除最多k个字符判断是否为回文串&#xff0c;就相当于问你子序列中最长的回文串的长度是否比n-k长,就将这题转换为了最长回文子序列。 764. 最大加号标志 核心思想&am…