node核心特性理解

原文地址在个人博客,转载请注明来源,谢谢!javascript

node是在前端领域常常看到的词。node对于前端的重要性已经不言而喻,掌握node也是做为合格的前端工程师一项基本功了。知道node、知道后端的一些东西,才能更好的与别人合做,发挥更大的价值。css

概述

本文主要介绍了我对node的一些核心特性的理解,包括node架构、特色、机制、核心模块与简单应用。html

正文

从浏览器到node

首先,node是一个平台,使用javascript做为编程语言,运行在服务端。服务端语言能作的,node通常都能作,并且有些状况下作的更好,由于它具备本身的特点。前端

node是javascript运行环境(runtime),就像浏览器同样,是一个平台。在浏览器中,V8引擎负责解释javascript,你在javascript调用的接口都是浏览器实现并提供的,浏览器会调用底层的、由其余语言(C++)实现并封装好的接口来完成任务;一样,在node中,也是V8引擎负责解释javascript,而你在javascript调用的浏览器提供的接口就不能用了,由于它脱离了浏览器的环境,可是由于你在node环境中,你就可使用node提供的由C++语言实现的、由javascript封装好的各类接口来完成后端任务。浏览器提供的API用于处理前端任务,好比弹个窗,换个主题,处理用户操做等,而node由于服务后端,所以提供的API则用来处理后端任务,好比响应请求,读取文件等,这些API由不一样的模块提供。由于关注领域不同,所以所作的任务就不同,提供的API就不同,可是原理、相关实现大体与浏览器端相同。java

从浏览器到node这一块若是想了解更多,推荐IBM的文章node.js究竟是什么?node

node 架构

node架构分为三层(参考连接):git

图片来源github

  • Node standard library:node标准库,也就是node模块提供各类接口的javascript实现,任何javascript代码、npm install 或者你写的模块都在这里
  • Node bindings:包括C/C++ bindings(胶水代码)和Add on(添加其余C/C++库时须要本身写的Bindings),这一层向下封装了V8和libuv接口,向上提供了基础API接口,是链接javascript和C++的桥梁
  • 第三层是支撑 Node.js 运行的关键,由 C/C++ 实现。
    • V8 是Google开发的JavaScript引擎,提供JavaScript运行环境,能够说它就是 Node.js 的发动机,负责解释javascript,与chrome浏览器相同。
    • Libuv 是专门为Node.js开发的一个封装库,提供跨平台的异步I/O能力,负责node运行时的线程池调度。
    • C-ares:提供了异步处理 DNS 相关的能力。
    • http_parser、OpenSSL、zlib 等:提供包括 http 解析、SSL、数据压缩等系统底层的访问。

日常咱们用到的也就是第一层node各个模块实现的接口。chrome

那他们之间时如何协做的呢数据库

javascript主线程
javascript主线程

程序启动,V8引擎会首先解析javascript代码,经过Node bindings来调用C/C++库。执行到当前事件时,会把事件放在调用堆栈(stack和heap)处理(能够理解为放进一个工做空间,如上图),在堆栈中的任何I/O请求都会交给libuv来处理,libuv维持一个线程池,里面是一些工做线程(以下图),请求会调用这些线程来完成任务,这些线程则调用底层的C/C++库。完成时,libuv再把结果返回事件队列等待主线程执行。在此期间,主线程继续执行其余任务。

node 执行特性

单线程、非阻塞型I/O

单线程的意思就是只在一个线程上运行javascript。首先,javascript 在浏览器端是单线程的,这是为了不多线程产生任务冲突的状况;其次,java和PHP这类多线程后端语言,为避免同步I/O阻塞,每处理一个链接都会产生一个新线程,这样的话在遇到大量并发请求时就会受到物理内存的限制。node 延续了浏览器端单线程javascript,只用一个主线程执行javascript,不断循环遍历事件队列,执行事件。事实上,主线程发出的I/O请求,都会交给其余线程去完成,其余线程完成后悔返回结果放到事件队列。在此期间,主线程会继续执行其余任务,也就是在交给libuv后直接返回,继续执行下面的任务,主线程只负责循环执行事件队列,所以这种模式称为非阻塞型I/O,性能很好,适用于处理大量并发请求,还能简化开发。

事件驱动机制

仍是跟浏览器的差很少。总的来讲就是,浏览器端把鼠标点击、键盘按键等定义为事件,而node把网络请求、I/O操做等也看做事件,严格来讲,一切动做都是事件,这就是事件驱动的思想。在程序启动时,便进入事件循环,不断遍历执行事件队列中产生的事件,而在执行过程当中,又会产生新的事件,所以称为事件循环。主线程执行事件时,遇到麻烦的I/O请求会交给libuv来调度其余工做线程来帮忙,忙完后就会造成事件返回结果到事件队列等待主线程处理。在此期间,主线程会继续执行其余任务。

mbp 曾经作过一个巧妙的比喻,把 Node.js 当作一家餐厅。我在此借用下他的例子,稍做修改来阐述下 Node.js 的执行状况:

把 Node.js 应用程序想象成一家星巴克,一个训练有素的前台服务生(惟一的主线程)在柜台前接受订单。当不少顾客同时光临的时候,他们排队(进入事件队列)等候接待;每当服务生接待一位顾客,服务生会把订单告知给经理(libuv),经理安排相应的专职人员去烹制咖啡(工做线程或者系统特性)。这个专职人员会使用不一样的原料和咖啡机(底层 C/C++ 组件)按订单要求制做咖啡或甜点,一般会有四个这样的专职人员保持在岗待命(线程池),高峰期的时候也能够安排更多(不过须要在一早就安排人员来上班,而不能中午临时通知)。服务生把订单转交给经理以后不须要等着咖啡制做完成,而是直接开始接待下一位顾客(事件循环放进调用堆栈的另外一个事件),你能够把当前调用堆栈里的事件当作是站在柜台前正在接受服务的顾客。

当咖啡完成时,会被发送到顾客队列的最后位置,等它移动到柜台前服务生会叫相应顾客的名字,顾客就来取走咖啡(最后这部分在真实生活中听起来有点怪,不过你从程序执行的角度理解就比较合乎情理了)。

​ ——By Amio

若是你想进一步了解javascript 事件驱动机制,推荐深刻理解 javascript 事件循环机制

node 模块

node 模块机制是CommonJs 的实现。起初,javascript 标准一片混沌,并无其余成熟语言(例如C++)的模块机制、标准库、接口等,为了让javascript 具有开发大型应用的能力,为了让 javascript 能在后端运行,CommonJS 就制定了javascript 模块规范。node 借鉴了这个规范,让javascript 以模块形式组织起来。模块机制是一个成熟语言必备的,一个模块表明一个功能的封装,它就像搭积木同样,不一样模块能够衔接在一块,使语言具备极强的可扩展型。node 模块机制同时制定了模块规范,能让全球的开发者均可以在node官网上传本身的包。此外,node 社区又实现了node 包管理器npm,使用npm能够轻松管理各类包。

node 的模块分为核心模块和用户模块,前者是底层的、自带的,后者是第三方。

核心模块有Global(全局对象)、Http、fs(文件系统)、Buffer、Stream、Events、URL、path等,这些模块提供了后端服务的基本功能,都提供本身关注功能的API。

在使用模块时,require 便可。但在require背后,node 有一套寻找模块的机制:

node require机制
node require机制

从上图能够看到,node 优先从缓存区读取,缓存区有直接读取,没有则加载并缓存,这样作不用一遍一遍去找了,很是高效。node 在缓存区没有发现模块时,会分析require 的路径和文件后缀,node 有个模块路径的查找策略,咱们能够在名为module_paths 的js文件里console.log(module.paths)而后node module_paths.js运行来间接查看node 寻找文件模块的具体文件的方式:

[ '/home/username/nodeProject/node_modules',
 '/home/username/node_modules',
 '/home/node_modules',
 '/node_modules' ] //Linux下的数组输出(/home/username因电脑不一样而异)

[ 'c:\\nodeProject\\node_modules', 'c:\\node_modules' ] //Windows复制代码

也就是按照下面的顺序:

  • 当前文件目录下的node_modules目录。
  • 父目录下的node_modules目录。
  • 父目录的父目录下的node_modules目录。
  • 沿路径向上逐级递归,直到根目录下的node_modules目录。

这些顺序都是在查找缓存以后的。

在找到模块后,node 将在引入以前对这个模块进行编译执行,编译成功后会缓存,执行的结果会返回给调用者。

简单应用

有了node 自带核心模块的基础功能,就能够进一步封装更强大、容易操做的功能了,就像jQuery 对于javascript 基础API 同样,node 社区也诞生了像 Express、KOA等框架来构建node.js程序

node.js开发框架
node.js开发框架

这些框架的详情移步2017 Node.js 开发框架比较

另外,node 还能够链接MySQL,MangoDB进行数据库操做。

下面是使用express 脚手架生成的基本 node应用结构:

.
├── app.js            //程序入口
├── bin
│   └── www              //二机制文件
├── package.json      //项目配置文件
├── public
│   ├── images        
│   ├── javascripts
│   └── stylesheets
│       └── style.css
├── routes
│   ├── index.js      //路由文件入口
│   └── users.js
└── views
    ├── error.jade    //界面模板
    ├── index.jade
    └── layout.jade复制代码

如今使用 node做为后端语言一般都要配合类库和框架使用。

node 的单线程、非阻塞型特色让它很是适合高并发的应用,适合处理大量重复的、简单的逻辑,适合构建Rest/JSON API服务;同时,也正是由于这些特性,node 不适合CPU使用率较重、IO使用率较轻的偏计算应用。缺点是由于单线程,一个进程挂就全挂了,可靠性低,但这是能够避免的。node 更多的应用是在前端、中间件、先后端分离等。

因为 node 的诸多优势,如今愈来愈多大公司开始使用node、深度使用node。

总结

node 的核心概念、思想远不止这么多,应用更是多了去了,无奈本人水平有限,只能说个浅层,还有不少像进程管理、异步编程、异常调试、部署、性能调优、与集群、CDN协调等都值得深刻探索一下。不管如何,node 是让javascript 迈向企业级开发语言重要的一步(也许已是了),前端工程师从未像如今这样的powerful,能作的事情愈来愈多,所能涉及的领域也愈来愈多。前端这行愈来愈使人兴奋了。

相关文章
相关标签/搜索