Java网络编程:Netty框架学习(一)---BIO、NIO、AIO等概念梳理

概述

Netty是一个致力于创建高性能网络应用程序的成熟的IO框架,相比较与直接使用底层的Java IO API, 你不需要先成为网络专家就可以基于Netty去构建复杂的网络应用。有很多开源中间件,它们的底层都使用了Netty

Java网络编程:Netty框架学习(一)---BIO、NIO、AIO等概念梳理_第1张图片
各类中间件

学习Netty之前我们需要认识主要的I/O模型

四类主要的I/O模型

  • 同步阻塞IO(Blocking IO)
  • 同步非阻塞IO(Non-blocking IO)
    这里所说的NIO(同步非阻塞IO)模型,并非Java的NIO(New IO)
  • IO多路复用(IO Multiplexing)
    即经典的Reactor反应器设计模式,有时也称为异步阻塞IO, Java中的Selector选择器和Linux中的epoll都是这种模型。
  • 异步IO(Asynchronous IO)
    异步IO,指的是用户空间与内核空间的调用方式反过来。用户空间的线程变成被动接受者,而内核空间成了主动调用者。这有点类似于Java中比较典型的回调模式,用户空间的线程向内核空间注册了各种IO事件的回调函数,由内核去主动调用。
    ※Linux中因为不完善,所以性能和IO多路复用差别不是很大,所以Netty是基于IO多路复用模型,而不是AIO

java中的NIO库

问 啥是NIO?
NIO 全称是Non-Blocking IO,也就是同步非阻塞IO(因为是对jdk1.4中原有的I/O功能做了改进,所以也称之为新I/O 即New-I/O)

NIO的特性

  • 面向缓冲区(Buffer)
  • 选择器(Selectors)
    选择器用于监听多个管道的事件,使用传统的阻塞时可以方便的知道什么时候可以进行读写,而使用非阻塞通道,选择器可以让我们知道什么时候通道准备好了
  • 非阻塞模式
  • 管道(Channel)
    管道(Channel):管道实际上就像传统IO中的流,到任何目的地(或来自任何地方)的所有数据都必须通过一个 Channel 对象

目前常见的NIO框架

  • Netty(主流版本为4.1)
  • Mina
  • Grizzly

Netty

Netty是一个高性能、异步事件驱动的NIO框架,它提供了对TCP、UDP和文件传输的支持,作为一个异步NIO框架,Netty的所有IO操作都是异步非阻塞的,通过Future-Listener机制,用户可以方便的主动获取或者通过通知机制获得IO操作结果。

netty 使用场景

  1. 互联网行业:在分布式系统中,各个节点之间需要远程服务调用,高性能的 RPC 框架必不可少
  2. 游戏行业:Netty 作为高性能的基础通信组件,它本身提供了 TCP/UDP 和 HTTP 协议栈。
    非常方便定制和开发私有协议栈,账号登录服务器,地图服务器之间可以方便的通过 Netty 进行高性能的通信
  3. 大数据领域:经典的 Hadoop 的高性能通信和序列化组件 Avro 的 RPC 框架,默认采用 Netty 进行跨界点通信,它的 Netty Service 基于 Netty 框架二次封装实现。还有著名的Kafka 底层也采用了Netty

对比传统BIO、IO复用模型、Netty 的非阻塞I/O模型

Java网络编程:Netty框架学习(一)---BIO、NIO、AIO等概念梳理_第2张图片
BIO

说明:
每个请求都需要独立的线程完成数据 Read,业务处理,数据 Write 的完整操作问题。当并发数较大时,需要创建大量线程来处理连接,系统资源占用较大。连接建立后,如果当前线程暂时没有数据可读,则线程就阻塞在 Read 操作上,造成线程资源浪费

Java网络编程:Netty框架学习(一)---BIO、NIO、AIO等概念梳理_第3张图片
I/O复用模型

说明:
在 I/O 复用模型中,会用到 Select,这个函数也会使进程阻塞,但是和阻塞 I/O 所不同的是这两个函数可以同时阻塞多个 I/O 操作。
而且可以同时对多个读操作,多个写操作的 I/O 函数进行检测,直到有数据可读或可写时,才真正调用 I/O 操作函数。

Netty 的非阻塞 I/O 的实现关键是基于 I/O 复用模型,这里用 Selector 对象表示:


Java网络编程:Netty框架学习(一)---BIO、NIO、AIO等概念梳理_第4张图片
Netty 的非阻塞 I/O

说明:
Netty 的 IO 线程 NioEventLoop 由于聚合了多路复用器 Selector,可以同时并发处理成百上千个客户端连接。
当线程从某客户端 Socket 通道进行读写数据时,若没有数据可用时,该线程可以进行其他任务。线程通常将非阻塞 IO 的空闲时间用于在其他通道上执行 IO 操作,所以单独的线程可以管理多个输入和输出通道。
由于读写操作都是非阻塞的,这就可以充分提升 IO 线程的运行效率,避免由于频繁 I/O 阻塞导致的线程挂起。
一个 I/O 线程可以并发处理 N 个客户端连接和读写操作,这从根本上解决了传统同步阻塞 I/O 一连接一线程模型,架构的性能、弹性伸缩能力和可靠性都得到了极大的提升。

Linux文件句柄数限制

在Linux下,通过调用ulimit命令,可以看到单个进程能够打开的最大文件句柄数量。
对于高并发、高负载的应用,就必须要调整这个系统参数,以适应处理并发处理大量连接的应用场景

#查看
> ulimit -n
#修改
> ulimit -n 500000

终极解除Linux系统的最大文件打开数量的限制,可以通过编辑Linux的极限配置文件/etc/security/limits.conf来解决,修改此文件,加入如下内容

#软性极限
soft nofile 500000
#硬性极限
hard nofile 500000

※在使用和安装目前非常火的分布式搜索引擎——ElasticSearch,就必须去修改这个文件,增加最大的文件句柄数的极限值
在服务器运行Netty时,也需要去解除文件句柄数量的限制,修改/etc/security/limits.conf文件即可。

你可能感兴趣的:(Java网络编程:Netty框架学习(一)---BIO、NIO、AIO等概念梳理)