Node.js底层实现

对于Node.js的全面认识我还不够,只知道它用了谷歌的v8引擎,能做到高并发,(谷歌浏览器用的是v8引擎,这款浏览器对于脚本的执行性能是秒杀了其它浏览器)。下面我们来全面了解下。

先放图

从图中可以看出,node.js主要由三部分构成

V8 javascript引擎

Libuv线程池

第三方库

我们来看看Libuv线程池(核心)

libuv使用异步,事件驱动的编程方式,核心是提供i/o的事件循环和异步回调。libuv的API包含有时间,非阻塞的网络,异步文件操作,子进程等等。(跨平台的异步IO库,但它提供的功能不仅仅是IO,还 包括进程、线程、信号、定时器、进程间通信,线程池等。)

1.什么是异步I/O、事件循环?

1.1 异步I/O(输入输出input/output)

首先,node的异步I/O不等于非阻塞I/O。非阻塞I/O调用后会虽然也是立即返回,但是应用层会不断的重复I/O操作去轮询系统是否完成数据读取,让CPU处理状态判断,对CPU造成资源的浪费。

然而在异步I/O里,基于多子线程的方式去解决了非阻塞I/O的问题,应用层(主线程)发起I/O请求后,就不再过问情况了。然后让子线程来完成数据获取,当读写完成后通知主线程。

1.2 事件循环

当子线程完成并通知主线程后,主线程在什么时机去调用呢?这时候就得说到事件循环。事件循环类似于while(true)的一个程序,在每次循环的时候,都会去检查一下是否有事件待处理,如果有就取出执行,否则继续下一次循环。

那主线程是去哪里检查呢,这里就要引入观察者这个概念,每次事件循环中有一个或者多个观察者,按照优先级依次进行询问和处理。

所以,事件循环是一个典型的生产/消费模型,异步I/O、网络请求等是事件的生产者,这些事件被传递到对应的观察者那里,等待事件循环取出并处理。

1.2.1 请求对象

当调用异步I/O时,会创建一个请求对象,该对象包含了传入的参数和当前方法上下文,以及我们最关注的回调函数。创建完成后,将其推入线程池中等待执行。至此,主线程的调用立即返回,继续执行当前任务的后续操作。

1.2.2 执行回调

当线程池中有可用线程池时,会对请求对象进行调用,执行完毕后,会将执行结果记录在对象中,归还线程,并且告诉观察者自己已经ready,然后观察者会把它放入队列中。

当主线程来询问观察者时,就可以取出请求对象,并且执行上面的回调函数。至此,整个异步I/O的流程就结束了。

2.为什么设计成单线程(单主线程)?

目前业内存在的几种web服务器模型有同步、多进程和多线程,每个都存在一些问题:

  • 同步:一次只能处理一个请求,造成CPU浪费,总处理耗时久。
  • 多进程、多线程:虽然大幅度的解决了同步存在问题,但是当遇到大并发请求时,资源会很快用光,只能通过增加系统资源来扩展。

反而基于单主线程的方式,也就是Node的异步I/O+事件循环,无须为每一个请求创建额外的对应线程,可以省掉创建和销毁线程的开销,同时操作系统在调度任务时因为线程较少,上下文切换的代价很低。

NodeJS 异步I/O详解 - 知乎

Node.js介绍5-libuv的基本概念 - 简书

Node.js的底层原理 - 知乎

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值