【入门指南】node.js

node.js简介

  • node.js不是一种独立语言,是一个可让js在服务器端运行的平台
  • 区别与传统语言平台依靠多线程来实现高并发的设计思路,node采用单线程、异步式I/O、事件驱动式的程序设计模型
  • node.js使用的JavaScript引擎为V8引擎,还使用了高效的 libev 和 libeio 库支持事件驱动和异步式 I/O 来代替传统平台的多线程模式,带来性能的提高(传统多线程模式对于 高并发的访问,一方面线程长期阻塞等待,另外一方面为了应付新请求而不断增长线程,所以 会浪费大量系统资源,同时线程的增多也会占用大量的 CPU 时间来处理内存上下文切换, 并且还容易遭受低速链接攻击。)
  • 有别于php等语言,在使用php构建web服务时,必须外部依赖一个Nginx、Apache等http服务器,而后经过http服务区的模块加载或CGI调用,才能将php的执行结果呈现给用户;而node.js内置了http服务器模块,无需再额外搭建
  • node.js能够调用c/c++代码,对于性能要求比较高的模块可使用c/c++来实现

node.js只在第一次运行时会读取文件内容,之后都会直接访问内存,也就是当文件实时改动时,不会触发从新编译文件内容,因此须要使用supervisor、pm2等工具,对node服务进行实时管理php

异步式I/O 与事件驱动式编程

阻塞与线程

什么是阻塞(block)呢?线程在执行中若是遇到磁盘读写或网络通讯(统称为 I/O 操做), 一般要耗费较长的时间,这时操做系统会剥夺这个线程的 CPU 控制权,使其暂停执行,同 时将资源让给其余的工做线程,这种线程调度方式称为 阻塞。当 I/O 操做完毕时,操做系统 将这个线程的阻塞状态解除,恢复其对CPU的控制权,令其继续执行。这种 I/O 模式就是通 常的同步式 I/O(Synchronous I/O)或阻塞式 I/O (Blocking I/O)node

异步式 I/O (Asynchronous I/O)或非阻塞式 I/O (Non-blocking I/O)则针对 全部 I/O 操做不采用阻塞的策略。当线程遇到 I/O 操做时,不会以阻塞的方式等待 I/O 操做 的完成或数据的返回,而只是将 I/O 请求发送给操做系统,继续执行下一条语句。当操做 系统完成 I/O 操做时,以事件的形式通知执行 I/O 操做的线程,线程会在特定时候处理这个 事件。为了处理异步 I/O,线程必须有事件循环,不断地检查有没有未处理的事件,依次予 以处理。c++

多线程与单线程的比较:

对于须要长时间计算的I/O处理操做web

  • 多线程模式:若是想实现高并发,就必须开启多个线程 shell

  • 单线程模式:I/O异步,经过事件方式通知线程,便可完成高并发 express

单线程事件驱动的异步式 I/O 比传统的多线程阻塞式 I/O 究竟好在哪里呢?npm

  • 简而言之, 异步式 I/O 就是少了多线程的开销。对操做系统来讲,建立一个线程的代价是十分昂贵的, 须要给它分配内存、列入调度,同时在线程切换的时候还要执行内存换页,CPU 的缓存被 清空,切换回来的时候还要从新从内存中读取信息,破坏了数据的局部性。(基于多线程的模型也有相应的解决方案,如轻量级线程(lightweight thread)等。事件驱动的单线程异步模型与多线 程同步模型到底谁更好是一件很是有争议的事情,由于尽管消耗资源,后者的吞吐率并不比前者低)
  • 异步式编程的缺点在于不符合人们通常的程序设计思惟,存在回调地狱的状况(使用async、promise等编写方式)

node.js的事件循环机制

Node.js 程序由事件循环开始,到事件循环结束,全部的逻辑都是事件的回调函数,因此 Node.js 始终在事件循环中,程序入口就是 事件循环第一个事件的回调函数。事件的回调函数在执行的过程当中,可能会发出 I/O 请求或 直接发射(emit)事件,执行完毕后再返回事件循环,事件循环会检查事件队列中有没有未 处理的事件,直到程序结束.编程

与其余语言不一样的是,Node.js 没有显式的事件循环,相似 Ruby 的 EventMachine::run() 的函数在 Node.js中是不存在的。Node.js的事件循环对开发者不可见,由libev库实现。libev支持多种类型的事件,如 ev_io、ev_timer、ev_signal、ev_idle 等,在 Node.js 中均被 EventEmitter 封装。libev 事件循环的每一次迭代,在 Node.js 中就是一次 Tick,libev 不 断检查是否有活动的、可供检测的事件监听器,直到检测不到时才退出事件循环,进程结束json

npm包管理器

建立npm包

Node.js 根 据 CommonJS 规范实现了包机制,开发了 npm来解决包的发布和获取需求。 使用以下命令初始化建立npm包数组

npm init
复制代码

Node.js 的包是一个目录,其中包含一个 JSON 格式的包说明文件 package.json。严格符 合 CommonJS 规范的包应该具有如下特征:

  • package.json 必须在包的顶层目录下;
    • 做为npm包的描述性文件,其中经常使用的字段:
    • main:做为包模块的入口(Node.js 在调用某个包时,会首先检查包中 package.json 文件的 main 字段,将其做为包的接口模块,若是 package.json 或 main 字段不存在,会尝试寻找 index.js 或 index.node 做 为包的接口)
    • name:包的名称
    • description:包的简要说明
    • version:版本字符串
    • keywords:关键字数组,一般用于搜索
    • maintainers:维护者数组,每一个元素要包含 name、email (可选)、web (可选)字段
    • contributors:贡献者数组,格式与maintainers相同。包的做者应该是贡献者数组的第一个元素
    • bugs:提交bug的地址,能够是网址或者电子邮件地址
    • licenses:许可证数组
    • repositories:仓库托管地址数组
    • dependencies:包的依赖,一个关联数组,由包名称和版本号组成
  • 二进制文件应该在 bin 目录下;
  • JavaScript 代码应该在 lib 目录下;
  • 文档应该在 doc 目录下;
  • 单元测试应该在 test 目录下。 Node.js 对包的要求并无这么严格,只要顶层目录下有 package.json,并符合一些规范 便可。固然为了提升兼容性,咱们仍是建议你在制做包的时候,严格遵照 CommonJS 规范

本地模式与全局模式

全局模式的安装:

npm [install/i] -g [package_name]

为何要使用全局模式呢?多数时候并非由于许多程序都有可能用到它,为了减小多 重副本而使用全局模式,而是由于本地模式不会注册 PATH 环境变量。举例说明,咱们安装 supervisor 是为了在命令行中运行它,譬如直接运行 supervisor script.js,这时就须要在 PATH 环境变量中注册 supervisor。npm 本地模式仅仅是把包安装到 node_modules 子目录下,其中 的 bin 目录没有包含在 PATH 环境变量中,不能直接在命令行中调用。而当咱们使用全局模 式安装时,npm 会将包安装到系统目录,譬如 /usr/local/lib/node_modules/,同时 package.json 文 件中 bin 字段包含的文件会被连接到 /usr/local/bin/。/usr/local/bin/ 是在PATH 环境变量中默认 定义的,所以就能够直接在命令行中运行 supervisor script.js命令了

使用全局模式安装的包并不能直接在 JavaScript 文件中用 require 获 得,由于 require 不会搜索 /usr/local/lib/node_modules/

区别:

  • 当咱们要把某个包做为工程运行时的一部分时,经过本地模式获取
  • 若是要 在命令行下使用,则使用全局模式安装

建立全局连接

npm 提供了一个有趣的命令 npm link,它的功能是在本地包和全局包之间建立符号链 接。咱们说过使用全局模式安装的包不能直接经过 require 使用,但经过 npm link命令 能够打破这一限制。举个例子,咱们已经经过 npm install -g express 安装了 express, 5 这时在工程的目录下运行命令: npm link express ./node_modules/express -> /usr/local/lib/node_modules/express 咱们能够在 node_modules 子目录中发现一个指向安装到全局的包的符号连接。经过这种方法,咱们就能够把全局包当本地包来使用了

除了将全局的包连接到本地之外,使用 npm link命令还能够将本地的包连接到全局。 使用方法是在包目录( package.json 所在目录)中运行 npm link 命令。若是咱们要开发 一个包,利用这种方法能够很是方便地在不一样的工程间进行调试和测试

具体使用案例:

如今有两个模块,npm-link-module为咱们开发的npm包;npm-link-test为咱们要使用上面的npm包来作测试

cd npm-link-module  //进入开发的npm包目录里
npm link //将本地的包连接到全局

cd npm-link-test  //进入到测试项目中
npm link npm-link-module  //将全局包npm-link-module 连接到本地node_modules路径下,这样本地就可使用require()引用了
复制代码

包的发布

  • npm adduser 建立帐号
  • npm whoami 命令测验是否已经取得了帐号
  • npm publish 发布包
  • 经过https://www.npmjs.com/ 去搜索本身发布的包
  • 往后有更新时,更改package.json中的version版本,从新npm publish便可
  • npm unpublish 取消已发布的包

node命令行调试(调试功能由 V8 提供)

使用node debug xxx.js 便可开启调试模式

相关文章
相关标签/搜索