前言

如果你有一定的前端基础,比如 HTML、CSS、JavaScript、jQuery;那么,Node.js 能让你以最低的成本快速过渡成为一个全栈工程师(我称这个全栈为伪全栈,我认为的全栈也要精通数据库,不喜勿喷),从而触及后端和移动端的开发。当然,Node.js也不是万能的、也不是说学了它就可以完全取代后端的其他开发语言,它有自己的使命和擅长的应用领域。

除此之外现在非常火热的 Vue.js,React.js ,等很多数据层动态交互优先选用了Node.js,一些比较流行的打包工具也是如此;综上,为你为什么要学习它又增加了一大理由。

Node.js 和传统的后端语言(比如PHP、JAVA等)相比,各有优缺点,各自擅长领域和侧重点不同,因此,各有千秋、各有需求市场。Node.js 让我们进行后端开发多了一种便捷的手段。所以大家也不要总说哪些语言是最好的,各有各的使命,嘿嘿。

Node.js的特点

非阻塞异步io

例如,当在访问数据库取得数据的时候,需要一段时间。在传统的单线程处理机制中,在执行了访问数据库代码之后,整个线程都将暂停下来,等待数据库返回结果,才能执行后面的代码。也就是说,I/O阻塞了代码的执行,极大地降低了程序的执行效率。

由于 Node.js 中采用了非阻塞型I/O机制,因此在执行了访问数据库的代码之后,将立即转而执行其后面的代码,把数据库返回结果的处理代码放在回调函数中,从而提高了程序的执行效率。

当某个I/O执行完毕时,将以事件的形式通知执行I/O操作的线程,线程执行这个事件的回调函数。为了处理异步I/O,线程必须有事件循环,不断的检查有没有未处理的事件,依次予以处理。

阻塞模式下,一个线程只能处理一项任务,要想提高吞吐量必须通过多线程。而非阻塞模式下,一个线程永远在执行计算操作,这个线程的CPU核心利用率永远是100%。所以,这是一种特别有哲理的解决方案:与其人多,但是好多人闲着;还不如一个人玩命,往死里干活儿。

单线程

在 Java、PHP 或者 .net 等服务器端语言中,会为每一个客户端连接创建一个新的线程。而每个线程需要耗费大约2MB内存。也就是说,理论上,一个8GB内存的服务器可以同时连接的最大用户数为4000个左右。要让Web应用程序支持更多的用户,就需要增加服务器的数量,而 Web 应用程序的硬件成本当然就上升了。

Node.js不为每个客户连接创建一个新的线程,而仅仅使用一个线程。当有用户连接了,就触发一个内部事件,通过非阻塞I/O、事件驱动机制,让 Node.js 程序宏观上也是并行的。使用 Node.js ,一个8GB内存的服务器,可以同时处理超过4万用户的连接。

另外,单线程带来的好处,操作系统完全不再有线程创建、销毁的时间开销。但是单线程也有很多弊端,会在 Node.js 的弊端详细讲解,请继续看。

事件驱动

Node.js 中,客户端请求建立连接,提交数据等行为,会触发相应的事件。在 Node.js 中,在一个时刻,只能执行一个事件回调函数,但是在执行一个事件回调函数的中途,又有其他事件产生,可以转而处理其他事件(比如,又有新用户连接了),然后返回继续执行原事件的回调函数,这种处理机制,称为“事件环”机制。

Node.js 底层是 C++(V8也是C++写的)。底层代码中,近半数都用于事件队列、回调函数队列的构建。用事件驱动来完成服务器的任务调度,这是鬼才才能想到的。针尖上的舞蹈,用一个线程,担负起了处理非常多的任务的使命。


注意这里的事件循环,也可以说是 Node.js 的一个精髓所在,下面引用一段 Node.js 官网的内容

   ┌───────────────────────────┐┌─>│           timers          ││  └─────────────┬─────────────┘│  ┌─────────────┴─────────────┐│  │     pending callbacks     ││  └─────────────┬─────────────┘│  ┌─────────────┴─────────────┐│  │       idle, prepare       ││  └─────────────┬─────────────┘      ┌───────────────┐│  ┌─────────────┴─────────────┐      │   incoming:   ││  │           poll            ││  └─────────────┬─────────────┘      │   data, etc.  ││  ┌─────────────┴─────────────┐      └───────────────┘│  │           check           ││  └─────────────┬─────────────┘│  ┌─────────────┴─────────────┐└──┤      close callbacks      │   └───────────────────────────┘

引用Node官网中的一段内容:

注意:每个框将被称为事件循环的“阶段”。每个阶段都有一个要执行的回调FIFO队列。虽然每个阶段都以其自己的方式特殊,但通常情况下,当事件循环进入给定阶段时,它将执行特定于该阶段的任何操作,然后在该阶段的队列中执行回调,直到队列耗尽或最大回调数量为止已执行。当队列耗尽或达到回调限制时,事件循环将移至下一阶段,依此类推。关于事件循环是一个核心点,经常会被面试官考具体执行输出的问题,大家可以看我的这篇文章

跨平台

起初,Node 只能在 Linux 平台上运行。后来随着 Node的发展,微软注意到了它的存在,并投入了一个团队帮助 Node 实现 Windows 平台的兼容,在v0.6.0版本发布时,Node 已经能够直接在 Window 平台运行了。Node 是基于libuv实现跨平台的。

Node.js的弊端

单线程带来的弊端

Node.js中有一个特点就是单线程,它带来了很多好处,但是它也有弊端,单线程弱点如下。

  1. 无法利用多核CPU
  2. 错误会引起整个应用退出无法继续调用异步I/O
  3. 大量计算占用CPU导致无法继续调用异步I/O

以上确实是Node的弊端,但是都会有一些对应的解决方案:

弊端1:解决方案

  • (1)一些管理工具比如pm2,forever 等都可以实现创建多进程解决多核 CPU 的利用率问题。
  • (2)在v0.8版本之前,实现多进程可以使用child_process
  • (3)在v0.8版本之后,可以使用cluster模块,通过主从模式,创建多个工作进程解决多核CPU的利用率问题。

弊端2:解决方案

  • (1)Nnigx反向代理,负载均衡,开多个进程,绑定多个端口;
  • (2) 一些管理工具比如pm2,forever 等都可以实现进程监控,错误自动重启等
  • (3)开多个进程监听同一个端口,使用Node提供的cluster模块;
  • (4)未出现cluster之前,也可以使用child_process,创建多子线程监听一个端口。
  • (5)这里说明下,有上面的这些解决方案,但是写node后端代码的时候,异常抛出try catch显得格外有必要。

弊端3:解决方案

  • (1)可以把大量的密集计算像上面一样拆分成多个子线程计算
  • 但是如果不允许拆分,想计算100万的大数据,在一个单线程中,Node确实显得无能为力,这本身就是V8内存限制的弊端。

说明:child_process与cluster模块我会单独拿一篇文章来讲。值得开心的是上面这些弊端随着Node的版本更新,和新的api模块出现,好像解决了这些弊端。

调试

用过node的人可能第一时间就会想到debug太难了,没有stack trace,因此调试比较困难。

Node社区中的npm包

Node.js社区有很多包品质良莠不齐、如果你想偷懒而又刚好npm了一个有问题的包你就很麻烦,因为代码是开源的,只能自己调试了。

Node.js的应用场景

介绍了Node.js的特点和弊端,再说一下Node.js的应用场景。

Node.js适合用来开发什么样的应用程序呢?

善于I/O,不善于计算。因为Node.js最擅长的就是任务调度,如果你的业务有很多的 CPU 计算,实际上也相当于这个计算阻塞了这个单线程,就不太适合Node开发,但是也不是没有解决方案,只是说不太适合。

当应用程序需要处理大量并发的I/O,而在向客户端发出响应之前,应用程序内部并不需要进行非常复杂的处理的时候,Node.js非常适合。Node.js也非常适合与websocket配合,开发长连接的实时交互应用程序。

具体场景可以表现为如下:

  • 第一大类:用户表单收集系统、后台管理系统、实时交互系统、考试系统、联网软件、高并发量的web应用程序;

  • 第二大类:基于web、canvas等多人联网游戏;

  • 第三大类:基于web的多人实时聊天客户端、聊天室、图文直播;

  • 第四大类:单页面浏览器应用程序;

  • 第五大类:操作数据库、为前端和移动端提供基于json的API;

  • 第六大类,....

更多招聘信息

扫码添加我的微信,一定要备注面试,进入面试群,或者与我交流。

加我微信拉你进入面试交流群

关注该公众号接收各大厂招聘信息,直达大厂负责人。如果你是技术负责人,欢迎投递内推信息。

更多大厂招聘,面试面经,技能要求,请关注公众号【互联网大厂招聘】

回调函数 相当于线程_阿里面试题:请简述下 Node 的线程模型相关推荐

  1. c++ 传入回调函数 参数没有传入_一文读懂回调函数

    1 什么是回调函数? 来自公众号:C语言与cpp编程 首先什么是"回调"呢? 我的理解是:把一段可执行的代码像参数传递那样传给其他代码,而这段代码会在某个时刻被调用执行,这就叫做回 ...

  2. python回调函数的作用是_回调函数的意义以及python实现

    因工作需要,最近在学习使用python来解析各种文件,包括xmind,xml,excel,csv等等. 在学习python解析XML的时候看到这样一段话: 当时就犯了老毛病,被一个不是很知道的名词引起 ...

  3. java 创建线程_【80期】说出Java创建线程的三种方式及对比

    点击上方"Java面试题精选",关注公众号 面试刷图,查缺补漏 >>号外:往期面试题,10篇为一个单位归置到本公众号菜单栏->面试题,有需要的欢迎翻阅. 一.Ja ...

  4. python如何停止子线程_【已解决】python 如何结束子线程呢

    复制内容到剪贴板 代码:# -*- coding:utf-8 -*- import wx import os import sys import configparser import ftpserv ...

  5. 线程间共享 部分变量 Spring框架下向异步线程传递HttpServletRequest参数

    参考 https://www.jianshu.com/p/6bf1adb775e0 https://blog.csdn.net/kid551/article/details/88703414 需求场景 ...

  6. pc端编码表必须为gbk才能正常启动软件_【干货】请收下这份非常完整的PCIE4.0 发送端测试SOP...

    编者注:本文作者为 是德科技(中国)有限公司的马卓凡.黄腾.刘宗祺.PCIE4.0的电气特性分为了发送端测试和接收端测试,本文主要介绍的是发送端测试. 一.前言 进入2019年,随着5G商用的坚实推进 ...

  7. c语言注册回调函数主要用途,C语言回调函数的概念及其应用

    笔者能力有限,如果文中有错误的地方,欢迎各位朋友给我及时地指出来,我将不甚感激,谢谢~ 概念 引用维基百科上的关于回调函数的概念:在计算机程序设计中,回调函数,或简称回调(Callback 即call ...

  8. linux 线程_浅谈Linux线程模型

    Thread Basic 基础概念 线程是操作系统能够调度和执行的基本单位,在Linux中也被称之为轻量级进程.从定义中可以看出,线程它是操作系统的概念,在不同的操作系统中的实现是不同的,不过今天分享 ...

  9. js回调函数的理解(轉)

    js回调函数(callback)理解Mark!讲之前说一句function say(){alert(,,,,,,,,)}var say=function (){alert(,,,,,,,)}var s ...

最新文章

  1. 在虚拟机中安装Ubuntu Server 15.04
  2. 专用ADC与群集软件之比较
  3. 大白话解析模拟退火算法、遗传算法入门
  4. python字符串内建函数_python字符串内建函数
  5. (需求实战_终章) SpringBoot2.x 整合RabbitMQ
  6. c语言非线程安全函数引发的BUG一列
  7. 用PS为网迅安卓公司设计基于安卓平台的手机应用图标
  8. 微软水下数据中心“浮出水面”、GitHub代码保存在北极,数据黑科技贮藏方式大曝光!...
  9. fmpeg分析视频gop的大小
  10. 公有云、私有云和混合云介绍
  11. 物联网平台搭建的全过程介绍(五)——基于阿里云物联网平台的Android聊天app源码
  12. vue拼接html并绑定点击事件
  13. STM32定时器-6步PWM输出
  14. 中断优先级和中断线程优先级
  15. 下载tensorflow时遇到的问题
  16. python- 按指定列值筛选数据
  17. java项目统一打印入参出参等日志
  18. regsvr32命令详解
  19. 基于QT的TCP通信
  20. proteus使用NE555简易电子琴仿真

热门文章

  1. python函数库_10. 标准库简介
  2. c++二维数组指针详解
  3. TensorFlow下安装matplotlib模块
  4. 操作系统--内核级线程实现
  5. git远程分支修改名字
  6. 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
  7. ftp+linux+使用webdav,群晖-win/mac/nfs ftp tftp webdav文件服务的概念及设置
  8. redirect java 配置_Java从后台重定向(redirect)到另一个项目的方法
  9. linux 管道 top,linux IPC总结——管道
  10. 现代软件工程 其实还是人的问题