Java网络编程:IO,NIO与Netty

Java网络编程:IO,NIO与Netty

  • Java网络编程:IO,NIO与Netty
    • Java I/O相关概念
      • 同步与异步
      • 阻塞与非阻塞
      • OIO
      • NIO
      • AIO
      • reactor 模型
      • proactor 模型
    • Java IO应用场景
    • Netty简介
    • NIO与Netty
    • 生产使用

Java网络编程:IO,NIO与Netty

新公司新项目,项目需要在硬件和软件平台进行信息传递,具体来说使用Netty。硬件和软件使用socket连接,硬件作为客户端,软件平台作为服务的,使用TCP/IP通信。接着这个机会把Java IO和Netty重新学习了一下,总结在这里,不准确或错误的地方,欢迎指出来。

Java I/O相关概念

对于Java IO,可以分为同步与异步,也可以分为阻塞与非阻塞,下面对这些概念进行解释:

同步与异步

  • 同步与异步,描述的是用户线程与系统内核的交互方式。
  • 同步:用户线程发起I/O请求后,需要等待或者轮询内核I/O操作完成后,才能继续执行
  • 异步:用户线程发起I/O请求后,仍立即继续执行下去,当内核I/O操作完成后会通知用户线程,或者调用用户线程注册的回调函数。

阻塞与非阻塞

  • 阻塞与非阻塞,描述的是用户线程调用内核I/O操作的方式。
  • 阻塞:I/O操作彻底完成后,才能返回到用户空间。
  • 非阻塞:I/O操作被调用后,立刻返回给用户线程一个状态值,无须等待I/O操作完成
  • 一个IO操作分为两部分,发起I/O请求和实际I/O操作。
  • 阻塞I/O和非阻塞I/O的区别在于第一步,发起I/O请求是否会被阻塞,如果阻塞直到I/O操作完成,那就是传统的阻塞I/O,否则就是非阻塞I/O
  • 同步I/O和异步I/O在于第二步,如果实际I/O操作阻塞请求进程,那就是同步I/O,否则就是异步I/O。

OIO

  • 早期Java提供了java.net包用于开发网络应用,这类API被称为Java OIO(Old-blocking IO),也称阻塞IO,Java IO的第一代,就是普通的IO,也称作BIO。
  • java.io包下面,在我们初次学习Java语言时,也一定会去看或者使用这个包下面的类.
  • 它是线程同步阻塞的,每个线程只能绑定处理一个socket。当线程发起IO请求,不管内核是否准备好IO操作,从发起请求起,线程一直阻塞,直到操作完成。
  • 标准IO流程是基于字节流或字符流进行操作的

NIO

  • NIO,Java的New IO,非阻塞IO,也可以称为 Non-blocking IO,在java.nio包下,从Java 1.4引入。
  • NIO是基于通道(Channel)和缓冲区(Buffer)进行操作的,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。
  • 同步非阻塞通信,每个线程可以处理多个channel(异步)。当线程发起IO请求后,立即返回;内核在做好IO操作的准备之后,通过调用注册的回调函数通知线程做IO操作,线程开始阻塞,直到操作完成。
  • 其实是逐个channel处理的,发起IO请求后立刻返回并进入排队,等待IO准备好再去调用,就是非阻塞伪异步。
  • 选择器(Selector):Java NIO引入了选择器的概念,选择器用于监听多个通道的事件(例如连接打开、数据到达、数据读取)。因此单个线程可以监听多个数据通道,大大提升了单机的并发能力。

AIO

  • AIO(异步I/O),彻底的异步IO通信,NIO之后的版本,也称为“NIO.2”,在Java 1.7版本引入,使用方法与最早的标准I/O有很大的差异。
  • Java AIO采取“订阅-通知”的模式。应用程序向操作系统注册I/O监听,然后做自己的事情。
  • 当内核做好IO操作的准备之后,做IO操作,直到操作完成或者失败之后,再通过调用注册的回调函数通知应用程序线程
  • 在Windows系统,操作系统提供了IOCP(I/O CompletionPort,I/O完成端口);在Linux系统,使用epoll对异步I/O进行模拟

reactor 模型

reactor 模型:非阻塞同步网络模型,NIO使用的模型,事件分离器负责等待文件描述符或socket为读写操作准备就绪,然后将就绪事件传递给对应的处理器,最后由处理器负责完成实际的读写工作。

proactor 模型

proactor 模型:异步网络模型,AIO使用的模型。与reactor模型不同,proactor模型是起一个worker线程执行IO操作,成功后返回主线程。

Java IO应用场景

Java对IO的支持经历了这几个阶段:

  1. 阻塞IO:Java最早的IO,同步阻塞IO,一个线程一个连接。适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中。
  2. NIO:在JDK1.4中引入。NIO本身是基于事件驱动思想来完成的,其主要想解决的是BIO的大并发问题。NIO基于Reactor,当socket有流可读或可写入socket时,操作系统会相应的通知引用程序进行处理,应用再将流读取到缓冲区或写入操作系统。适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂。
  3. AIO:在JDK1.7中引入,这部分内容被称作NIO.2,主要在java.nio.channels包下增加了四个异步通道:AsynchronousSocketChannelAsynchronousServerSocketChannelAsynchronousFileChannelAsynchronousDatagramChannel。适用于连接数目多且连接比较长(重操作)的架构,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。

Netty简介

  • Java的IO接口功能基本完备,但是使用起来很繁琐。为了简化Java IO编程,Netty出现了。
  • Netty是第三方的Java IO框架,是一个提供异步事件驱动(Asynchronous Event-Driven)的网络应用框架。
  • Netty集成以上的几种IO接口,包括阻塞IO与NIO都支持,但主要是基于Java NIO API实现的。Netty内部封装了 Java NIO API的复杂性,并提供了线程池处理,使得开发NIO的应用变得简单。
  • Netty支持丰富的网络协议,TCP、UDP、HTTP、HTTP/2、WebSocket、SSL/TLS等
  • Netty对部分功能进行了重写和优化,在更加易用的同时,性能也得到了巨大的提升。
  • Netty有一个简单却不失强大的架构,主要由三部分组成:缓冲(ByteBuf),通道(Channel),事件模型(event model)。

NIO与Netty

  • 作为语言基础类库,Java 自身的 NIO 设计更偏底层,这本无可厚非,但是对于一线的应用开发者,其复杂性、扩展性等方面,就存在一定的局限了
  • 在基础 NIO 之上,Netty 构建了更加易用、高性能的网络框架,广泛应用于互联网、游戏、电信等各种领域。
  • 单独从性能角度,Netty 在基础的 NIO 等类库之上进行了很多改进,例如:更加优雅的 Reactor模式实现、灵活的线程模型、利用 EventLoop 等创新性的机制,可以非常高效地管理成百上千的 Channel。
  • 充分利用了 Java 的 Zero-Copy 机制,并且从多种角度,“斤斤计较”般的降低内存分配和回收的开销。例如,使用池化的 Direct Buffer 等技术,在提高 IO 性能的同时,减少了对象的创建和销毁;利用反射等技术直接操纵 SelectionKey,使用数组而不是 Java 容器等。
  • 使用更多本地代码。例如,直接利用 JNI 调用 Open SSL 等方式,获得比 Java 内建 SSL 引擎更好的性能。
  • 在通信协议、序列化等其他角度的优化。
  • 总的来说,Netty 并没有 Java 核心类库那些强烈的通用性、跨平台等各种负担,针对性能等特定目标以及 Linux 等特定环境,采取了一些极致的优化手段。

生产使用

  • 硬件设备作为客户端
  • 软件平台作为服务端
  • 使用TCP/IP通信传输数据
  • 数据格式使用事先约定好的数据包格式,包括报文头、消息数据体,每个字段都要规定所占字节长度
  • 使用Netty实现网络通信,使用LengthFieldBasedFrameDecoder基于长度字段的帧解码器
  • 硬件通过网络发生数据包,软件平台接收socket消息,对数据包解码处理,得到对应数据

你可能感兴趣的:(java,java,网络编程,Netty,Java,IO,NIO,NIO与Netty)