Node.js
Node.js前言
- Node.js之父 Ryan Dahl(瑞安·达尔)
数学系博士, 中途退学, 选择了诗和远方 为了生活, 学习了Ruby On Rails接Web项目, 经过两年成了Web服务器专家 第一个阶段: 接项目做网站 第二个阶段: 帮助客户解决性能问题 工作少了, 活更高端, 钱赚的更多了 2009年推出Node.js, 2012年退出Node.js, 转战Go语言 Node适合小型,实时事务型服务器网站 GO更适合构建大型服务器网站 不要说某种语言好或者不好, 都有各自的应用场景, 只有合适不合适
- Node出现的背景 为了解决Web服务器的高并发性能问题 什么性能问题?
- 缩短发送到响应的时长 发送请求快一点 :不能控制(客户端网速决定) 响应快一点 :可以控制(服务器带宽提高, CDN加速…) 服务器处理请求任务快一点:可以控制(优秀的程序员) 多线程:发送一个请求就开启一条线程 服务器从磁盘读取/写入数据到数据库快一点 所有项目后期都会遇到的瓶颈:不能控制(磁盘的读取速度有上限)
- 传统服务器的运作流程 如何避免I/O阻塞?
Ryan Dahl(瑞安·达尔)尝试过用Ruby, c, Lua去解决, 但都因为语言自身的各种限制而一一失败 语言历史包袱太重, 船大难掉头 各种语言的思想都根深蒂固, 生态没法轻易改变 渐渐摸索到解决问题的钥匙:事件驱动 异步I/O
V8引擎的出现
- 什么是V8引擎?
一款专门对JavaScript语言进行解释和执行的流程虚拟机 比如把V8引擎嵌入到浏览器中,那么我们写的JavaScript代码就会被浏览器所执行;那么如果把V8引擎嵌入到NodeJS环境下,那么我们写的JavaScript代码就会被服务器所执行。 只要V8引擎能够嵌入到不同的宿主环境中,那么就可以用JavaScript语言来写各种不同领域的应用。 —万能的JS
- 起初的作用?
用于Chrome浏览器解析js脚本 比如: 发送HTTP请求给服务器, 响应服务器端返回的HTTP请求
- 引擎的优势?
- 强大的编译和快速执行效率
- 运用了大量的算法和奇技淫巧
- 性能非常好, 它的执行效率远超Python, Ruby等其它脚本语言
- 历史包袱轻, 没有同步I/O
- 强大的事件驱动机制
- Node的诞生
Ryan Dahl(瑞安·达尔)修改V8引擎的内核, 把它用在了服务器开发, 经过修改后的这样一套东西就被称为Node.js
Node.js简介
什么是Node.js
Node.js是一个让JavaScript运行在服务器端的开发平台 Node之前, js代码只能运行在客户端, 最多只能在浏览器内翻江倒海 Node之后, js代码可以和操作系统(Mac OS, windows, Linux…)交互, 战场从浏览器延伸到了服务器
- 版本变化
一开始叫Web.js, 目的就是用于写高性能Web服务器的越写越大, 形成生态(服务器开发, 各种框架的依赖…), 改名为Node.js Node: 节点, Node的开源团队希望它像节点一样可以不断扩展, 壮大 Joyent收购Node,把它变成公司旗下的一产品, 但程序员都有一颗开源的心(共产主义, 希望Node不属于某个人,某个公司), 退出, 搞了个io.js , 分久必合合久必分原来是0.几, 突然来了个4.0, 不要感觉奇怪!Node 奇数是开发版, 偶数是稳定版
- 功能类似的其他后端语言 PHP、JSP、Python、Ruby 和系统进行交互
- 和其它后端语言的区别 Node.js不是一种独立的语言 PHP, JSP,… 既是语言, 也是平台 Node.js用JavaScript进行编程, 运行平台是包装后的js引擎(V8) 轻量级架构 java,php,.net都需要运行在服务器上,apache,tomat,naginx,IIS Node.js不用架设在任何服务器软件之上 用最小的硬件成本, 达到更高的并发, 更优的处理性能
Node.js的特点
单线程
- 优势 减少了内存开销(操作系统完全不再有线程创建、销毁的时间开销) 在Java、PHP或者.net等服务器端语言中,会为每一个客户端连接创建一个新的线程。而每个线程需要耗费大约2MB内存,相当于有一个人就要分配一个线程,就要占用空间大小 当有用户连接了,就触发一个内部事件,通过非阻塞I/O、事件驱动机制,让Node.js程序宏观上也是并行的。使用Node.js,一个8GB内存的服务器,可以同时处理超过4万用户的连接。 Node.js不为每个客户连接创建一个新的线程,而仅仅使用一个线程。
- 劣势 如果某一个事情,进入了,但是被I/O阻塞了,整个线程就阻塞了 如果一个人把Node.js搞崩溃,全部崩溃(但很难搞崩溃)
非阻塞I/O 基本概念?
当在访问数据库取得数据的时候,需要一段时间。在传统的单线程处理机制中,在执行了访问数据库代码之后,整个线程都将暂停下来,等待数据库返回结果,才能执行后面的代码。也就是说,I/O阻塞了代码的执行,极大地降低了程序的执行效率。
不会傻等I/O语句结束,而会执行后面的语句。 Node.js中采用了非阻塞型I/O机制,因此在执行了访问数据库的代码之后,将立即转而执行其后面的代码,把数据库返回结果的处理代码放在回调函数中,从而提高了程序的执行效率。 当某个I/O执行完毕时,将以事件的形式通知执行I/O操作的线程,线程执行这个事件的回调函数。为了处理异步I/O,线程必须有事件循环,不断的检查有没有未处理的事件,依次予以处理。 阻塞模式下,一个线程只能处理一项任务,要想提高吞吐量必须通过多线程。而非阻塞模式下,一个线程永远在执行计算操作,这个线程的CPU核心利用率永远是100%。
所以,这是一种特别有哲理的解决方案:与其人多,但是好多人闲着;还不如一个人玩命,往死里干活儿。
事件驱动 基本概念? 不管是新用户的请求,还是老用户的I/O完成,都将以事件方式加入事件环,等待调度
运作流程?
在Node中,客户端请求建立连接,提交数据等行为,会触发相应的事件。 在Node中,在一个时刻,只能执行一个事件回调函数, 但是在执行一个事件回调函数的中途,可以转而处理其他事件 (比如,又有新用户连接了),然后返回继续执行原事件的回调函数,这种处理机制,称为“事件环”机制。 当某一个事件发生的时候,就去执行回调函数。执行完毕之后,再去找到事件循环当中找一个新的事件进行来
Node.js当中所有的I/O都是异步的, 都是回调函数套回调函数
Node.js的应用方向
- 特点
- 善于I/O,不善于计算 因为Node.js最擅长的就是任务调度,如果你的业务有很多的CPU计算,实际上也相当于这个计算阻塞了这个单线程,就不适合Node开发。 当应用程序需要处理大量并发的I/O,而在向客户端发出响应之前,应用程序内部并不需要进行非常复杂的处理的时候,Node.js非常适合。Node.js也非常适合与web socket配合,开发长连接的实时交互应用程序。
- 天生异步 callback:Node.js API与生俱来就是这样的 thunk:参数的求值策略 promise:最开始是Promise/A 规范,随后成为ES6标准 generator:ES6种的生成器,用于计算,但tj想用做流程控制 co:generator用起来非常麻烦,故而tj写了co这个generator生成器,用法更简单:async函数
- 适用场景
- 网站开发(如express/koa等)
- im即时聊天(socket.io)
- api(移动端,pc,h5)
- HTTP Proxy(淘宝、Qunar、腾讯、百度都有)
- 前端构建工具(grunt/gulp/bower/webpack/fis3…)
- 跨平台打包工具
- PC端的electron、nw.js,比如钉钉PC客户端、微信小程序IDE、微信客户端,移动的cordova,Phonegap,一站式开发框架ionic framework
- 写操作系统(NodeOS) 命令行工具(比如cordova、shell.js)
- 反向代理(比如anyproxy,node-http-proxy)
- 编辑器Atom、VSCode等
- Node.js也不是全能的
Node.js本是就是极客追求性能极致的产物,缺少了很多服务器的健壮考量, 所以Node不可能应用在银行、证券、电信等需要极高可靠性的业务中 中国的企业实战中,创业型公司(正处于A轮、B轮)非常爱使用Node做核心业务 ■ 功夫熊的APP,后台是Node.js在伺服 ■ 实现网,整站为Node.js搭建 成熟大企业,基本上都是用Node实现某一方面的功能: ■ 知乎用了一个Node进程,跑起了“站内信”功能 ■ 百度的很多表单,是用Node保存到数据库的
- 企业中使用的场景