首页 > 其他分享 >Netty(1)——NIO基础

Netty(1)——NIO基础

时间:2023-01-15 13:13:10浏览次数:38  
标签:Netty Java NIO 基础 线程 内存 IO Channel

本篇主要介绍Java NIO的基本原理和主要组件

Netty是由JBOSS提供的Java开源网络应用程序框架,其底层是基于Java提供的NIO能力实现的。因此为了掌握Netty的底层原理,需要首先了解Java NIO的原理。

NIO

计算机主要由CPU、内存、外存、IO设备等硬件组成,计算机执行计算的过程就是CPU从内存中获取数据,进行计算,然后再将计算结果写入内存中。但由于内存非常昂贵且下电后数据会丢失,计算机需要使用外存来持久化存储大规模的数据,外存提供了大量的存储空间,代价是其存取速度远小于内存。除了读取外存数据,计算机还可以从网络设备获取网络中的数据,受网络传输速度的限制,计算机获取网络数据的速度也远小于其读取内存的速度。

对于存取这些低速IO设备,操作系统(如Linux)提供了5种不同的IO模型。对于Java来说,其最先提供的就是基于最简单的阻塞式IO模型实现的BIO(Blocking IO)库。当调用BIO库读取硬盘中的数据时,用户进程会一直被阻塞在读数据的接口上,直到数据被操作系统从硬盘中获取出来并返回给用户,这时用户进程才能继续向下执行。由于读取硬盘速度相比CPU计算速度慢很多,进程就会一直被卡在读取数据这里,用户体验就是进程没有响应。即使CPU处于空闲状态,也无法使用CPU进行其他工作。这就浪费了大量的资源,同时也给用户造成了不好的体验。

除了最传统的阻塞式IO,操作系统还提供了其他几种改进的IO模型,总体思想都是尽可能减少用户进程阻塞在IO上的时间,在进行慢速设备IO时,进程无需等待,可以继续处理其他指令,当数据获取完成时操作系统再通知用户进程可以进行后续的数据处理操作。因此Java在1.4版本后就推出了一套新的IO接口NIO(New IO),这套IO接口基于多路复用IO模型,提供了非阻塞的IO能力,因此NIO中的N也可以理解为Non-blocking。这套NIO接口实现了只用一个线程来轮询等待所有应用进程的IO就绪状态,当某个应用进程的IO状态就绪时,再通知对应进程进行数据读写的操作。这就避免了每个应用进程在IO时被阻塞,为开发高性能和高并发的应用提供了关键能力。

NIO的3个核心组件

  • Channel
  • Buffer
  • Selector

Channel(通道)

image

Channel 是 NIO 的核心概念,它表示一个打开的连接,是数据读写的双向通道,这个连接可以连接到 I/O 设备(例如:磁盘文件,Socket)或者一个支持 I/O 访问的应用程序,Java NIO 使用缓冲区和通道来进行数据传输。

Channel的主要实现类有:

  • FileChannel(读写文件)
  • DatagramChannel(UDP编程)
  • SocketChannel(TCP编程)
  • ServerSocketChannel(TCP编程)

Buffer(缓冲区)

Buffer是NIO的另一个核心概念,NIO库操作数据都是通过缓冲区处理的,在数据读写的过程都要先经过缓冲区,然后再从缓冲区中按照块来处理数据。

image

从类图中可以看到,7 种数据类型对应着 7 种子类,这些名字是 Heap 开头子类,数据是存放在 JVM 堆中的。

MappedByteBuffer

MappedByteBuffer存放在堆外直接内存中,可以与文件进行映射。

通过java.nio包和MappedByteBuffer允许Java程序直接从内存中读取文件内容,通过将整个或部分文件映射到内存,由操作系统来处理加载请求和写入文件,应用只需要和内存打交道,这使得IO操作非常快。

Mmap内存映射和普通标准IO操作的本质区别在于它并不需要将文件中的数据先拷贝至OS的内核IO缓冲区,而是可以直接将用户进程私有地址空间中的一块区域与文件对象建立映射关系,这样程序就好像可以直接从内存中完成对文件读/写操作一样。

Selector(选择器)

概念继承于操作系统IO模型中多路复用IO模型中的selector,其主要作用是,用户可以把所有读写Channel都注册在某个Selector上,Selector会不断的轮询注册在上面的所有channel,如果某个channel为读写等事件做好准备,那么就处于就绪状态,通过Selector可以不断轮询发现出就绪的channel,进行后续的IO操作。为何要做这种设计呢?

如果每一个Channel都需要一个线程来为其IO过程提供服务,则会占用大量的内存,CPU需要在很多线程间进行切换,有太多额外开销,而且随着连接数量增加,线程数量会达到上限,无法支持大连接数。

有一种解决方案是使用有固定线程数量的线程池来处理所有连接请求,但线程池中的线程一旦被占用,就要阻塞等待IO完成才能被其他连接使用,如果IO请求花费时间很长,那会导致后续的大量IO请求需要排队等待。这种情况只适合处理短连接比较多的场景。

针对连接数量非常多,数据流量比较少的场景,多路复用的IO模型就比较适合。如下图所示,每一个Channel可以把自己注册到一个独立运行的Selector线程中,这个Selector线程会轮询所有Channel的读写状态,当发现一个就绪的Channel时,就可以使用工作线程为这个Channel提供服务。这样工作线程就不需要阻塞在某一个Channel上,只有真正要进行数据读写时才分配给某个Channel,极大提高了线程的利用率。

image

标签:Netty,Java,NIO,基础,线程,内存,IO,Channel
From: https://www.cnblogs.com/leometeor/p/17052864.html

相关文章

  • MC群组服开服教程系列七: 基础指令插件
    插件简介EssentialsX我们这里不介绍cmi了,这个是收费插件。EssentialsX是Spigot服务器的必备插件,为任何大小和规模的服务器提供核心功能。这些功能包括:玩家设置家......
  • Markdown最基础语法内容
    基础常用语法(大多符号后都要跟一个空格)一、标题1.使用#号可表示1-6级标题,一级标题对应一个#号,二级标题对应两个#号,以此类推。#不要漏了符号和内容之间的空格一......
  • JAVASE基础强化Day2
    总结:数据类型:基本数据类型,引用数据类型八大基本数据类型:Byte:字节类型:1个字节,8个bit,在内存中开辟8个bit的空间每个bit就是二进制的 Short:2个字节,8*2=16个bit,在内存中......
  • Python 基础实战
    1.概述本节实现一个文件管理程序,该程序会使用到如下知识点:函数面向对象采用面向对象的程序设计方法对数据建模异常处理使用异常处理和文件相关的错误,例如文件不存......
  • 语言基础
    语法时间复杂度分析常数优化......
  • java基础教程:IO流
    一:IO流的分类1)按流向分:输入流:读取数据,把持久设备的数据读取到内存中。输出流:写出数据,把内存的数据写出到持久设备。2)按数据类型分:计算机中一切数据都是:字节数据。字符数据:底......
  • Java基础教程:ArrayList入门
    1ArrayList类概述什么是集合提供一种存储空间可变的存储模型,存储的数据容量可以发生改变ArrayList集合的特点底层是数组实现的,长度可以变化泛型的使用用于约束集合中存储......
  • 【核反应堆物理分析】1-反应堆核物理基础:简单单的中子物理学
    HG-NRE-P101反应堆核物理基础1.中子与原子核的作用1.1中子与中子核反应反应堆核物理,实际上就是堆内中子的物理学。中子是组成原子核的粒子之一,其静止质量\(m\)稍大于......
  • Date and Time 日期时间 – 开发中的基础知识
    前言日期,时间几乎是每个项目都会接触到的.作为程序员必须对它有所了解.这篇想聊聊它们的基础知识.  以前写的文章以前写过好几篇,但是非常乱.这篇就作为综合整......
  • 04.Java基础语法
    一元运算符Java基础语法一、注释、标识符、关键字注释Java中的注释有三种:​ 单行注释​ 多行注释​ 文档注释publicclassHello_World{//两个斜杠就是一个......