Netty篇章(1)—— 核心原理介绍

终于进入到Netty框架的环节了,前面介绍了大量的Java-NIO的内容,核心的内容Selector、Channel、Buffer、Reactor掌握了,那么学起来Netty也是水到渠成的事情。如果没有掌握前面的内容那么学Netty会非常吃力,下面讲解Netty核心原理与概念。

Netty是一个Java NIO客户端/服务器框架,是一个为了快速开发可维护的高性能、高可扩展的网络服务器和客户端程序而提供的异步事件驱动基础框架和工具。如果要开发一个网络通信模块,那么Netty是首选,知名的Dubbo、Zookeeper、RocketMQ 网络通信模块全都是Netty实现的,我发现阿里的分布式框架网络通信模块很喜欢使用Netty作为网络通信框架。Netty的目标之一,是使通信开发可以做到“快速和轻松”。使用Netty除了能“快速和轻松”的开发TCP/UDP等自定义协议的通信程序之外,使用Netty还可以做到“快速和轻松”地开发应用层协议的通信程序,如FTP, SMTP, HTTP以及其他的传统应用层协议。 总之一句话,Netty是一款高性能、高可扩展性、能进行快速扩展以支持不同协议通信、完成不同业务处理的网络通信框架。

在使用Netty前,首先需要考虑一下JDK的版本, 建议使用JDK1.8。然后是Netty的版本,建议使用Netty 4.0以上的版本:

<dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.66.Final</version>
</dependency>

Netty中的Reactor反应器

前面一篇Reactor的文章不知道强调了多少次Reactor的概念,如果还不清楚,这里再次强调:Reactor就是一个单独的线程执行的Selector组件接受客户端IO事件的实例。粗暴理解成 Reactor = Thread + Selector。在Netty的实现中Reactor角色叫做NioEventLoop(事件循环),它就是封装了Selector组件对象和Thread线程实例。NioEventLoop类有两个重要的成员属性:一个是Thread线程类的成员,一个是Java NIO选择器的成员属性。 NioEventLoop的继承关系和主要的成员属性,如下图所示。

在这里插入图片描述

NioEventLoop和前面章节讲到反应器实现,在思路上是一致的:一个NioEventLoop拥有一个Thread线程,负责一个Java NIO Selector选择器的IO事件轮询。其实可以简单吧Reactor理解成Selector就行,在Netty中, EventLoop反应器和Channel通道的关系是啥呢?理论上来说,一个EventLoop反应器和NettyChannel通道是一对多的关系:一个反应器可以注册成千上万的通道。

在这里插入图片描述

后面系列文章将结合Channel、Handler等知识通过代码进行介绍,目前只要理解了NioEventLoop就是Reactor反应器即可,理解Reactor是什么就行。

Netty中的Channel通道

前面也讲过NIO中的Channel通道,反应器模式和通道紧密相关,反应器的查询和分发的IO事件都来自于Channel通道组件。Netty中不直接使用Java NIO的Channel通道组件,对Channel通道组件进行了自己的封装。Netty实现了一系列的Channel通道组件,为了支持多种通信协议,换句话说,对于每一种通信连接协议, Netty都实现了自己的通道。Netty中不直接使用Java NIO的Channel通道组件,对Channel通道组件进行了自己的封装。Netty实现了一系列的Channel通道组件,为了支持多种通信协议,换句话说,对于每一种通信连接协议, Netty都实现了自己的通道。

Netty中常见的通道类型如下:

  • NioSocketChannel:异步非阻塞TCP Socket传输通道。
  • NioServerSocketChannel:异步非阻塞TCP Socket服务器端监听通道。
  • NioDatagramChannel:异步非阻塞的UDP传输通道
  • OioSocketChannel:同步阻塞式TCP Socket传输通道。
  • OioServerSocketChannel:同步阻塞式TCP Socket服务器端监听通道。
  • OioDatagramChannel:同步阻塞式UDP传输通道。

不论是那种通道类型,在主要的API和使用方式上和NioSocketChannel类基本是相同的,更多是底层的传输协议不同,而Netty帮大家极大的屏蔽了传输差异,所以,如果没有特殊情况,的很多通道都可以参考NioSocketChannel通道。Netty只是做了封装,底层还是Java-NIO的Channel通道,继承关系如下:

在这里插入图片描述

Netty中的Handler处理器

在Netty中, EventLoop反应器内部有一个线程负责Java NIO选择器的事件的轮询,然后进行对应的数据分发。这里和经典Reactor模式的区别: Netty的IO事件分发(Dispatch) ,属于EventLoop的内部分发, 并没有直接将IO事件分发到EventLoop的外部。如何理解?假设发生了IO读事件,那么EventLoop将输入的数据读取到ByteBuf中。EventLoop读取到数据之后,再将输入数据分发到通道的Pipeline, 此次数据分发的目标,才是Netty的Handler处理器。也就是说IO事件还是自己读,只是将读到的数据放到Pipeline中,供程序员对数据进行处理,而这个处理也就是Handler处理器类要做的事情。Netty的Handler处理器分为两大类:第一类是ChannelInboundHandler入站处理器;第二类是ChannelOutboundHandler出站处理器,二者都继承了ChannelHandler处理器接口。

Ok@! 很多读者读到这开始懵逼了,什么出站入站嘛!我连Handler都不知道是啥呢?你又引入了什么出站处理器和入站处理器,还有什么乱七八糟的Pipeline是啥? 我是懂读者心里状态的,因为我学习的时候也是带着这些疑问硬啃完的,相信我,继续往下看你的疑问将柳暗花明。

前面介绍过Selector反应器,其中有个Selector选择器,如果客户端A已经连接了服务器,此时向服务器发送数据,那么对于服务器而言将产生一个IO读事件,通过Selector的select方法将查询到这个读事件,然后接下来对这个读事件进行处理。而对IO事件的处理就是处理器,处理器在前面我们讲解Reactor反应器中没有特意定义为一个类,而只是一个处理方法。而在Netty中,如果我们需要对已经查询到的IO事件进行处理,我们需要重写处理器类的一些读数据方法或者写数据方法,而这些处理器又分为ChannelOutboundHandler出站处理器和ChannelInboundHandler入站处理器。

那么什么是入站处理器呢?什么是出站处理器呢?Netty的出入站处理指的的API调用的方向是应用层开发维度的,你可以理解为当发生了IO读事件会被EventLoop查询到,然后分发到内部的IO事件处理方法, 之后把读取到的客户端数据发射到通道的Pipeline, 这里还没有讲解Pipeline的概念,你可以理解为一个数据流水线。然后这个数据就会在数据流水线中往下传播,其中就有ChannelInboundHandler入站处理器,处理器的方法read将被调用读取流进来的数据,然后程序员就可以在这里实现对数据的处理,例如解码、显示到界面,然后保存到数据库等操作。IO事件触发了,然后EventLoop读取数据把数据往Pipeline发送,其中经过入站处理器。这不就和废水处理厂一样的逻辑吗?数据就是废水,废水入站进行处理,处理完之后再向下传播或者终止。

明白了上述入站处理器之后,出站处理器就不难理解了吧!Netty中的出站处理具体指的是什么呢?指的是从ChannelOutboundHandler处理器到通道的某次IO操作,例如,在应用程序完成业务处理后,可以通过ChannelOutboundHandler出站处理器将处理的结果写入底层通道。它的最常用的一个方法就是write()方法,把数据写入到通道。最直观的理解就是通过出站处理器将服务器的数据进行处理,例如从数据库中查询,然后编码,然后再将处理的数据写到底层Channel通道中发送给客户端。Netty中的出站处理,不仅仅包括write()方法,还包括从Handler处理器到底层Channel的方向的其他操作。 Netty出站和Java NIO的出站在概念上有细微的区别,其实不需要分的这么清楚,入站就是读客户端的数据进行处理,出站就是服务器的数据处理完后发送出去,就这样理解。

无论是入站还是出站, Netty都提供了各自的默认适配器实现:

  • ChannelInboundHandler的默认实现为ChannelInboundHandlerAdapter (入站处理适配器) ;
  • ChannelOutboundHandler的默认实现为ChanneloutBoundHandlerAdapter(出站处理适配器)。

这两个默认的通道处理适配器,分别实现了基本的入站操作和出站操作功能。如果要实现自己的业务处理器,不需要从零开始去实现处理器的接口,只需要继承通道处理适配器即可。

NettyPipeline通道处理流水线

学习到现在,我们知道了Reactor是和Channel进行绑定的,但是上面的Handler和Channel如何建立连接关系呢?Netty设计了一个特殊的组件,叫做ChannelPipeline(通道处理流水线),它像一条管道,将一个通道的多个Handler处理器实例串在一起,形成一条流水线。ChannelPipeline(通道流水线)的默认实现,实际上被设计成一个双向链表。所有的Handler处理器实例被包装成了双向链表的节点,被加入到了ChannelPipeline(通道流水线)中。一个 Netty 通道拥有一个 ChannelPipeline 通道流水线类型的成员属性,该属性的名称叫做 pipeline。以入站处理为例。每一个来自通道的IO数据,都会进入一次ChannelPipeline通道流水线。在进入第一个Handler处理器后,这个IO数据将按照既定的从前往后次序,在流水线上不断地向后流动,流向下一个Handler处理器。如果后面没有其他的入站处理器,这就意味着这个IO数据在此次流水线中的处理结束了。如果在中间需要终止流动,可以选择将当前处理器的结果,不再交给下一个Handler处理器,流水线的执行也被截断了。

Netty的通道流水线与普通的流水线不同, Netty的流水线不是单向的,而是双向的,而普通的流水线基本都是单向的。 Netty是这样规定的:入站处理器Handler的执行次序,是从前到后,或者说从头到尾;出站处器Handler的执行次序,是从后到前。总之, IO事件在流水线上的执行次序,与IO事件的类型是有关系的 。除了流动的方向与IO操作类型有关之外,流动过程中所经过的处理器类型,也是与IO操作的类型有关。入站类型的IO操作, 只能从Inbound入站处理器类型的Handler向后传播;出站的IO操作, 只能从Outbound出站处理器类型的Handler向前传播。

在这里插入图片描述

到这里,Netty的各个组件就基本上介绍完毕,后面几期文章就会从代码的实现来讲解如何使用Netty框架。

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

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

相关文章

关于 LLM,你了解多少?

LLM定义 大语言模型&#xff08;LLM&#xff09;是一种基于大量文本数据训练的深度学习模型。它的主要功能是生成自然语言文本或理解语言文本的含义。这些模型可以处理多种自然语言任务&#xff0c;如文本分类、问答、对话等&#xff0c;是通向人工智能的一条重要途径。 LLM发…

Vue3当中通过script和defineOptions两种方式指定组件的name

在vue2当中我们可以通过name属性来指定组件的名称&#xff0c;这个name会显示在vue调试工具当中&#xff0c;方便我们进行调试&#xff1b;当我们想实现一个无限递归的菜单组件时&#xff0c;也需要用到这个name属性&#xff0c;没有name属性的组件是无法递归的。 在vue3当中&…

vue中使用锚点定位

vue中不能使用a标签来使用锚点定位&#xff0c;可以使用自带的scrollIntoView方法 1、首先获取对应的需要定位的盒子ID 2、然后添加scrollIntoView方法&#xff0c;定义效果 属性及其含义&#xff1a; block: "start",// 定义垂直方向的对齐&#xff0c;默认为 &q…

C++类的入门

C类 一&#xff1a;类的简介&#xff1a; C的类是一种用户定义的数据类型&#xff0c;用于封装数据和方法。它是面向对象编程的基本概念&#xff0c;允许程序员将数据和操作数据的方法组合在一起。类可以包含成员变量和成员函数&#xff0c;用于描述对象的属性和行为。通过类…

美创荣登“2023大数据产业年度最具投资价值”榜单

近日&#xff0c;由上海市经济和信息化委员会、上海市科学技术委员会指导&#xff0c;数据猿和上海大数据联盟主办的“第六届金猿季&魔方论坛——大数据产业发展论坛”在沪隆重召开&#xff0c;并重磅揭晓《2023大数据产业年度最具投资价值》榜单。 美创科技凭借在数据安全…

k8s-kubectl常用命令

一、基础命令 1.1 get 查询集群所有资源的详细信息&#xff0c;resource包括集群节点、运行的Pod、Deployment、Service等。 1.1.1 查询Pod kubectl get po -o wid 1.1.2 查询所有NameSpace kubectl get namespace 1.1.3 查询NameSpace下Pod kubectl get po --all-namespaces…

JAVA 学习 面试(二)多线程篇

Java多线程 线程池 线程池原理 创建方式&#xff1a;newFixedThreadPool (固定数目线程的线程池)、newCachedThreadPool(可缓存线程的线程池)、newSingleThreadExecutor(单线程的线程池)、newScheduledThreadPool(定时及周期执行的线程池)、new ThreadPoolExecutor() &#x…

Elasticsearch 常用信息

简述 本文针对 Elasticsearch&#xff08;简称ES&#xff09;集群6.x版本出现故障时&#xff0c;可通过提供的命令进行排查。 1、集群健康状态 集群健康状态状态说明red不是所有的主要分片都可用。表示该集群中存在不可用的主分片。可以理解为某个或者某几个索引存在主分片丢失…

AI破局之路:一名猎头高管的AI自学之旅——公众号

AI破局之路&#xff1a;一名猎头高管的AI自学之旅——公众号。 我是周知&#xff0c;有8年猎头行业经验深耕各类顶级科技企业。 2023年&#xff0c;应该有很多同行离开这个行业吧. 毕竟我们面临着前所未有的挑战。猎头行业的每一个参与者&#xff0c;无论是初入职场的猎头新人、…

2024最新科普:文件加密软件功能大盘点

随着信息化时代的到来&#xff0c;数据安全问题越来越受到人们的关注。 文件加密作为一种重要的数据保护手段&#xff0c;被广泛应用于企业和个人用户中。 本文将对文件加密软件的功能进行大盘点&#xff0c;帮助大家了解这一安全领域的知识。 一、文件加密软件的定义 文件加…

【issue-halcon例程学习】measure_arc.hdev

例程功能 检查倒角后铸件的细长孔之间的距离。 代码如下 read_image (Zeiss1, zeiss1) get_image_size (Zeiss1, Width, Height) dev_close_window () dev_open_window (0, 0, Width / 2, Height / 2, black, WindowHandle) set_display_font (WindowHandle, 14, mono, true,…

《代码之丑》学习笔记15——新需求破坏了代码,怎么办?

15 | 新需求破坏了代码&#xff0c;怎么办&#xff1f; 文章目录 15 | 新需求破坏了代码&#xff0c;怎么办&#xff1f;一次驳回的实现 一次定时提交的实现总结时刻 前面文章讲的所有坏味道都是告诉你如何在已有的代码中发现问题。不过你要明白&#xff0c;即便我们能够极尽所…

【STM32】USB程序烧录需要重新上电 软件复位方法

文章目录 一、问题二、解决思路2.1 直接插拔USB2.2 给芯片复位 三、解决方法3.1 别人的解决方法3.2 在下载界面进行设置 一、问题 最近学习STM32的USB功能&#xff0c;主要是想要使用虚拟串口功能&#xff08;VCP&#xff09;&#xff0c;发现每次烧录之后都需要重新上电才可以…

FRRouting学习(一) 配置日志文件

以配置isis event事件日志为例 1、在配置之前&#xff0c;/var/log/frr路径下是没有文件的&#xff1a; 2、在vtysh config之下输入&#xff1a;log file /var/log/frr/isisd.log debugging 后面的debugging表示日志级别&#xff0c;可以根据自己修改 3、配置好了之后&#xf…

Operation

contents 服务器一、相关概念1.1 云服务器与实例1.2 关于域名解析延时与80端口1.3 关于备案1.4 关于SSL证书1.5 关于SSL证书的签发1.6 关于SSL证书的部署1.7 关于LNMP和LAMP1.8 关于bt面板 二、单服务器单一级域名多网站2.1 创建多个二级域名2.2 解析二级域名绑定到服务器上2.3…

基于SpringBoot Vue求职招聘系统

大家好✌&#xff01;我是Dwzun。很高兴你能来阅读我&#xff0c;我会陆续更新Java后端、前端、数据库、项目案例等相关知识点总结&#xff0c;还为大家分享优质的实战项目&#xff0c;本人在Java项目开发领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目&#x…

codeforces 1354B

思维题 题目链接 题目大意 给定一个只包含 1 , 2 , 3 1,2,3 1,2,3的字符串&#xff0c;输出包含 1 , 2 , 3 1,2,3 1,2,3最短字串的长度 思路 重点是三个字符的位置&#xff0c;我们用三个变量来定义三个位置&#xff0c;用一个指针遍历数组不断更新三个位置&#xff0c;每次…

工业设备管理系统:助力企业实现数字化转型

随着工业4.0和智能制造的快速发展&#xff0c;数字化转型已成为企业提升竞争力、适应市场变化的必然选择。工业设备管理系统作为数字化转型的关键组成部分&#xff0c;能够为企业提供实时监控、数据分析、预警和远程控制等功能&#xff0c;助力企业实现数字化转型的目标。 一、…

debian12.4配置

文章目录 debian12.4配置概述笔记将非root用户添加到sudo组更换国内源配置ssh的客户端访问关闭屏保END debian12.4配置 概述 在虚拟机中装了一个debian12.4, 想配置ssh客户端连接, 出了问题. 配置乱了, 还好长了个心眼, 做了快照. 发现2个问题: debian12.4默认安装完, 有ss…

mysql生成最近24小时整点时间临时表

文章目录 生成最近24小时整点生成最近30天生成最近12个月 生成最近24小时整点 SELECT-- 每向下推1行, i比上次减去1b.*, i.*,DATE_FORMAT( DATE_SUB( NOW(), INTERVAL ( -( i : i - 1 ) ) HOUR ), %Y-%m-%d %H:00 ) AS time FROM-- 目的是生成12行数据( SELECTa FROM( SELECT…