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.hqwc.cn/news/422295.html

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

相关文章

机械设计-哈工大课程学习-螺旋传动

二、摩擦类型 1、静态摩擦&#xff1a;这是身体静止时所经历的摩擦。换句话说&#xff0c;就是身体有运动倾向时的摩擦力。 2、动态摩擦&#xff1a;这是身体在运动时所经历的摩擦。也称为动摩擦。动摩擦有以下两种类型&#xff1a; ①滑动摩擦&#xff1a;一个物体在另一个…

【深蓝学院】移动机器人运动规划--第2章 基于搜索的路径规划--笔记

0. Outline 1. Graph Search Basis Configuration Space等概念 机器人配置: 指机器人位置和所有点的表示。 DOF: 指用于表示机器人配置所需的最小的实数坐标的数量n。 C-space: 包含机器人n维所有配置的空间。 在C-space中机器人的pose是一个点。 机器人在C-space中被表示为一…

stm32中的SPI

SPI的简介 文章目录 SPI的简介物理层协议层基本通讯过程起始和终止信号数据有效性CPOL/CPHA及通讯模式 STM3的SPI特性及架构通讯引脚时钟控制逻辑数据控制逻辑整体控制逻辑通讯过程 代码配置实现结构体的定义SPI时钟信号的定义SPI端口定义SPI命令 flash驱动代码初始化代码(配置…

算法基础学习|双指针算法

双指针算法 代码模板 for (int i 0, j 0; i < n; i ){while (j < i && check(i, j)) j ;// 具体问题的逻辑 } 常见问题分类&#xff1a;(1) 对于一个序列&#xff0c;用两个指针维护一段区间(2) 对于两个序列&#xff0c;维护某种次序&#xff0c;比如归并…

Day34 1005k次取反最大值 134加油站 135分发糖果

1005 k次取反最大值 给定一个整数数组 A&#xff0c;我们只能用以下方法修改该数组&#xff1a;我们选择某个索引 i 并将 A[i] 替换为 -A[i]&#xff0c;然后总共重复这个过程 K 次。&#xff08;我们可以多次选择同一个索引 i。&#xff09; 以这种方式修改数组后&#xff0…

从零学Java - Stream API

Java - Stream API 文章目录 Java - Stream API什么是流(Stream)?Stream 的特点Stream使用步骤1 创建 Stream流2 中间操作3 终止操作 什么是流(Stream)? 流&#xff08;Stream&#xff09;与集合类似&#xff0c;但集合中保存的是数据&#xff0c;而Stream中保存对集合或数组…

深入MySQL窗口函数:原理和应用

在现代数据库管理系统中&#xff0c;窗口函数&#xff08;Window Functions&#xff09;已经成为处理复杂数据分析任务的关键工具。MySQL从8.0版本开始引入了对窗口函数的支持&#xff0c;这极大地增强了其在数据分析和报表生成方面的能力。本文将深入探讨MySQL窗口函数的原理、…

JVM系列-4.类加载器

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring原理、JUC原理、Kafka原理、分布式技术原理、数据库技术、JVM原理&#x1f525;如果感觉博主的文…

体重管理的微观关键:脂肪组织、肠道菌群与肥胖的关联

谷禾健康 如今&#xff0c;全球约有 26 亿人&#xff08;约占世界人口的 40%&#xff09;受到超重或肥胖的影响。除非采取果断的行动来遏制这一日益严重的流行病&#xff0c;否则预计到 2035 年&#xff0c;将有超过 40 亿人&#xff0c;也就说世界人口的一半受到超重或肥胖的影…

2017年认证杯SPSSPRO杯数学建模B题(第二阶段)岁月的印记全过程文档及程序

2017年认证杯SPSSPRO杯数学建模 B题 岁月的印记 原题再现&#xff1a; 对同一个人来说&#xff0c;如果没有过改变面容的疾病、面部外伤或外科手术等经历&#xff0c;年轻和年老时的面容总有很大的相似性。人们在生活中也往往能够分辨出来两张不同年龄段的照片是不是同一个人…

数据结构Java版(4)——链表

一、概述 链表是一种常见的数据结构&#xff0c;用于存储一系列具有相同类型的数据元素。它由多个节点组成&#xff0c;每个节点包含一个数据元素和一个指向下一个节点的指针。 链表与数组不同&#xff0c;它的节点在内存中不是连续存储的&#xff0c;而是通过每个节点中的指针…

详解SpringCloud微服务技术栈:一文速通RabbitMQ,入门到实践

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位大四、研0学生&#xff0c;正在努力准备大四暑假的实习 &#x1f30c;上期文章&#xff1a;详解SpringCloud微服务技术栈&#xff1a;DockerCompose部署微服务集群 &#x1f4da;订阅专栏&#xff1a;微服务技术全家桶 希…