一、开篇
阅读一个分布式开源项目的时候,最重要的就是了解这个项目的通信框架。
因为一个分布式的开源框架,通常是集群部署的,不同的节点和节点之间需要相互通信来完成复杂的功能,而阅读到这些源码的时候,如果不了解它通信机制的话,就会迷失在代码里,像走进了一片原始森林。
比如 HDFS ,使用的通信框架是自己封装的 Hadoop Rpc;Spark 底层通信就是用的 Netty;而最近阅读的 Kafka 源码,底层使用的是原生的 Java NIO。
所以本次,我们来聊一聊 Java NIO 的那些主要的知识点。
二、多图弄懂 NIO 三大核心概念
谈到 NIO,就会有三个核心的概念:通道、缓冲、选择器。
直接开门见山,或许听起来会有点迷茫,我们需要从头开始说。
1、通道
以前在并发要求不是很高的情况下,是 CPU 来全权处理输入输出的(中断),如下图:
用户程序向服务端发起读写请求,cpu 直接处理这些请求。这样有一个弊端,当 IO 请求非常多的时候,会大量占用 CPU,使得整个系统的处理能力会下降。
随着计算机的发展,出现了一种新的方式,使用 DMA 来全权处理 IO 请求,如下图:
DMA 是 Direct Memory Access,直接内存访问控制。
为什么要增加这个设备呢?是因为 CPU 中断方式不能满足数据传输速度的要求,因为在中断方式下,每次中断需要保存断点和现场,中断返回时,要恢复断点和现场。
所有这些原因,使得中断方式难以满足高速外设对传输速度的要求。
所以,就有了 DMA 这样的设备,在 DMA 方式的数据传输过程中,当 I/O 设备需要进行数据传送时,通过 DMA 控制器向 CPU 提出 DMA 传送请求,CPU 响应之后将让出系统总线,由 DMA 控制器接管总线进行数据传输,而此时 CPU 除了做一些初始化操作之外,可以去做自己的事情。
但是有了 DMA,仍然满足不了业务快速发展的需要,因为当 I/O 请求过多时,会出现总线冲突的问题。
所以后面就出现了通道(Channel),它和 DMA 不同的地方是,通道有自己的指令系统和程序,是一个协处理器;而 DMA 只能实现固定的数据传送控制。