Netty快速入门(01)Linux I/O模型介绍
Netty简述
Netty是一个高性能的网络编程框架。
上面提到了几个关键的字眼,高性能,网络编程,框架。这些概括Netty的本质。
Netty是一个NIO客户端服务器框架,可以快速轻松地开发协议服务器和客户端等网络应用程序。它极大地简化并简化了TCP和UDP套接字服务器等网络编程。
“快速简便”并不意味着最终的应用程序会受到可维护性或性能问题的影响。Netty经过精心设计,具有丰富的协议,如FTP,SMTP,HTTP以及各种二进制和基于文本的传统协议。因此,Netty成功地找到了一种在不妥协的情况下实现易于开发,性能,稳定性和灵活性的方法。
先来简单看一下Netty官网的架构图:
从图中可以看出,Netty的架构分为三块,核心(Core),通信服务(Transport Services)还有各种协议(Protocol Support)。我们想象将来要学习的内容都和这些有关系。通过架构图对其有个基本印象。
Linux I/O 模型
在Linux中,将I/O模型分为五种类型:
阻塞式 I/O 模型
非阻塞式 I/O 模型
I/O 复用
信号驱动式 I/O
异步 I/O
Linux中的I/O流程概括来说可以分为两步:
1、等待数据准备好(Waiting for the data to be ready)
2、从内核向进程复制数据(Copying the data from the kernel to the process)
来看下面的图片:
从上面的流程可以看出,首先是内核空间把数据从硬件(磁盘)中读到内核空间的缓冲区中,进行这一步操作时,数据处于内核态,通过磁盘驱动器,把数据从磁盘读到内核缓冲区来。下一步是把数据从内核缓冲区拷贝到用户空间的缓冲区,数据由内核态变为用户态。
知识普及:Linux中的程序大致运行在两个空间,自己的程序运行在用户空间,用户空间的权限有限,相对的另外一个空间是内核空间,比如驱动程序或者一些核心的系统调用都是在内核空间完成的。我们的I/O操作当在一个用户空间做系统调用的时候,数据会自动从用户态变到内核态来进行操作,完成了以后再从内核空间拷贝到用户空间。这种状态的切换是为了保证安全。比如在我们32位的操作系统中,大部分是4G的内存,一般前面一个G主要是内核态使用,后面三个G是用户态使用。
阻塞式 I/O 模型
阻塞式I/O是我们最常见的一种IO,当我们发起一个IO请求之后,开始进行系统调用,数据变为内核态,这两个阶段是一直处于阻塞的。数据开始从磁盘拷贝到内核空间,处理完后再从内核空间拷贝到应用空间,数据变为用户态。这整个的过程涉及到的所有程序线程都是在等待状态。比如我们Java普通的Socket编程,就是这样一个流程。整个过程中数据没有完成前,接收方都是出于等待状态,这就是阻塞式IO模型。明显可见效率不会高。
非阻塞式 I/O 模型
这种方式的特点是调用的时候不会等待(也就是不会阻塞),系统如果没有数据,就会立刻告诉你现在没数据,会立刻返回,然后由调用方自己去问现在有没有,如果没有就下次再问有没有,相当于不断去轮询结果,直到某个时刻被告知有结果了,这个时候数据已经从磁盘拷贝到内核空间了,数据也处于内核态,就差最后从内核态拷贝到用户空间,但是,从内核空间拷贝到用户空间,让数据从内核态变为用户态,这个过程在非阻塞式 I/O 模型中,也是阻塞的!所以效率也不会太高。
I/O 复用模型
复用的意思是,系统一次去查看多个io的进度,看哪一个有了结果,对于有结果的,就开始执行下面从内核空间拷贝到用户空间的操作,这个模型和上面非阻塞式 I/O 模型的区别是,非阻塞式 I/O 模型一次只看一个结果好了没有,而IO复用模型一次可以查看多个,一次监控一批系统调用好了没有,这是复用模型的特点。在一定程度上,能提高一些效率。
信号驱动式 I/O 模型
在Linux系统中,有一种信号机制,也就是说调用方可以注册一个信号,当系统调用完成之后,可以通知这个信号,那注册信号的人就会知道这个请求已经完成了,这种信号机制应用在IO当中就是信号驱动式IO。这样就不是查看结果是否好了,而是被通知的一种方式。不过通知后,从内核态到用户态这个过程还是阻塞的。纯异步的模型就是下面要说的这个。
异步 I/O模型
这种模型是真正的纯异步的IO模型,当开始系统调用,数据从磁盘读到内核空间,并且从内核态已经拷贝到了用户态之后,整个流程已经完成了,然后在进行回调,通知调用方。主要的区别在于不是在内核空间中完成了就通知,而是由内核空间到了用户空间后再通知,没有任何阻塞的过程,是一种更加彻底的异步IO。
各种I/O模型之间的比较
阻塞式IO就是发起调用之后,就一直阻塞,在等着,直到整个IO完成。在这个过程当中,进程是不能干任何事情的。都在等待。
非阻塞式IO就是,进程会主动去问好了没,好了没,好了没。。。直到得到回复好了,然后发起读请求,把数据从内核空间拷贝到用户空间。这个过程是阻塞的。
IO复用模型,就是每次都查看多个结果好了没,如果发现n个当中有一两个有了结果,就返回,有结果的这些开始拷贝。
信号驱动式IO模型,就是等数据拷贝到内核空间再通知,前面这段时间可以做别的事情,等内核空间准备好了,通知,再把数据从内核空间拷贝到用户空间。
异步IO模型,就是发起调用后就彻底不管了,等数据好了后从内核空间拷贝到用户空间了,再进行通知,整个过程没有阻塞的步骤。
从比较重来看,异步IO从理论上来看是最好的,不存在任何阻塞的时间,系统资源理论上可以得到充分利用。
同步VS异步
lPOSIX标准将同步I/O和异步I/O定义为:
同步I/O操作:导致请求进程阻塞,直到I/O操作完成。
异步I/O操作:不导致请求进程阻塞。
从定义上看,只有最后的异步IO模型是真正的异步,前面四种都达不到真正的异步。但是目前来看,纯异步的IO一直都不太成熟,比较混乱,没有一个标准的解决方案。用的最多的还是IO复用模型,这个是目前为止比较成熟的一个模型。
在Java中,我们用的最多的Socket网络编程,就是阻塞式IO模型,后来的NIO就是IO复用模型,在Java中不支持信号驱动模型。Java的NIO2.0,也叫AIO,提供了纯异步的IO模型,但是现在的异步IO模型还不是很成熟,所以用的最多的就是NIO,也就是IO复用模型。
推荐书籍《Unix网络编程》,推荐理由:网络编程的经典之作,经历了十年左右,内容基本变化不大,原理性书籍,是网络编程的必看之书。
本文由博客一文多发平台 OpenWrite 发布!
Netty快速入门(01)Linux I/O模型介绍的更多相关文章
- Netty快速入门(05)Java NIO 介绍-Selector
Java NIO Selector Selector是Java NIO中的一个组件,用于检查一个或多个NIO Channel的状态是否处于可读.可写.如此可以实现单线程管理多个channels,也就是 ...
- Netty快速入门(08)ByteBuf组件介绍
前面的内容对netty进行了介绍,写了一个入门例子.作为一个netty的使用者,我们关注更多的还是业务代码.也就是netty中这两种组件: ChannelHandler和ChannelPipeline ...
- Netty快速入门(03)Java NIO 介绍-Buffer
NIO 介绍 NIO,可以说是New IO,也可以说是non-blocking IO,具体怎么解释都可以. NIO 1是在JSR51里面定义的,在JDK1.4中引入,因为BolckingIO不支持高并 ...
- Netty快速入门(09)channel组件介绍
书接上回,继续介绍组件. ChannelHandler组件介绍 ChannelHandler组件包含了业务处理核心逻辑,是由用户自定义的内容,开发人员百分之九十的代码都是ChannelHandler. ...
- Netty快速入门(06)Netty介绍
前面简单的介绍了Java I/O 和NIO,写了示例程序. Java I/O是阻塞的,为了让它支持多个并发,就要针对每个链接启动线程,这种方式的结果就是在海量链接的情况下,会创建海量的线程,就算用线程 ...
- 网络应用框架Netty快速入门
一 初遇Netty Netty是什么? Netty 是一个提供 asynchronous event-driven (异步事件驱动)的网络应用框架,是一个用以快速开发高性能.可扩展协议的服务器和客户端 ...
- Netty快速入门(10)Reactor与Netty
Reactor模式 Reactor是1995年由道格拉斯提出的一种高性能网络编程模式.由于好多年了,当时的一些概念与现在略有不同,reactor模式在网络编程中是非常重要的,可以说是NIO框架的典型模 ...
- ETCD快速入门-01 ETCD概述
1.ETCD概述 1.1 ETCD概述 etcd是一个高可用的分布式的键值对存储系统,常用做配置共享和服务发现.由CoreOS公司发起的一个开源项目,受到ZooKeeper与doozer启发而 ...
- docker快速入门01——docker安装与简单应用
1.docker简介 Docker 是一个开源的应用容器引擎,Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级.可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化 ...
随机推荐
- pytorch JIT浅解析
概要 Torch Script中的核心数据结构是ScriptModule. 它是Torch的nn.Module的类似物,代表整个模型作为子模块树. 与普通模块一样,ScriptModule中的每个单 ...
- 洛谷P3313 [SDOI2014]旅行 题解 树链剖分+线段树动态开点
题目链接:https://www.luogu.org/problem/P3313 这道题目就是树链剖分+线段树动态开点. 然后做这道题目之前我们先来看一道不考虑树链剖分之后完全相同的线段树动态开点的题 ...
- H3C 常见ISDN连接方式
- Python--day63--单表的增删改查/GET和POST/request相关知识点回顾
- UVA 437 "The Tower of Babylon" (DAG上的动态规划)
传送门 题意 有 n 种立方体,每种都有无穷多个. 要求选一些立方体摞成一根尽量高的柱子(在摞的时候可以自行选择哪一条边作为高): 立方体 a 可以放在立方体 b 上方的前提条件是立方体 a 的底面长 ...
- linux内核符号表
我们已经看到 insmod 如何对应共用的内核符号来解决未定义的符号. 表中包含了全局内 核项的地址 -- 函数和变量 -- 需要来完成模块化的驱动. 当加载一个模块, 如何由模块 输出的符号成为内核 ...
- H3C 端口隔离基本配置
- ASP.NET MVC4.0+EF+LINQ+bui+bootstrap+网站+角色权限管理系统(4)
接下来就是菜单管理了,菜单分为两部分,一部分是菜单管理,另一部分是左边的树形菜单 数据库添加菜单表Menus USE [MVCSystem] GO /****** Object: Table [dbo ...
- eslint的使用和配置
eslint的使用和配置 什么是eslint ESLint 是在 ECMAScript/JavaScript 代码中识别和报告模式匹配的工具,它的目标是保证代码的一致性和避免错误.在许多方面,它和 J ...
- 移动端开发touchstart,touchmove,touchend事件详解和项目
移动端开发touchstart,touchmove,touchend事件详解和项目 最近在做移动端的开发,在一个“服务商管理”页面使用到了触摸事件"touchstart",&quo ...