libuv 原理_Nodejs的运行原理-libuv篇
前言
这应该是Nodejs的运行原理的第7篇分享,这篇过后,短时间内不会再分享Nodejs的运行原理,会停更一段时间,PS:不是不更,而是会开挖新的坑,最近有在研究RPG Maker MV,区块链,云计算,可能会更新一些相关文章,或者相关教学。
回到正题,异步编程的难点在于请求与响应不是按顺序发生的。以http server 为例,异步编程赋予了server 高并发的品质,而且他可以以很小的资源代价,不断地接受和处理请求。但是快速处理请求不表示快速地返回请求=>高并发不等同于快速反馈。
在Nodejs中,libuv则为异步编程的实现提供了可能。libuv为builtin modules 提供了API,这些API用来支撑请求和数据的返回的异步处理方式。
这一篇分享,我们主要讨论libuv的运行原理,从两个角度出发:
1) libuv的架构
2) 案例,从细节的角度看libuv是如何对待不同I/O请求,按照不同的方式来完成异步请求和数据返回的。
Libuv的架构
从左往右可分为两部分,Network I/O的相关请求,另一部分File I/O,DNS Ops和User Code组成。
上图展示了libuv细节的流程,图中代码很简单,包括2个部分:
1. server.listen()是用来创建TCP server时,通常放在最后一步执行的代码。主要指定服务器工作的端口以及回调函数。
2. fs.open()是用异步的方式打开一个文件。
选择两个示例很简单,因为libuv架构图可视:libuv对Network I/O和 File I/O采用不同的机制。
上图右半部分,主要分成两个部分:
1. 主线程:主线程也是node启动时执行的现成。node启动时,会完成一系列的初始化动作,启动V8 engine,进入下一个循环。
2. 线程池:线程池的数量可以通过环境变量UV_THREADPOOL_SIZE配置,最大不超过128个,默认为4个。
Network I/O
V8 engine执行从server.listen() 开始,调用builtin module Tcp_wrap 的过程。
在创建TCP链接的过程中,libuv直接参与Tcp_wrap.cc函数中的 TCPWrap::listen() 调用uv_listen()开始到执行uv_io_start()结束。看起来很短暂的过程,其实是类似linux kernel的中断处理机制。
uv_io_start()负载将handle插入到处理的water queue中。这样的好处是请求能够立即得到处理。中断处理机制里面的下半部分与数据处理操作相似,交由主线程去完成处理。
代码逻辑很简单,查看loop中是否包含handle,如果有遍历default loop。
File I/O
这里我们研究一下 File I/O。
同Network I/O一样,我们的应用所依赖的fs模块,后面有一个builtin module Node_file.cc作为支撑。 Node_file.cc包含了各种我们常用的文件操作的接口,例如open, read, write, chmod,chown等。但同时,它们都支持异步模式。 我们通过Node_file.cc中的Open()函数来研究一下具体的实现细节。
如果你用类似source insight之类的代码阅读工具跟踪一下代码调用顺序,会很容易发现对于异步模式,Open()函数会在一系列辅助操作之后,进入函数uv_fs_open(),并且传入了一个FSReqWrap的对象。
FSReqWrap(),从名字可以看得出来,这是一个wrap,且是与FS相关的请求。也就是说,它基于某一个现成的机制来实现与FS相关的请求操作。这个现成的机制就是ReqWrap。好吧,它也是个wrap。乘你还没疯的时候,看一下图6吧。这里完整展示了FSReqWrap类继承关系。
除了FSReqWrap,还有其它Wrap,例如PipeConnectWrap,TCPConnectWrap等等。每个Wrap均为一种请求类型服务。 但是这些wrap,都是node自身的行为,而与libuv相关的是什么呢?上图中表示出了FSReqWrap关键的数据结构 uv_fs_s req__。
让我们把目光回到uv_fs_open()。在调用这个函数时, req__作为其一个重要的参数被传递进去。而在uv_fs_open()内部,req__则被添加到work queue的末尾中去。图3 thread pool中的thread会去领取这些request进行处理。 每个request很像一个粘贴板,它将event loop, work queue,每个请求的处理函数(work()),以及请求结束处理函数(done())绑定在一起。绑定的操作在uv__work_submit()中完成。 例如对于这里的req__,绑定在它身上的work()为uv__fs_work(), done()为uv__fs_done()。
这里有一个比较有意思的问题值得额外看一下。我们的thread pool是在什么时候建立的呢?
答案是:在第一次异步调用uv__work_submit()时。
每个thead的入口函数是 Threadpool.c中的worker()。工作逻辑比较简单,依次取出work queue中的请求,执行绑定在该请求上的work()函数。 前面我们提到的绑定在请求上的done()函数在哪里执行呢?这也是一个比较有意思的操作。libuv通过uv_async_send()通知event loop去执行相应的callback函数,也即我们绑定在request上的done()函数。uv__work_done()用于完成这样的操作。
uv_async_send()与主线程之间通过PIPE通信。
我在这一小节以一个FSReqWrap以及Open()函数为例,描述了libuv处理这种File I/O请求时所涉及的各种操作:
建立thread pool(只建立一次)
在每个请求req__上绑定与其相关的event loop, work queue, work(), done()
thread worker()用来处理work queue里面的每个请求,并执行work()
通过uv_async_send()通知event loop执行done()
libuv 原理_Nodejs的运行原理-libuv篇相关推荐
- java能够运行的原理_JAVA程序运行原理分析(一)
作为JAVA的开发人员,需要知道JAVA是如何运行的,这个需要好好思考下. (一)class文件内容 class文件包含JAVA程序执行的字节码,也就是说程序的执行是通过class里面的内容进行执行的 ...
- SpringBoot原理-SpringBoot核心运行原理
导语 Spring Boot最为核心的功能就是自动配置,所有功能的实现都是基于"约定优于配置"的原则,但是Spring Boot是如何实现自动配置的功能的,下面就通过源码学习S ...
- python解析器原理_Python程序运行原理图文解析
本文研究的主要是Python程序运行原理,具体介绍如下. 编译型语言(C语言为例) 动态型语言 一个程序是如何运行起来的?比如下面的代码 #othermodule.py def add(a, b): ...
- java的运行原理_Java的运行原理(转载)
在Java中引入了虚拟机的概念,即在机器和编译程序之间加入了一层抽象的虚拟的机器.这台虚拟的机器在任何平台上都提供给编译程序一个的共同的接口.编译程序只需要面向虚拟机,生成虚拟机能够理解的代码,然后由 ...
- php 浏览网页的原理,PHP网页运行原理
1.用户在Web浏览器(客户端)中键入网址以访问网站.此连接还含有HTML表单的HTML页面. 2.浏览器连接到Apache服务器上,服务器中存放有组成该网站的HTML和PHP文件.Apache为客户 ...
- php框架laravel原理,Laravel框架运行原理
写在前面: 使用任何框架,如果理解该框架原理,应用起来会更加得心应手. 一.生命周期 1. 入口文件: Laravel框架所有请求入口统一进入/public/index.php文件,请求通过Ngxin ...
- Libuv的安装及运行使用
Libuv的安装及运行使用 Libuv的官网链接:http://libuv.org/ GitHub下载链接:https://github.com/libuv/libuv CMake下载链接:https ...
- 【VLAN高级技术】--- MUX VLAN运行原理及实例配置讲解
文章目录 一.MUX VLAN产生原因 二.MUX VLAN运行原理 三.实例配置讲解(重点!!!) 四.MUX VLAN配置命令 一.MUX VLAN产生原因 个人认为MUX VLAN主要是为大中型 ...
- jsp是什么以及jsp运行原理
jsp是什么以及jsp运行原理 一.JSP的简单介绍 1. JSP(Java Server Pages)是由Sun Microsystems公司倡导.许多公司参与一起建立的一种动态网页技术标准.JSP ...
最新文章
- jmail用免费邮箱需开启SMTP服务及注意事项
- Keepalived配置文件
- python定时任务:apscheduler的使用(还有一个celery~)
- pat 1034. Head of a Gang (30)
- 1088 三人行 (20 分)
- 带有审计表的实体框架核心(EF Core)
- 【Linux】Centos7重启网卡失败
- 关于Java中的final关键字
- 勉强算是面经——1.诺瓦科技
- UG不用计算机名,win10系统安装UG软件后打开提示计算机名不对的解决步骤
- 说说 JavaEye 网站架构
- NC文件按时序维度拆分
- linux步进电机驱动程序,基于S3C2440嵌入式Linux的步进电机驱动程序
- 智慧能源管控系统在钢铁企业的设计与应用
- 【寻找最佳小程序】12期:小程序数据助手——微信官方打造,移动端数据分析工具...
- 报错问题:Invalid bound statement (not found):cn.mall.dao.BookMapper.selectAll
- 川藏北线-成都老茶馆叹茶
- c语言软件中ovr怎么取消,OVR Toolkit
- Springbootg整合validation整合
- java part part_Java Nashorn--Part 5
热门文章
- MySQL助手_java 8.0Mysql 助手类
- Web前端——JavaScript(bom文档对象模型)
- Linux之防火墙开通端口
- zephyr_Facebook,IBM,Yahoo和更多新闻发布的物联网Zephyr项目
- java/05/(Swing包)窗体,组件,布局管理器,面板,监听事件
- CSS3 响应式布局之响应式图片
- pthread_exit()
- CMakeList.txt的简介
- 最短哈密尔顿圈matlab解法_复杂制造过程最优哈密尔顿圈算法的MATLAB仿真与分析.doc...
- Python 竟能绘制如此酷炫的三维图