《Netty权威指南》笔记 —— 第一章, 第二章

本文从Java I/O的演进开始,详细介绍了BIO、NIO和AIO的区别与优缺点,强调了NIO在多路复用、非阻塞I/O上的优势。同时,分析了Java NIO的不足,如API复杂和同步阻塞问题。最后,探讨了为何选择Netty作为NIO框架,包括其易用性、强大功能、高度定制性和高性能。
摘要由CSDN通过智能技术生成

第1章 Java I/O 的演进之路

I/O多路复用技术: 当需要同时处理多个客户端接入请求时, 可以利用多线程或者I/O多路复用技术进行处理.
I/O 多路复用技术通过把多个I/O的阻塞复用到同一个select的阻塞上, 从而使得系统在单线程的情况下可以同时处理多个服务端请求. 减少系统开销, 系统不需要创建新的额外进程或者线程.

应用场景

  • 服务器需要同时处理多个处于监听状态或者多个连接状态的套接字
  • 服务器需要同时处理多种网络协议的套接字

epoll 克服了select的缺点

  1. 支持一个进程打开的socket描述符 不受限制(仅首先于操作系统最大文件句柄数)
  2. I/O效率不会随着FD数目的增加而线性下降
  3. 使用mmap加速内核与用户空间的消息传递
  4. epoll的API更加简单

Java.NIO包

  • 异步I/O操作的缓冲区ByteBuffer等
  • 异步I/O操作的管道Pipe
  • 进行各种I/O操作的Channel, 包括ServerSocketChannel和SocketChannel

Java.NIO包的主要问题

  • 没有统一的文件属性(例如读写权限)
  • API能力比较弱, 例如目录的级联创建和递归遍历, 往往需要自己实现
  • 底层存储系统的一些高级API无法使用
  • 所有的文件操作都是同步阻塞调用, 不支持异步文件读写操作

第2章 NIO入门

BIO编程

  • Client/Server
    • 三次握手, socket通信
  • 通信模型: 通常由一个独立的Acceptor线程负责监听客户端的连接, 接受请求之后为每个客户端创建一个新的线程进行链路处理, 处理完后通过输出流返回应答给客户端
弊端
  • 缺乏弹性伸缩能力
  • 访问量增加后, 服务端的线程个数和客户端并发访问数呈1:1的关系, 线程是java虚拟机宝贵的系统资源, 程数膨胀会让系统的性能急剧下降
  • 在高性能服务器应用, 需要面向成千上万个客户端的并发连接, 这种模型显然无法满足高性能, 高并发接入.
    

伪异步I/O编程

改进线程链接1:1模型, 演进出了一种通过线程池或者消息队列实现 1个或者多个线程处理N个客户端的模型, 由于它的底层通信机制依然使用同步阻塞I/O, 所以被称为“伪同步”.

  • 连接线程比 M:N, M大于N
  • 当有新的客户端接入时, 将客户端的Socket封装成一个Task (该任务实现Java.lang.runnable接口)投递到后端的线程池中进行处理, JDK的线程池维护一个消息队列和N个活跃线程, 对消息队列中的人物进行处理. 由于线程池可以设置消息队列的大小和最大线程数, 因此它的资源占用是可控的, 无论多少个客户端并发访问,都不会导致资源耗尽和宕机
  • 采用了线程池实现, 避免了为每个请求都创建一个独立线程造成的线程资源耗尽问题. 但是由于底层仍然是同步阻塞模型, 因此无法从根本上解决问题.
弊端

当对Socket的输入流进行读取操作的时候, 它会一直阻塞下去, 知道发生以下三种事件:

  1. 有数据可读
  2. 可用数据已经读取完毕
  3. 发生空指针或者I/O异常

这意味着当对方操作比较缓慢或者网络传输缓慢时, 读取输入流的一方的通信线程将被长时间阻塞, 如果对方要60s才能够将数据发送完成, 读取一方的I/O线程也将会被同步阻塞60s, 其他只能排队.资源利用率低下.

NIO编程

缓冲区(Buffer) 是与原I/O的一个重要区别, 在面向流I/O中, 可以将数据直接写入或则将数据直接读到Stream对象中. NIO库中 都是用缓冲区来操作. 实际上, 缓冲区市个字节数组 bytebuffer

通道(Channel) 像是自来水管, 网络数据通过Channel读取和写入. 通道与流不同之处在于通道是双向的, 流是单向的, 通道可以读写同时 Channel是全双工, 比流更好映射底层操作系统的API.

Channel继承关系类
多路复用Selector

Selector会不断地轮询(poll) 注册在其上的Channel, 如果某个Channel上面发生读或者些事件, 这个channel就处于就绪状态, 会被Selector轮询出来, 然后通过selectionKey可以获得就绪Channel的集合,进行后续的I/O操作

一个多路复用Selector可以同时轮训多个channel, JDK采用了epoll() 代替传统的select实现, 所以它并没有最大连接句柄1024/2048 限制, 这也就意味着只需要一个线程负责Selector的轮询, 就可以接入成千上万的客户端.

NIO服务端通信序列图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值