《Netty权威指南》第1章 Java的I/O演进之路

起源

从前

  • 因为C和C++的优势,他们可以直接使用操作系统的异步IO能力
  • J2EE的服务器,几乎全部基于同步阻塞IO构建
  • NIO的框架不够成熟,且对小公司的使用门槛较高


    早期Java程序员开发IO系统,遇到的问题:

  • 没有数据缓冲区,性能存在问题

  • 没有Channel概念,只有输入流和输出流
  • 同步阻塞式BIO,通常导致通信线程长时间阻塞
    直到JDK1.4才退出Java NIO

1.1.1 Linux网络IO模型
Linux内核对所有外部设备当作文件来操作。对一个文件读写操作后会调用内核提供的系统命令,返回一个描述符(fd或socketfd)描述符就是一个数字,它指向内核中的一个结构体。

Unix提供了5种I/O模型:

  1. 阻塞IO:在进程空间调用recvfrom,系统调用直到数据包到达且复制到应用的缓冲区(数据从内核复制到用户空间)或发生错误时才返回。进程在它调用recvfrom开始到返回的时间都是阻塞的。
    这里写图片描述
  2. 非阻塞IO:recvfrom从应用层到内核的时候,如果该缓冲区没有数据的话,就直接返回一个EWOULDBLOCK错误,一般都对非阻塞IO模型进行轮询检查这个状态,看内核是不是有数据到来。
    这里写图片描述
  3. IO复用:Linux提供select/poll,进程通过将一个或多个fd传递给select或poll系统调用,阻塞在select操作上,这样select/poll可以帮我们侦测多个fd是否处于就绪状态。
  4. 信号驱动IO:开启套接口信号驱动IO功能,并通过系统调用sigaction执行一个信号处理函数。数据准备就绪时,为该进程生成一个SIGIO信号,通过信号回调通知应用程序调用recvfrom读取数据,通知主循环函数处理数据。
    这里写图片描述
  5. 异步IO:告知内核启动某个操作,并让内核在整个操作后,通知我们。和上一种的区别是:信号驱动IO由内核通知我们何时可以开始一个IO操作,异步IO由内核通知我们IO操作何时已经完成


    1.1.2 IO多路复用技术
    在IO编程过程中,当需要同时处理多个客户端接入请求时,可以利用多线程或者IO多路复用技术。后者是把多个IO阻塞复用到同一个select的阻塞上,从而使得系统在单线程情况下同时处理多个客户端请求。
    优势:开销小,无需创建新的进程或线程
    主要应用场景:服务器需要同时处理多个处于监听状态或者多个连接状态的套接字;

Linux选择epoll代替select。优点先省略。

猜你喜欢

转载自blog.csdn.net/qq_24572475/article/details/82263227