Netty中的核心概念

事件传播机制

当pipeline中有多个handler时,netty内部的事件是如何向后传递到每个handler中的?

结论:需要在当前handler中手动将当前事件传递下去

1,如果handler是直接实现的接口,使用ChannelHandlerContext的fireXXX方法

2,如果handler是继承Adapter,直接调用父类即可,比如:super.channelRead(ctx, msg);

super.channelRead(ctx, msg);的本质也是调用了Context中的fireActive方法

    @Skip
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        ctx.fireChannelActive();
    }

ChannelOutboundHandler 可以用来做什么?

1,响应数据包装,压缩,加密,…等通用功能

ChannelHandler 的执行顺序

BootStrap

1,Bootstrap是引导的意思,它的作用是配置网络参数并引导Netty程序启动,将各个组件都串起来

2,Netty中提供了2种类型的引导类,一种用于客户端(Bootstrap),而另一种(ServerBootstrap)用于服务器,它们之间的区别在于:

  • ServerBootstrap 需要指定绑定的端口,服务器开启监听接收连接,而 Bootstrap 则是想要连接到远程节点故需要对端的地址信息

  • 引导客户端只需要一个EventLoopGroup,服务端一般需要两个

Channel

Netty中的Channel是与网络套接字相关的,底层对应了一个socket连接,它负责基本的IO操作,比如:

  • read(),write() 等,它的一些核心作用有:

  • 获得当前网络连接的通道状态

  • 获得网络连接的配置参数(如缓冲区大小等)

  • 网络I/O操作

EventLoop和EventLoopGroup

1,Netty是基于事件驱动的,比如:连接就绪;数据读取;异常事件等,有了事件,就需要一个组件去监控事件的产生和事件的协调处理,这个组件就是EventLoop(事件循环)

2,Netty 中每个Channel 都会被分配到一个 EventLoop,一个 EventLoop 可以服务于多个 Channel的事件处理

3,每个 EventLoop 会占用一个 Thread,在这个Thread上处理相应的事件

4,EventLoopGroup 包含了一组EventLoop,可以理解成Netty的线程池

EventLoopGroup线程数有多大

// 主线程,不处理任何业务逻辑,只是接收客户的连接请求
EventLoopGroup boss = new NioEventLoopGroup();
// IO线程,处理注册其上Channel的I/O事件及其他Task
EventLoopGroup worker = new NioEventLoopGroup();

默认为当前CPU核心数*2

对于boss group,我们其实也只用到了其中的一个线程,因为服务端一般只会绑定一个端口启动

小结

Bootstrap的作用及类型

1,配置网络参数并引导netty程序启动,

2,ServerBootstrap作用于服务端,Bootstrap作用于客户端

Channel的作用

1,底层绑定的是一个网络连接socket,故可以获取网络通道状态

2,获取相关网络配置参数

3,处理相关操作,如IO

EventLoop和EventLoopGroup 的作用

1,EventLoop 检测并协调处理所注册Channel的相关事件,

2,EventLoop 绑定在一个线程上

3,EventLoopGroup 包含了一组EventLoop,可以理解成Netty的线程池

ChannelPipeline

1,ChannelHandler 是Netty的事件处理器,在其对应的事件回调方法中处理事件,是开发者介入的入口

2,ChannelHandlerContext 持有ChannelHandler并构成双向链表,handler基于它连接pipeline和channel

3,ChannelPipeline 提供了一个了容器,持有ChannelHandlerContext 构成的链表,并连接channel

在刚开始的时候,ChannelPipeline只有head和tail,当接收到了客户端的请求之后,准备初始化ChannelPipeline的时候会回调Handler方法,把Handler方法全都加入在管道当中。

channel中存放着这个套接字的各种信息。

ChannelHandler如何复用?

添加@Sharable注解

SimpleChannelInboundHandler

对于编写Netty数据入站处理器,可以选择继承ChannelInboundHandlerAdapter,也可以选择继承SimpleChannelInboundHandler,区别是什么?

    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        boolean release = true;

        try {
            if (this.acceptInboundMessage(msg)) {
                this.channelRead0(ctx, msg);
            } else {
                release = false;
                ctx.fireChannelRead(msg);
            }
        } finally {
            if (this.autoRelease && release) {
                ReferenceCountUtil.release(msg);
            }

        }

    }

继承SimpleChannelInboundHandler需要重写channelRead0方法,且可以通过泛型指定msg类型

SimpleChannelInboundHandler在接收到数据后会自动release掉数据占用的Bytebuf资源

ByteBuf的内存模型

1,堆缓冲区(HeapByteBuf):内存分配在jvm堆,分配和回收速度比较快,可以被JVM自动回收,缺点是,如果进行socket的IO读写,需要额外做一次内存复制,将堆内存对应的缓冲区复制到内核Channel中,性能会有一定程度的下降。由于在堆上被 JVM 管理,在不被使用时可以快速释放。

2,直接缓冲区(DirectByteBuf):内存分配的是堆外内存(系统内存),相比堆内存,它的分配和回收速度会慢一些,但是将它的数据写入或从Socket Channel中读取数据到它时,由于减少了一次内存拷贝,速度比堆内存块(netty内部默认使用)

3,复合缓冲区(CompositeByteBuf):顾名思义就是将两个不同的缓冲区从逻辑上合并,让使用更加方便。

ByteBuf的分配

Netty提供了ByteBufAllocator接口,有两个重要实现:PooledByteBufAllocator 和 UnpooledByteBufAllocator

1,PooledByteBufAllocator:实现了 ByteBuf 内存的池化,提高性能减少并最大限度地减少内存碎片,池化思想通过预先申请一块专用内存地址作为内存池进行管理,从而不需要每次都进行分配和释放(netty内部默认使用该方式,Android除外)

2,UnpooledByteBufAllocator:没有实现内存的池化,每次都会为ByteBuf对象重新分配内存

ByteBuf资源释放

1,unpool模式下,ByteBuf如果采用的是堆缓冲区可以由GC回收,但是如果采用的是直接缓冲区,就不受GC的管理,就得手动释放否则会发生内存泄露

2,pool模式下,某个ByteBuf对象关联的内存何时可以被归还给pool

引用计数法:ByteBuf对象的引用计数为0时,它关联的内存要么直接释放要么归还到池,Netty提供了ReferenceCounted接口

ReferenceCountUtil.release(buf)

什么时候释放?

1,数据入站能自动释放的地方:TailContext(前提是事件能传递到这),继承SimpleChannelInboundHandler

2,数据出站能自动释放的地方:HeadContext 出站消息一般是由应用所申请,到达最后一站时,经过一轮复杂的调用,在flush完成后终将被release掉

1,对于入站消息:

  • 随着事件向后传递,依然将原Bytebuf对象向后传,如果能到TailContext则会自动释放该ByteBuf

  • 事件传递的过程中,向后传递的是新的ByteBuf对象,则有必要手动释放原ByteBuf

  • 在可以的情况下选择继承SimpleChannelInboundHandler是个不错的选择

2,对于出站消息:

  • 应用的ByteBuf对象能走到HeadContext,则在flush后会释放

  • 事件传递的过程中,向后传递的是新的ByteBuf对象,则有必要手动释放原ByteBuf

通过Wrap操作可以快速转换或得到一个ByteBuf对象,Unpooled 工具类中提供了很多重载的wrappedBuffer方法

Netty Future

Netty 自己实现的 Future 继承了 JDK 的 Future,新增了 Listener 机制,任务结束会回调Listener

    public void testNettyFuture2() throws InterruptedException {
        EventLoopGroup group = new NioEventLoopGroup(1);

        Future<String> future = group.submit( () ->{
            log.info("---异步线程执行任务开始----");
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("---异步线程执行任务结束----");
            return "hello netty future";
        });

        //基于future 添加监听
        /*future.addListener(new GenericFutureListener<Future<? super String>>() {
            @Override
            public void operationComplete(Future<? super String> future) throws Exception {
                future.get();
            }
        });*/
        future.addListener( future1 -> {
            log.info("---收到异步线程执行任务结果通知----执行结果是;{}",future1.get());
        });

        log.info("---主线程向后执行----");
        TimeUnit.SECONDS.sleep(10);
    }

Netty Promise

1,Netty的Future基于JDK Future增加了Listener机制,但是Listener的触发则是需要等到异步任务执行结束,而任务大都是一个Runnable或者Callable,也就是需要等到其run()方法或者call()方法返回后才会触发Listener的执行,整个过程无法人为干预。

2,Netty的 Promise接口扩展了Netty的Future接口,它可以设置异步执行的结果并触发Listener,比如在IO操作过程,不管是顺利完成、还是发生异常,都可以设置Promise的结果,并且通知Promise的

public void testNettyPromise() throws InterruptedException {
        EventLoopGroup group = new NioEventLoopGroup();
        Promise promise = new DefaultPromise(group.next());// promise 绑定到 eventLoop上
        
        group.submit(()->{
            log.info("---异步线程执行任务开始----");
            try {
                // int i = 1/0;
                TimeUnit.SECONDS.sleep(3);
                log.info("first");
                promise.setSuccess("hello netty promise");

                TimeUnit.SECONDS.sleep(3);
                log.info("two");
                log.info("---异步线程执行任务结束----");
                log.info("finish");

            } catch (Throwable e) {
                log.info("exception ={}",e.getMessage());
                promise.setFailure(e);
            }
        });

        promise.addListener( future -> {
            if (future.isSuccess()) {
                log.info("----异步任务执行结果:{}",future.get());
            }else {
                log.info("异步任务执行失败,exception={}",future.cause().getMessage());
            }
        });

        log.info("---主线程----");
        TimeUnit.SECONDS.sleep(10);

    }

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

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

相关文章

针对BSV区块链新推出的网络访问规则NAR和警报系统AS的解释与问答

​​发表时间&#xff1a;2024年2月22日 BSV区块链社区团队最近开设了一个Twitter&#xff08;X&#xff09;话题空间&#xff0c;讨论BSV区块链协会最新推出的网络访问规则和警报系统的相关问题。 本次讨论由BSV区块链社区负责人Brett Banfe主持&#xff0c;以便社区成员更好…

【开源】SpringBoot框架开发毕业生追踪系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 登陆注册模块2.2 学生基本配置模块2.3 就业状况模块2.4 学历深造模块2.5 信息汇总分析模块2.6 校友论坛模块 三、系统设计3.1 用例设计3.2 实体设计 四、系统展示五、核心代码5.1 查询我的就业状况5.2 初始化就业状况5.…

正则表达式总结-满满干货拿走不谢

&#x1f341;博主简介&#xff1a; &#x1f3c5;云计算领域优质创作者 &#x1f3c5;2022年CSDN新星计划python赛道第一名 &#x1f3c5;2022年CSDN原力计划优质作者 &#x1f3c5;阿里云ACE认证高级工程师 &#x1f3c5;阿里云开发者社区专…

elasticsearch基础学习

elasticsearch简介 什么是elasticsearch elasticsearch&#xff08;简称es&#xff09;&#xff0c;其核心是 Elastic Stack&#xff0c;es是一个基于 Apache Lucene&#xff08;TM&#xff09;的开源的高扩展的分布式全文检索引擎&#xff0c;它可以近乎实时的存储、检索数据…

nginx stream四层加载多个子配

nginx.conf中写 stream.ini中写 gc.ini配置 在这里插入图片描述 nginx -t

第四天 Kubernetes集群的日志及监控-更新版

第四天 Kubernetes集群的日志及监控 k8s日志收集架构 https://kubernetes.io/docs/concepts/cluster-administration/logging/ 总体分为三种方式&#xff1a; 使用在每个节点上运行的节点级日志记录代理。在应用程序的 pod 中&#xff0c;包含专门记录日志的 sidecar 容器。…

问了 Gemini 1.5 Pro 五个问题,找到了初遇ChatGPT的感觉

一个月前&#xff08;2月15日&#xff09;&#xff0c;Sora和 Gemini 1.5 同时推出&#xff0c;这个故事很多人都听过了&#xff0c;Google 被冠以 AI 界汪峰的名头。 人们纷纷震惊于 Sora 的强大&#xff0c;讨论 Sora 是不是世界模型。而 Gemini 1.5 的第一个模型 Gemini 1.…

静态HTML5接入海康websocket视频流|海康ws视频流接入H5页面

引言 海康提供了vue实现插件播放视频的实例&#xff0c;实现取流失败了之后重新获取新的流播放视频&#xff0c;但是在很多情况下需要在静态HTML项目中进行视频的播放&#xff0c;于是引出此文。 海康开放平台SDK下载地址&#xff1a;https://open.hikvision.com/download/5c6…

【CSP试题回顾】202309-1-坐标变换(其一)

CSP-202309-1-坐标变换&#xff08;其一&#xff09; 解题代码 #include <iostream> using namespace std;long long n, m, dx, dy, x, y;int main() {cin >> n >> m;for (size_t i 0; i < n; i){int dx_i, dy_i;cin >> dx_i >> dy_i;dx …

【IEEE】Multimodal Machine Learning: A Survey and Taxonomy

不废话&#xff0c;先上思维导图&#xff0c;哈哈哈&#xff01; 论文题目Machine Learning: A Survey and Taxonomy作者Tadas Baltrusaitis , Chaitanya Ahuja , and Louis-Philippe Morency状态已读完会议或者期刊名称IEEE TRANSACTIONS ON PATTERN ANALYSIS AND MACHINE IN…

【视频图像取证篇】模糊图像增强技术之锐化类滤波场景应用小结

【视频图像取证篇】模糊图像增强技术之锐化类滤波场景应用小结 模糊图像增强技术之锐化类滤波场景应用小结—【蘇小沐】 &#xff08;一&#xff09;锐化类滤波器 模糊消除类滤波器&#xff08;Remove blur / Unsharpness&#xff09;。 通用去模糊滤波器&#xff1a;针对大…

Excel·VBA指定目标值切割分组

看到一个帖子《excel吧-数据切断分组问题》&#xff0c;对1列数据按指定长度进行切割分组&#xff0c;获取每组的长度组成方式 VBA代码 Sub 数据分割()Dim arr, target, brr, res, x&, y&, i&, 差额, trr(1 To 2) trr(0)为数值&#xff0c;trr(1)为组成方式arr…

【工具篇】我用Anki半个月背完了408

&#x1f60a;你好&#xff0c;我是小航&#xff0c;一个正在变秃、变强的文艺倾年。 &#x1f514;本文讲解Anki工具的高效使用&#xff0c;期待与你一同探索、学习、进步&#xff0c;一起卷起来叭&#xff01; 目录 一、记忆的原理二、Anki是什么三、同步服务器搭建 一、记忆…

牛客DP34 前缀和

解题思路 题目解析如图 思路 算出每个位置的到第一个位置的总和 比如 第一个位置 1 总和 1 第二个位置 2 总和 3 第三个位置 4 总和 7 要算 2到3 位置的前缀和 用3位置的总和减去1位置的总和即可 还要处理一个边界情况 如果1到1位置的前缀和那么就是 …

为 java 开发者设计的性能测试框架,用于压测+测试报告生成

拓展阅读 junit5 系列教程 基于 junit5 实现 junitperf 源码分析 Auto generate mock data for java test.(便于 Java 测试自动生成对象信息) Junit performance rely on junit5 and jdk8.(java 性能测试框架。压测测试报告生成。) junitperf junitperf 是一款为 java 开…

2024-03-18 作业

作业要求&#xff1a; 1> 将广播发送端和接收端各实现一遍 2> 将组播发送端和接收端各实现一遍 3> 将流式域套接字的服务器端和客户端各实现一遍 1&#xff1a;将广播发送端和接收端各实现一遍 运行代码&#xff1a; 服务端&#xff1a; 客户端&#xff1a; 运行截…

视频号带货做的人多吗?这个项目究竟靠不靠谱呢?

在当下互联网经济的浪潮中&#xff0c;视频号带货已经成为了一种新兴的商业模式&#xff0c;吸引了众多创业者和商家的目光。那么&#xff0c;视频号带货做的人多吗?这个项目究竟靠不靠谱呢?&#xff0c;接下来&#xff0c;一起看看本文的介绍吧。 首先&#xff0c;我们来看视…

ROS Kinetic通信编程:话题、服务、动作编程 opencv学习使用

文章目录 一、话题编程二、服务编程三、动作编程四、安装opencv 图片特效示例五、视频示例1. 虚拟机获取摄像头权限2. 播放视频3. 录制视频 接上篇&#xff0c;继续学习ROS通信编程基础 一、话题编程 步骤&#xff1a; 创建发布者 初始化ROS节点向ROS Master注册节点信息&…

Java 设计模式系列:行为型-观察者模式

简介 观察者模式是一种行为型设计模式&#xff0c;又被称为发布-订阅&#xff08;Publish/Subscribe&#xff09;模式&#xff0c;它定义了对象之间的一对多依赖关系&#xff0c;当一个对象的状态发生改变时&#xff0c;所有依赖于它的对象都会得到通知并被自动更新。 观察者…

configmap nginx.conf报错:invalid number of arguments in “proxy_set_header“

追加>> cat << EOF >> a.txt ###############gradle############## abcdefg chineewew ###############gradle############## EOF 覆盖> cat << EOF > /etc/profile ###############gradle############## 121321231 121231 ###############grad…
最新文章