js打印线程id_node.js概论

node.js的作用

服务器端面临的问题通常比前端更复杂,首先服务器的资源相对个人电脑而言都是比较昂贵的,所以如何用好内存、硬盘、带宽这些资源将会成为开发者必须考虑的问题。其次服务器端对接的程序比较多,数据库、日志系统、文件系统、网络等,可能会涉及更多领域的知识。但好在Node.js使用的是JavaScript,大大节省了前端开发者的学习成本,也有利于前后端实现同构。

Node.js服务器端很适合Web网站服务器端,尤其是访问量较大的网站,因为Node.js的并发能力非常强悍。比如淘宝的业务模型中就提出了中途岛模式来构建Web网站,其中Node.js作为中继服务器,负责渲染模板和合并、转发请求,如下图

65e23d3d41b127f014a1de363bf78c49.png

 Node.js作为中继服务器

利用Node.js的跨平台性以及提供的API也可以开发桌面应用。

什么是Node.js

Node.js是一个JavaScript运行环境,作为前端开发者可以把它理解为前端中的Chrome浏览器。同时它又是跨平台的,前端的 JavaScript 代码也是跨平台的,因为在主流操作系统平台下面都有可以运行的浏览器客户端,而Node.js也可以在多个操作系统中进行安装。同时由于Node.js的核心模块支持网络通信、文件读写等操作,配合其他数据库提供的驱动模块即可编写服务器端程序。

优点:
  1. 强大的并发能力。它的事件循环机制使得Node.js在执行代码的时候并不会被耗时的I/O操作(数据库查询、文件读写)所阻塞。可以瞬间处理大量的客户端请求,而不像大多数多线程服务器端那样并发能力会受到线程数量以及I/O操作耗时影响。

  2. 丰富的模块。NPM的出现让Node.js开发者可以自由分享和使用开发的模块,并且主流数据库如MySQL、Oracle、MongoDB都提供了Node.js的驱动程序。

  3. 成熟的Web框架。Node.js在Web服务器端开发中大放异彩也得益于一些开源项目,如提供JavaScript全栈式开发的ExpressJS框架,面向ES6/7的纯服务器端框架KoaJS,以及企业级开发框架ThinkJS、Egg,这使得用Node.js开发服务器端代码变得非常快速和容易。

缺点:
  1. CPU阻塞。虽然I/O操作不会阻塞Node.js程序,但是CPU密集型的操作却可以。因为它是单线程,无法使用多线程来分担计算压力,所以一旦碰到CPU耗时的操作一样会被阻塞。

  2. 稳定性低。单进程单线程使得Node.js在稳定性方面不如多线程的服务器,因为一旦代码出现严重错误或者漏洞导致报错后,整个线程将无法继续工作,服务器端停止响应请求,但是好在有第三方模块如PM2等来帮助解决这个问题。

  3. 弱类型。JavaScript 的语言特性决定其不支持变量类型声明,甚至函数参数也可以不声明直接使用arguments来读取。这就使得代码的维护性大大降低,因为开发者在调用函数时不知道需要传入什么结构类型的参数,也可能不知道调用的函数需要几个参数。要解决这个问题目前最好的方式就是使用TypeScript来做静态类型声明和校验。

Node.js的结构

3532d437f7fe423b269914f7c18737cb.png

 Node.js的结构

在我们平常进行开发编写代码的时候,只需要关注最上层的Node.js API,调用默认封装的模块进行开发即可。在这一层我们使用的是JavaScript代码。

Node.js 的底层代码就是用C++实现的,并且引用了 C++的一些库,就连Google的开源JavaScript引擎V8也是用C++编写的。但是我们在Node.js中还是使用JavaScript语言进行的开发,这是怎么回事呢?不同语言的确不能直接互相调用,Node.js Bindings的作用相当于是一些胶水代码,将Node.js那些用C/C++写的核心库转换成JavaScript的API。Addons和Bindings的作用相同,但是Bindings是针对Node.js核心模块而使用的,而Addons是针对第三方C/C++库。

Node.js的底层中需要关注的是V8引擎,它是Google开源的高性能JavaScript引擎,在Chrome浏览器中用的也是V8引擎。然后是LibUv,它是提供异步功能的C代码库。其他组件和库提供了对系统底层包括网络、文件等的访问。

总结一下,Node.js是一个用C++语言编写的JavaScript运行环境,从而让JavaScript开发者能对系统底层进行访问和操作。

Node.js的运行机制

Node.js采用单线程事件循环的工作机制

线程

我们在操作系统中启动应用程序的时候,就会创建一个或多个进程,比如在Windows中打开命令行窗口,就可以在资源管理器中看到对应的进程。不同进程之间的数据是隔离的,所以不同进程之间需要通信交换资源的时候,就需要访问对应进程的IP地址和端口。一个进程又可以创建多个线程,这些线程是并行工作的,它们共享进程中的资源。

传统的Web服务器端并不是单线程而是多线程的,利用多线程来处理多请求,服务器端进程负责把每个客户端请求任务分发给对应的单个线程来进行处理。它们处理客户端请求的过程如下图

14fd06ed28dd43b3a0497325033108ef.png

多线程Web服务器

  1. 服务器端在启动之时就会维护一个线程池,里面包含多个线程用来处理客户端请求。同时服务器端进程等待客户端请求。

  2. 客户端发送请求给服务器端。

  3. 服务器端收到这些请求之后选择一个客户端请求,再从线程池中选择一个线程,将请求分派给它进行处理。

  4. 线程开始处理请求,很可能需要读写数据库,而读写数据库的I/O操作一般会消耗一定的时间从而形成I/O阻塞,线程读写完数据库后将结果进行处理返回。线程被释放,回到线程池等待下次任务。

在这种模式下,一个线程只能处理一个客户端请求,一直到处理完成之后才能处理下一个请求。如果当前所有线程都在忙着等待I/O操作返回结果而阻塞,那么新来的请求需要等待很长时间。通常请求数量会远远大于线程池的线程数量,那么此时一般会在服务器端创建一个请求队列用来存储需要处理的请求,并按照顺序分派给可用的线程进行处理。

单线程优势:
  • 减少了创建、销毁和切换线程的开销,执行速度相对更快;

  • 内存占用小;

  • 更加安全。多线程因为共享资源,同时读写同一资源的时候就容易出现问题,比如死锁。

单线程劣势:
  • 安全性不足。线程出错会导致整个进程退出,容错性不够。

  • CPU利用率。单线程只能利用CPU的一个核,如果CPU有多个核(大多数CPU都是如此),那么其他核的资源就浪费了。另外,如果遇到需要耗费大量CPU计算的代码,整个线程也会出现阻塞。

单线程指的是Node.js运行我们编写的代码时是单线程的,Node.js的底层仍然是多线程的。

事件循环

afe430c8dd419c1047c4877f29d8f365.png

Node.js运行机制

  1. Node.js服务器端启动并初始化一个事件队列,然后创建一个事件循环,它是无限循环的单线程。

  2. 客户端发送请求。

  3. 服务器端接收到请求并放入到事件队列。

  4. 时间循环检查事件队列,采取先进先出的策略从事件队列中取出请求,判断请求是否会阻塞 I/O。如果会阻塞 I/O,那么从底层的线程池中取出线程用来处理请求,事件循环线程继续执行;如果不会阻塞I/O,那么事件循环线程处理请求。

  5. 线程处理完请求并返回结果给客户端。

和多线程响应多请求的服务器端相比,底层同样是用多线程处理多请求,这样有什么优势?

虽然在处理阻塞I/O的请求时和多线程服务器端一样,单个处理线程也会阻塞,但是事件循环线程并不受影响。举个例子,在多线程的服务器端中,如果线程池中的线程都在处理请求,此时因为没有可用的线程,将不能处理新的请求。但是在Node.js服务器端中,如果底层线程池都被占用,有新的请求过来时,如果是非阻塞I/O请求,那么事件循环线程可以直接进行处理并返回结果。

可以用生活中的两个场景来说明Node.js服务器和多线程服务器的区别。

在银行办理业务的时候一般会有多个窗口(线程),每个需要办理业务的客户(客户端请求)都会取号排队(请求队列),当有窗口空闲时会报号通知客户前去办理业务(线程处理客户端请求)。虽然此时有的窗口可能在等其他工作人员过来授权,或者在等客户填写单据(I/O阻塞),但每个窗口一次只能接待一位客户,当窗口为客户办理业务时其他它客户就只能等待。这就是传统多线程服务器工作模式。

如果你去过星巴克这类咖啡馆就会看到另一种模式。一般只有一个收银台,当很多顾客光临时,它们排队(事件队列)等候。每当顾客下单付款之后,收银台服务员会把订单打印出来,并继续服务下一位顾客,已经付款的顾客去旁边等待饮品烹制完成。负责制作饮品的店员(事件循环线程)拿到订单后使用不同的原料和机器来调制饮料,等饮料完成后通知对应的顾客(线程回调)。这就和Node.js服务器有些类似,不过Node.js服务器的并发能力远远超过咖啡馆。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值