Node.js学习

1 Node.js简介

1-1 Node.js是什么?

node.js不是一种独立的语言,也不是一个JavaScript框架,是一个让JavaScript运行在服务器端的开发平台。

1-2 node能做什么

1.具有复杂逻辑的网站

2.具有社交网络的大规模web应用

3.Web Socket服务器

4.TCP/UDP套接字应用程序

5.命令行工具

6.交互式终端程序

7.带有图形用户界面的本地应用程序

8.单元测试工具

9.客户端JavaScript编译器

2 node.js架构/特点

2-1 异步式I/O与事件驱动

2-1.1 阻塞和线程

  2-1.1.1 进程VS线程

    进程是计算机正在运行程序的实例,进程是程序的实体,进程是线程的容器。

    线程,有时候被称为轻量级进程,是程序执行流的最小单位。一个标准的线程由线程id,当前指令指针(PC),寄存器集合和堆栈组成。

  2-1.1.2 阻塞

    线程在执行中如果遇到磁盘读写或者网络通信(I/O操作),通常需要耗费较长的时间,这时候操作系统会剥夺这个线程的CPU控制权,使其暂停执行,将资源让给其他的工作线程,这种线程调度方式称为阻塞。

    当I/O操作完毕,操作系统将这个线程的阻塞状态解除,恢复其对CPU的控制权,令其继续执行。这种I/O模式就是通常所说的同步式I/O或阻塞式I/O。

2-1.2 高并发的传统解决方案

  2-1.2.1 多线程模型

    对于高并发的解决方案,传统的架构是多线程模型,也就是为每个业务逻辑提供一个系统线程,通过系统线程切换来弥补同步式 I/O 调用时的时间开销。

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

   2-1.2.2  同步式I/O

举例

res = db.query('SELECT * from some_table');

res.output();

 代码执行第一行,线程会阻塞,等待数据库查询结果/网络通信,接收到结果赋值给res,res将结果输出。

   如果同时有上千个任务高并发,不断创建新的线程来处理,浪费系统资源,占用CPU时间来处理上下文的切换。I/O阻塞了代码的执行,极大地降低了程序的执行效率。

2-1.3  Node.js的单线程模式

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

另外,单线程带来的好处,操作系统完全不再有线程创建、销毁的时间开销。坏处,就是一个用户造成了线程的崩溃,整个服务都崩溃了,其他人也崩溃了。不过以上缺点可以可以通过代码的健壮性来弥补。

  2-1.3.1  异步式I/O请求方式

举例

db.query('SELECT * from some_table',function(res){

   res.output();

});

db.save(data);

程序执行db.query不会等待查询结果,直接执行后面的语句db.save的操作,一直执行后面的语句直到进入事件循环,当查询结果返回的时候,会发送一个事件到事件队列,等到事件循环到回调函数的时候,再执行回调函数里面的逻辑。

  2-1.3.2   事件队列,事件不断循环

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

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

    阻塞模式下,一个线程只能处理一项任务,要想提高吞吐量必须通过多线程

    非阻塞模式下,一个线程永远在执行计算操作,这个线程的CPU核心利用率永远是100%

    所以,这是一种特别有哲理的解决方案:与其人多,但是好多人闲着;还不如一个人玩命,往死里干活儿

  2-1.3.3   事件驱动/事件循环

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

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

    说是三个特点,实际上是一个特点,离开谁都不行,都玩儿不转了。Node.js很像抠门的餐厅老板,只聘请1个服务员,服务很多人。结果,比很多服务员效率还高。Node.js中所有的I/O都是异步的,回调函数,套回调函数。

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

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

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

事件循环

2-2  node.js架构

Libev、libeio——支持linux、Mac OS、Unix等系统的事件驱动、异步式I/O

IOCP——支持Windows的事件驱动、异步式I/O

原文地址:https://www.cnblogs.com/SallyShan/p/12765590.html