热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

深入解析Netty:基础理论与IO模型概述

篇首语:本文由编程笔记#小编为大家整理,主要介绍了了解Netty之基本理论篇--IO模型相关的知识,希望对你有一定的参考价值。 也许迷途的惆怅,会扯碎我的脚步,可我相信未来会给我一双梦想的翅膀 虽然失

篇首语:本文由编程笔记#小编为大家整理,主要介绍了了解Netty之基本理论篇--IO模型相关的知识,希望对你有一定的参考价值。


也许迷途的惆怅,会扯碎我的脚步,可我相信未来会给我一双梦想的翅膀

虽然失败的苦痛,已让我遍体鳞伤,可我坚信光明就在远方





光明 From 依荨 05:24


通常,关于IO模型听得比较多的,同步阻塞IO、同步非阻塞IO等等,然后前面又说到一个多路复用模型,还有Reactor、Proactor模型。。。。


名词概念多了以后,就有点傻傻分不清楚了

然后今天特地整理了一下思路,轻装上阵


在IO模型前,首先需要了解下计算机操作系统层面的一些操作,当应用程序进行读写操作(无论是基于Socket还是文件)时,应用程序底层都是Input和Output操作应用程序进程缓冲区的数据,操作完成后,操作系统的调度系统将进程缓冲区的数据读写到操作系统内核缓冲区,再由操作系统内核kernel完成读写到最终的网卡<网络通信>或者磁盘<文件读写>。当然这里也有例外,比如JavaNIO中内存映射文件操作是个例外,详情可见,文中关于通过内存映射文件完成文件复制的说明。


为何需要缓冲区?频繁的操作系统IO操作调用,会有很大的功耗,所以一般来说,程序需要减少IO操作,比如日常工作中经常说的“不要在循环体中访问数据库,会很卡”,为什么呢?数据库其实也是把数据保存到系统磁盘文件中的,所以数据库连接然后查询数据库的一系列操作,也属于IO操作。所以需要先将数据加载到操作系统内核缓冲区,同时操作系统调度将数据加载到程序进程缓冲区,方便减少对操作系统的IO操作。


即简单用图解释下,程序的IO操作涉及的2个步骤



然后这里要说的IO模型就是基于操作系统层面的读写,即上图的前半段操作


一般来说,IO模型包含5个:

同步阻塞IO、同步非阻塞IO、信号驱动IO、IO多路复用、异步非阻塞IO


下面依次简单了解这几个模型

同步以一个简单例子来描述这个过程,假定有个房东,有很多套房子需要去收租,然后每次收租需要收取现金,同时给租户开具收据,看过很多短视频,房东收房租喜欢拿个装钱的袋子,那这里也有个装钱的袋子。类比IO操作,房东是应用程序,收到的租金是需要读取的数据,开具的收据是需要写出的数据


同步阻塞IO

房东,去某个租户家收租,等待租户清点现金给房东,房东接过现金,开具发票,对于房东来说,在开始去收租开始,需要一直等到租户把现金清点好,将现金放入袋子中。然后房东才把发票开具好,给到租户。

在租户给到现金之前,房东就这么傻傻的在门口等着。

这个过程,我们可以简单的理解为同步阻塞IO

了解Netty之基本理论篇--IO模型

这个装钱的袋子,当收到租金之后,肯定比之前更重了,于是袋子的状态和之前就不一样了,这里我们可以理解为文件描述符(FD)

在kernel数据没有复制到用户应用程序内存,程序线程就傻傻处于一个阻塞的状态,同时,由于读的时候不能写,写的时候不能读,读写之间又是一个同步状态,即为同步阻塞IO

这种模式也是比较常见的了,比如:,读写的同步操作,通常会用多线程,即伪异步来做!


同步非阻塞IO

当多次这样子收租方式之后,房东有点厌倦了,他不想在收租的时候,傻傻的等着租户清点现金完之后,然后收到钱,主要租金又高,租客数钱数半天,等着就很烦躁,于是房东想到一个办法,将收钱的袋子,放在门口<假定钱袋只能往里放钱,不可以拿走,然后人们素质又很高,不存在把钱袋子拿跑的情况>,然后房东可以在租客清点租金的期间内,该玩手机玩会手机,该干啥就干会儿啥。在这个期间,只要保证每隔一段时间,房东回过头来看钱袋子里有多了钱没有就好了。

直到租客交了租金,房东开了发票,带着钱开心的走了。这个过程结束了

了解Netty之基本理论篇--IO模型

每隔一段时间就回头看看,这个操作其实就是对文件描述符的一个轮询的过程,当数据准备就绪,则获取数据,否则就可以继续做其他的事,而不会阻塞在这里。

此种方式也是JavaNIO的模型中的一部分,但是此种模型也有不好的地方,即对于CPU来说是比较大的浪费


信号驱动IO

房东对上述过程还是不满意,因为需要每隔一段时间来看看,于是他在钱袋上安装了一个开关,当有钱进入的时候,开关就会响,于是他就可以安安心心的玩手机看直播了(#^.^#)


了解Netty之基本理论篇--IO模型

即,在kernel给到信号前,就可以一心一意做其他的事了。



按照顺序,本来应该说IO多路复用,但这里先把最后一个异步非阻塞说了,最后来说IO多路复用


异步非阻塞IO

有一次,房东和他儿子和女儿一起去收租,于是按照上述过程,女儿收钱,然后儿子开收据,收钱和开收据可以同时做了<这里忽略如果先收到收据不给钱的租客的情况,大家信誉良好,都是会给钱的>,于是,房东就直接可以义无反顾的去做自己的事了


了解Netty之基本理论篇--IO模型

即只要应用程序主线程发起了读写请求之后,就什么就不管了,只需要在回调中处理自己的事就好,中比较清晰的介绍了这个过程。

异步非阻塞的IO,在操作系统层面,实现得并不多,尤其在Linux上,所以,目前在软件编程过程中是使用得比较少的。


IO多路复用

基于同步非阻塞IO的过程,房东认为虽然方法可行,但是一家一家的收太麻烦了,于是他固定的地方,放好很多的钱袋,对应每个租户,告知租客,在收租那天,租客自己将钱清点好之后,放到钱袋中,于是收租的过程效率更高了

此模型基本是基于同步非阻塞IO的一个升级版本,同时将多个IO操作请求封装于通道中,都注册到Select上,通过不停的循环Select中通道及其通道状态(即文件描述符的状态),做各自不一样的事


那么基于IO多路复用,目前流行的多路复用IO模型的主要实现有四种:Selectpollepollkqueue




































主要实现
性能
具体实现方案
支持操作系统

select

较高
Reactor模型
Window/Linux
poll
较高
Reactor模型 Linux
epoll

Reactor/Proactor Linux
kqueue

Proactor Linux



试想这么几个问题:首先,租客不会一次性到来,会分批次的来,那么钱袋也是分批次的增加,房东轮询每个钱袋,也是越来越多,压力会显然增大,同时当发现某个钱袋装好了钱,于是自己便去处理这家人收租的事宜,于是轮询便停了下来,这样子是需要等到房东对于这家人的租金都处理妥当了<比如房东还需要检查钱是不是真的,有没有那么多等等事情,最后还要开具收据等一些列操作>之后,才能继续去轮询其他的钱袋了

这种方式其实对于程序来说,其实是不太理想的,于是,可以做个改进,房东就一直坚守着查看租客的增加,或者完成收租过程之后的租客减少的过程,当某个租客到来或者离开的时候,对应给到相应钱袋的状态描述符,同时将这个租客的接下来的操作交给儿子或者女儿去做,而房东就不在去做其他的事情了,

基于此,这里把房东一直坚守的过程称为一个反应堆(Reactor),把钱袋不断增加/减少的过程,视为一个Socket的新连接/断开连接,当有新的socket连接到来之后,注册对应事件,同时利用事件驱动机制<即事件到来的时候触发事件,而不是漫无目的的去监视事件>,当事件触发,即文件操作符的状态改变为某种状态的时候,由线程去处理相应的事件



这就是一个简易的Reactor模型,即Reactor模型是一个IO多路复用模型的实现方案


与此对应的Proactor模型,它则不在强调对应某种文件描述符而做相应的操作,相反,它所关心的是当前文件描述符是否是完成状态,类似房东收租,只关心钱袋是否已经有钱,只要有钱了,直接异步做完成收钱后所需要做的事,而不在意,当前钱袋是一个什么样的状态。


对比ReactorProactor两种模型,主要有以下区别:


1、Reactor实现同步I/O多路分发,Proactor实现异步I/O分发。

Reactor比较倾向于处理网络I/O,涉及文件I/O,单线程的Reactor可能被I/O阻塞导致事件分发异常。所以文件I/O最好还是使用Proactor模式,或者用多线程模拟实现异步I/O的方式。

2、 Reactor模式注册的是文件描述符的就绪事件,而Proactor模式注册的是完成事件。

即Reactor模式有事件发生的时候要判断是读事件还是写事件,然后用再调用系统调用(read/write等)将数据从内核中拷贝到用户数据区继续其他业务处理。Proactor模式一般使用的是操作系统的异步I/O接口,发起异步调用(用户提供数据缓冲区)之后操作系统将在内核态完成I/O并拷贝数据到用户提供的缓冲区中,完成事件到达之后,用户只需要实现自己后续的业务处理即可。

3、Reactor模式是一种被动的处理,即有事件发生时被动处理。而Proator模式则是主动发起异步调用,然后循环检测完成事件。


前面已经说到了,Netty是采用NIO,为什么不用AIO呢?

在这里相信已经有了答案


1、Netty整体架构是Reactor模型,而AIO是Proactor模型,当Netty使用AIO则会将两种模型混合在一起,比较混乱


2、在Linux系统上,AIO的底层实现,是利用多路复用IO中的epoll,没有很好的实现AIO,在性能上没有明显优势,同时Netty主要使用在Linux上


3、AIO接收数据前需要预分配缓存<因为异步操作>,所以当连接数非常大但流量小的时候,内存耗费比较严重


以上就是对于IO基本理论的一些简单介绍,可能存在不正确的地方,请多多指正



下一节,将正式进入Netty,介绍使用Netty如果处理数据传输中的粘包和半包情况


烦请动动手指,转发关注




推荐阅读
  • 从无到有,构建个人专属的操作系统解决方案
    操作系统(OS)被誉为程序员的三大浪漫之一,常被比喻为计算机的灵魂、大脑、内核和基石,其重要性不言而喻。本文将详细介绍如何从零开始构建个人专属的操作系统解决方案,涵盖从需求分析到系统设计、开发与测试的全过程,帮助读者深入理解操作系统的本质与实现方法。 ... [详细]
  • 如何在PHP中有效实现和管理互斥锁机制(PHP锁) ... [详细]
  • 【并发编程】全面解析 Java 内存模型,一篇文章带你彻底掌握
    本文深入解析了 Java 内存模型(JMM),从基础概念到高级特性进行全面讲解,帮助读者彻底掌握 JMM 的核心原理和应用技巧。通过详细分析内存可见性、原子性和有序性等问题,结合实际代码示例,使开发者能够更好地理解和优化多线程并发程序。 ... [详细]
  • 本书详细介绍了在最新Linux 4.0内核环境下进行Java与Linux设备驱动开发的全面指南。内容涵盖设备驱动的基本概念、开发环境的搭建、操作系统对设备驱动的影响以及具体开发步骤和技巧。通过丰富的实例和深入的技术解析,帮助读者掌握设备驱动开发的核心技术和最佳实践。 ... [详细]
  • Python与R语言在功能和应用场景上各有优势。尽管R语言在统计分析和数据可视化方面具有更强的专业性,但Python作为一种通用编程语言,适用于更广泛的领域,包括Web开发、自动化脚本和机器学习等。对于初学者而言,Python的学习曲线更为平缓,上手更加容易。此外,Python拥有庞大的社区支持和丰富的第三方库,使其在实际应用中更具灵活性和扩展性。 ... [详细]
  • 作为140字符的开创者,Twitter看似简单却异常复杂。其简洁之处在于仅用140个字符就能实现信息的高效传播,甚至在多次全球性事件中超越传统媒体的速度。然而,为了支持2亿用户的高效使用,其背后的技术架构和系统设计则极为复杂,涉及高并发处理、数据存储和实时传输等多个技术挑战。 ... [详细]
  • Python学习:环境配置与安装指南
    Python作为一种跨平台的编程语言,适用于Windows、Linux和macOS等多种操作系统。为了确保本地已成功安装Python,用户可以通过终端或命令行界面输入`python`或`python3`命令进行验证。此外,建议使用虚拟环境管理工具如`venv`或`conda`,以便更好地隔离不同项目依赖,提高开发效率。 ... [详细]
  • 当前,众多初创企业对全栈工程师的需求日益增长,但市场中却存在大量所谓的“伪全栈工程师”,尤其是那些仅掌握了Node.js技能的前端开发人员。本文旨在深入探讨全栈工程师在现代技术生态中的真实角色与价值,澄清对这一角色的误解,并强调真正的全栈工程师应具备全面的技术栈和综合解决问题的能力。 ... [详细]
  • 如何在Android项目中正确导入和配置MySQL数据库驱动 ... [详细]
  • MongoDB高可用架构:深入解析Replica Set机制
    MongoDB的高可用架构主要依赖于其Replica Set机制。Replica Set通过多个mongod节点的协同工作,实现了数据的冗余存储和故障自动切换,确保了系统的高可用性和数据的一致性。本文将深入解析Replica Set的工作原理及其在实际应用中的配置和优化方法,帮助读者更好地理解和实施MongoDB的高可用架构。 ... [详细]
  • Spring Security 认证模块的项目构建与初始化
    本文详细介绍了如何构建和初始化Spring Security认证模块的项目。首先,通过创建一个分布式Maven聚合工程,该工程包含四个模块,分别为core、browser(用于演示)、app等,以构成完整的SeehopeSecurity项目。在项目构建过程中,还涉及日志生成机制,确保能够输出关键信息,便于调试和监控。 ... [详细]
  • 我正在使用 Ruby on Rails 构建个人网站。总体而言,RoR 是一个非常出色的工具,它提供了丰富的功能和灵活性,使得创建自定义页面变得既高效又便捷。通过利用其强大的框架和模块化设计,我可以轻松实现复杂的功能,同时保持代码的整洁和可维护性。此外,Rails 的社区支持也非常强大,为开发过程中遇到的问题提供了丰富的资源和解决方案。 ... [详细]
  • 本文推荐了六款高效的Java Web应用开发工具,并详细介绍了它们的实用功能。其中,分布式敏捷开发系统架构“zheng”项目,基于Spring、Spring MVC和MyBatis技术栈,提供了完整的分布式敏捷开发解决方案,支持快速构建高性能的企业级应用。此外,该工具还集成了多种中间件和服务,进一步提升了开发效率和系统的可维护性。 ... [详细]
  • 深入解析 Django 中用户模型的自定义方法与技巧 ... [详细]
  • 浅析PHP中$_SERVER[
    在PHP后端开发中,`$_SERVER["HTTP_REFERER"]` 是一个非常有用的超级全局变量,它可以获取用户访问当前页面之前的URL。本文将详细介绍该变量的使用方法及其在不同场景下的应用,如页面跳转跟踪、安全验证和用户行为分析等。通过实例解析,帮助开发者更好地理解和利用这一功能。 ... [详细]
author-avatar
寄到家的_259
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有