Day18_Netty

文章目录

IO模型相关

同步与异步

同步:有一个活分为好多步骤,一个线程自己从头到尾自己把活干完(同步只有一个线程)
异步:有一个活分为好多步骤,至少有两个线程的情况下,A线程干活的情况下B线程也在干活,一起把这个活干完(异步至少有两个线程)

阻塞与非阻塞

阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态.,把自己“挂起”等待结果的叫阻塞,还可以干别的活叫非阻塞

阻塞就是 A任务执行时,B要阻塞等待。

非阻塞就是在执行A任务时,也可以执行其它任务(比如B任务)。

阻塞:假设你是一个餐厅的服务员,你正在等厨师做好一道菜给顾客。在厨师做菜的过程中,你什么都做不了,只能干等着,直到菜做好了你才能继续服务下一位顾客。这就是阻塞IO,你的工作(服务员的工作)被阻塞在了等待厨师做菜(IO操作)上

非阻塞:假设你是一个餐厅的服务员,你告诉厨师顾客要什么菜,然后你就去忙其他事情了(比如接待其他顾客)。每隔一段时间,你就去问一下厨师你的菜好了没有。这种方式虽然不会让你一直等着,但你需要不断地去询问,也就是“轮询”,这会消耗你的时间和精力(CPU资源)。

多路复用

多路复用:有一个selector专门负责监视多个IO操作然后及时反馈给当前线程,以便于当前线程可以专心搞其它事情(多路复用本质也是当前这一个线程在干活,所以它也是同步的,所以叫同步多路复用)

现在有一个多路复用器来帮你管理多个订餐请求。你告诉多路复用器你想要哪些餐厅的哪些菜,然后你就去忙其他事情了。多路复用器会帮你盯着这些餐厅,一旦有餐好了,他就会通知你来取。这样,你既可以处理多个订餐请求,又不需要一直等着或不断地去询问,大大提高了效率。

IO 模型

5种阻塞模型:同步阻塞I/O、同步非阻塞I/O、同步多路复用、异步阻塞(没有此情况)、异步非阻塞I/O、信号驱动 I/O

同步阻塞IO:是一个线程在处理IO请求,它处理这个客户端的IO的时候哪怕这个客户端的IO闲着它也不能处理别的客户端的IO,一个线程在干活所以是同步的,干活的时候不能干别的所以叫阻塞,所以它是同步阻塞IO

同步非阻塞IO:是一个线程在处理IO请求,它处理这个客户端的IO的时候如果这个客户端的IO闲着它可以处理别的客户端的IO,一个线程在干活所以是同步的,干活的时候可以干别的所以叫非阻塞,所以它是同步非阻塞IO

多路复用:有一个selector专门负责监视多个IO操作然后及时反馈给当前线程,以便于当前线程可以专心搞其它事情(多路复用本质也是当前这一个线程在干活,所以它也是同步的,所以叫同步多路复用)

异步阻塞(没有此情况)

异步非阻塞:有两个线程在干活,让另一个线程干活然后把结果告诉你

BIO、NIO、AIO

BIO:属于同步阻塞 IO 模型 。数据的读取写入必须阻塞在一个线程内等待其完成。

NIO:属于同步非阻塞的 I/O模型。网络通信基本都是NIO

AIO:(Asynchronous I/O)异步的IO模型。应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。目前来说 AIO 的应用还不是很广泛。Netty 之前也尝试使用过 AIO,不过又放弃了。这是因为,Netty使用了 AIO 之后,在 Linux 系统上的性能并没有多少提升。

缓冲区是什么意思?

缓冲区实质上是一个数组。在读取数据时,它是直接读到缓冲区中的。在写入数据时,它是写入到缓冲区中的。

种类:ByteBuffer、CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer

Java有哪些数据类型

这里是引用

基本数据类型sout打印出来的是数值, 引用数据类型sout打印出来的是对象的地址值
其中八种基本数据类型:byte、short、char‐‐>int‐‐>long‐‐>float‐‐>double,boolean
所占的空间大小:

	byte(1)
short(2)、char(2)
int(4)、long(8)
float(4)、double(8)

说说这 8 种基本数据类型对应的包装类型?
这八种基本类型都有对应的包装类分别为:Byte、Short、Character、Integer、Long、Float、Double、Boolean

那基本类型和包装类型有啥区别不?
Byte、Short、Character、Integer、Long、Float、Double、Boolean这些包装类的默认值是null,因为它们是对象类型。

基本类型是有默认值的:byte默认值0、short默认值0、char默认值’\u0000’、int默认值0、long默认值0L、float默认值0.0f、double默认值0.0d,boolean默认值false

零拷贝

零拷贝

传统的 IO 将一个文件通过 socket 写出,内部工作流程是这样的:

在传统的数据传输过程中,当应用程序需要从磁盘读取数据并通过网络发送时,通常需要经历以下步骤:

这里是引用

这个过程涉及了多次数据拷贝和上下文切换(用户态和内核态之间的切换),这会导致CPU资源的浪费和数据传输效率的降低。

“零拷贝”这个名字听起来很神奇,好像数据在传输过程中完全没有被拷贝一样。但实际上,这里的“零拷贝”是指减少了数据在用户空间和内核空间之间的拷贝次数,并不是没有拷贝而是减少了拷贝次数,特别是避免了将数据从内核空间拷贝到用户空间,然后再从用户空间拷贝回内核空间(如网络发送缓冲区)的过程。这样,数据的传输变得更加高效,减少了CPU的负担和内存带宽的占用。

Netty 的零拷贝了解么?

在 OS 层面上的 零拷贝通常指避免在 用户态(User-space) 与 内核态(Kernel-space) 之间来回拷贝数据。而在 Netty 层面 ,零拷贝主要体现在对于数据操作的优化。

Netty 中的零拷贝体现在以下几个方面

  1. 使用 Netty 提供的 CompositeByteBuf 类, 可以将多个ByteBuf 合并为一个逻辑上的 ByteBuf, 避免了各个 ByteBuf 之间的拷贝。
  2. ByteBuf 支持 slice 操作, 因此可以将 ByteBuf 分解为多个共享同一个存储区域的 ByteBuf, 避免了内存的拷贝。
  3. ByteBuf的duplicate操作

这里是引用
在这里插入图片描述
在这里插入图片描述

深拷贝和浅拷贝的区别是什么?

浅拷贝:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象。
深拷贝:被复制对象的所有变量都含有与原来的对象相同的值.而那些引用其他对象的变量将指向被复制过的新对象.而不再是原有的那些被引用的对象.换言之.深拷贝把要复制的对象所引用的对象都复制了一遍。

Netty的基本组件

Netty 是什么?

就简单用 3 点来概括一下 Netty 吧!

  1. Netty 是一个 基于 NIO 的 client-server(客户端服务器)框架,使用它可以快速简单地开发网络应用程序。
  2. 它极大地简化并优化了 TCP 和 UDP 套接字服务器等网络编程,并且性能以及安全性等很多方面甚至都要更好。
  3. 支持多种协议 如 FTP,SMTP,HTTP 以及各种二进制和基于文本的传统协议。
    易于开发,且性能、稳定性和灵活性都非常的好

Netty 基于 NIO,那为啥不直接用 NIO 呢? / 为什么要用 Netty?

不用 NIO 主要是因为 NIO 的编程模型复杂而且对编程功底要求比较高。
NIO 在面对断连重连、包丢失、粘包等问题时处理过程非常复杂。

Netty 具有下面这些优点:

  • 简单而强大的线程模型。
  • 自带编解码器解决 TCP 粘包/拆包问题。
  • Netty支持多种常见的网络协议,包括TCP、UDP、HTTP、WebSocket等。这使得它适用于各种应用场景
  • 比直接使用 Java 核心 API 有更高的吞吐量、更低的延迟、更低的资源消耗和更少的内存复制。
  • 经历了大型项目的使用和考验,而且很多开源项目都使用到了 Netty, 比如我们经常接触的 Dubbo、RocketMQ 等等。
  • 异步事件驱动:Netty采用基于事件驱动的模型,通过异步的方式处理网络操作。这允许在单线程上处理大量的并发连接,提高了系统的吞吐量和性能。
  • 高性能:Netty通过优化的事件循环、内存管理和零拷贝等技术,实现了出色的性能表现。
  • 支持并发和多连接:Netty通过使用多线程和高效的事件处理机制,能够轻松处理数千甚至数万个并发连接,适用于高并发场景。

Netty的核心组件是什么?

巧计:一个EventLoop绑定了多个Channel,一个Channel会关联一个ChannelPipeline,一个ChannelPipeline里面会有很多的ChannelHandler

Netty的核心组件包括以下几个主要部分:

  1. Channel(通道):
    • Channel代表了一个网络连接,可以是客户端到服务器的连接,也可以是服务器之间的连接。每个Channel都由一个EventLoop负责处理,而一个EventLoop可以管理多个Channel。
    • Channel是处理数据的通道。Channel负责所有的I/O操作(读取、写入、连接和绑定等)
  2. EventLoop(事件循环): 每个Channel都与一个EventLoop关联,它负责处理分配给它的所有Channel(通道)的所有事件。EventLoop会不断地轮询注册在其上的Channel,处理这些Channel上的IO事件,这样可以确保Channel的所有事件都在同一个线程中按顺序处理,从而避免了多线程并发带来的复杂性。一个EventLoop可能处理着多个channel的事件。一个EventLoop通常关联一个线程,而一个Netty应用可能有多个EventLoop,每个EventLoop运行在独立的线程上
  3. ChannelPipeline(通道管道):
    • ChannelPipeline是一个由一系列ChannelHandler组成的处理链。ChannelHandler如进行数据编解码、业务逻辑处理等。ChannelPipeline将这些ChannelHandler串联起来,形成一个处理链。
    • 每个Channel都有一个关联的ChannelPipeline,用于处理入站和出站的数据。
  4. ChannelHandler(通道处理器): 在Netty中,网络操作(如连接、读取数据、写入数据等)都被视为事件。当这些事件发生时,Netty会将这些事件传递给相应的事件处理器(Handler)。事件处理器就像是处理网络事件的“工人”,它们负责实现数据编解码、业务处理等。ChannelHandler可添加到ChannelPipeline中,形成一个处理链。
  5. ByteBuf(字节缓冲区): ByteBuf是Netty中用于存储和操作字节数据的缓冲区。它提供了灵活的API,支持池化、切片等高级特性,有助于提高性能和内存管理效率。
  6. ChannelFuture(通道未来): ChannelFuture表示异步操作的结果,例如I/O操作的成功、失败或取消。通过ChannelFuture,开发者可以注册监听器以处理操作完成时的回调。
  7. Bootstrap(引导类): Bootstrap是Netty用于启动客户端的引导类。它负责配置和启动Netty的客户端组件,包括设置Channel类型、EventLoop组、ChannelPipeline等。
  8. ServerBootstrap(服务器引导类): ServerBootstrap是Netty用于启动服务器的引导类。它包含了一些服务器独有的配置选项,如处理客户端连接请求、设置TCP参数等。

这些核心组件共同构建了Netty的基础架构,使得开发者能够通过简单而强大的API构建高性能的网络应用和服务。

这里是引用

什么是Channel和ChannelPipeline?

  1. Channel(通道):
    • Channel代表了一个网络连接,可以是客户端到服务器的连接,也可以是服务器之间的连接。每个Channel都由一个EventLoop负责处理,而一个EventLoop可以管理多个Channel。
    • Channel是处理数据的通道。Channel负责所有的I/O操作(读取、写入、连接和绑定等)
  2. ChannelPipeline(通道管道):
    • ChannelPipeline是一个由一系列ChannelHandler组成的处理链。ChannelHandler如进行数据编解码、业务逻辑处理等。ChannelPipeline将这些ChannelHandler串联起来,形成一个处理链。
    • 每个Channel都有一个关联的ChannelPipeline,用于处理入站和出站的数据。

Netty中的ChannelHandlerContext的作用是什么?

ChannelHandlerContext代表了一个ChannelHandler和ChannelPipeline之间的上下文,允许ChannelHandlerChannelPipelineChannel进行交互。

ChannelHandlerContext的主要作用包括:

  1. 与ChannelPipeline的交互: 通过ChannelHandlerContext,可以获得与当前ChannelHandler相关联的ChannelPipeline的引用。这允许你动态地修改ChannelPipeline,添加、移除或替换ChannelHandler

    // 获取 ChannelPipeline
    ChannelPipeline pipeline = ctx.pipeline();
    
  2. 与Channel的交互: 通过ChannelHandlerContext,可以获取关联的Channel实例。这使得可以进行底层的通信操作,例如写入数据或关闭通道。

    // 获取 Channel
    Channel channel = ctx.channel();
    
  3. 触发事件: ChannelHandlerContext可以触发各种事件,如数据读取、写入、通道激活等。通过fireXXX方法,可以在处理器链中传播事件。

    // 触发数据读取事件
    ctx.fireChannelRead(msg);
    
  4. 执行任务: 通过ChannelHandlerContext,可以提交任务到事件循环中执行。这对于异步处理和长时间运行的任务很有用。

    // 执行任务
    ctx.executor()</
  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乘风破浪的牛马

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值