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模型分为五种类型:

  1. 阻塞式 I/O 模型

  2. 非阻塞式 I/O 模型

  3. I/O 复用

  4. 信号驱动式 I/O

  5. 异步 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模型介绍的更多相关文章

  1. Netty快速入门(05)Java NIO 介绍-Selector

    Java NIO Selector Selector是Java NIO中的一个组件,用于检查一个或多个NIO Channel的状态是否处于可读.可写.如此可以实现单线程管理多个channels,也就是 ...

  2. Netty快速入门(08)ByteBuf组件介绍

    前面的内容对netty进行了介绍,写了一个入门例子.作为一个netty的使用者,我们关注更多的还是业务代码.也就是netty中这两种组件: ChannelHandler和ChannelPipeline ...

  3. Netty快速入门(03)Java NIO 介绍-Buffer

    NIO 介绍 NIO,可以说是New IO,也可以说是non-blocking IO,具体怎么解释都可以. NIO 1是在JSR51里面定义的,在JDK1.4中引入,因为BolckingIO不支持高并 ...

  4. Netty快速入门(09)channel组件介绍

    书接上回,继续介绍组件. ChannelHandler组件介绍 ChannelHandler组件包含了业务处理核心逻辑,是由用户自定义的内容,开发人员百分之九十的代码都是ChannelHandler. ...

  5. Netty快速入门(06)Netty介绍

    前面简单的介绍了Java I/O 和NIO,写了示例程序. Java I/O是阻塞的,为了让它支持多个并发,就要针对每个链接启动线程,这种方式的结果就是在海量链接的情况下,会创建海量的线程,就算用线程 ...

  6. 网络应用框架Netty快速入门

    一 初遇Netty Netty是什么? Netty 是一个提供 asynchronous event-driven (异步事件驱动)的网络应用框架,是一个用以快速开发高性能.可扩展协议的服务器和客户端 ...

  7. Netty快速入门(10)Reactor与Netty

    Reactor模式 Reactor是1995年由道格拉斯提出的一种高性能网络编程模式.由于好多年了,当时的一些概念与现在略有不同,reactor模式在网络编程中是非常重要的,可以说是NIO框架的典型模 ...

  8. ETCD快速入门-01 ETCD概述

    1.ETCD概述 1.1 ETCD概述     etcd是一个高可用的分布式的键值对存储系统,常用做配置共享和服务发现.由CoreOS公司发起的一个开源项目,受到ZooKeeper与doozer启发而 ...

  9. docker快速入门01——docker安装与简单应用

    1.docker简介 Docker 是一个开源的应用容器引擎,Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级.可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化 ...

随机推荐

  1. Python--day61--Django ORM关系的简单梳理

    models.py中的代码和数据库中的表对应

  2. [转]vue原理简介

    写vue也有一段时间了,对vue的底层原理虽然有一些了解,这里总结一下. vue.js中有两个核心功能:响应式数据绑定,组件系统.主流的mvc框架都实现了单向数据绑定,而双向绑定无非是在单向绑定基础上 ...

  3. 第一种方式:cookie的优化与购物车实例

    一 Cookie 的优化 1.1 一般而言,我们设置cookie是在php中设置 例如: <?php setcookie('testKey1','hello world',0,'/'); //# ...

  4. CCPC2018 桂林 D "Bits Reverse"

    传送门 题目描述 Now given two integers x and y, you can reverse every consecutive three bits ,,) means chan ...

  5. JAVA核心知识点--打包 FatJar 方法小结

    目录 什么是 FatJar 三种打包方法 1. 非遮蔽方法(Unshaded) 2. 遮蔽方法(Shaded) 3. 嵌套方法(Jar of Jars) 小结 参考阅读 原文地址:https://yq ...

  6. Spring AOP 源码分析

    一.准备工作 在这里我先简单记录下如何实现一个aop:   AOP:[动态代理] 指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式: 1.导入aop模块:Spring AOP: ...

  7. ajaxSetup()方法

    使用ajaxSetup()方法设置全局Ajax默认选项 使用ajaxSetup()方法可以设置Ajax请求的一些全局性选项值,设置完成后,后面的Ajax请求将不需要再添加这些选项值,它的调用格式为: ...

  8. vue-learning:30 - component - 组件实例的引用方式

    组件实例的引用方式 ref / $refs $root $parent $children 扩展查找任意组件实例的方法 在vue开发的项目中,通常会以一棵嵌套的组件树的形式来组织项目. 都存在着一个根 ...

  9. UE4 C++ 代码编译方式

    Unreal 有一个非常酷的特性 —> 不必关闭编辑器就可以编译 C++ 更改! 有两种方法可以达到这个目的: 1.直接点击编辑器主工具栏中的 编译(Compile) 按钮. 2.在编辑器继续运 ...

  10. Xcode崩溃日志分析工具symbolicatecrash用法

    1.什么是symbolicatecrash? symbolicatecrash是Xcode自带的一个分析工具,可以通过机器上的崩溃日志和应用的.dSYM文件定位发生崩溃的位置,把crash日志中的一堆 ...