### Node 简述 ``` Node构建与V8引擎之上, 其模型与浏览器类似, javascript运行在单个进程的单个线程之上。 其好处是: 程序状态是单一, 在没有多线程的情况下没有锁、线程同步的问题, 操作系统在调 度时也因为较少上下文切换, 可以很好的提高CPU的使用率。 而如今, CPU基本都是多核的, 一个Node进程只能利用一个核, 这将抛出Node应用的第一个问题: 如何充分利用多核CPU服务器? 另外, Node执行在单线程上, 一旦抛出的异常无法捕获, 将会引起整个进程的崩溃, 则问题二: 如何保证进程的健壮性和稳定性? ``` ### 服务模型的变迁 ``` 1、 石器时代: 同步 早期的服务器, 执行模型为同步, 其模式为一次只为一个请求服务, 所有请求都得按次序等待服务。 意味着除了当前请求被处理外, 其余请求都处于耽搁状态, 假设每次响应服务耗用的时间稳定为N秒, 这类服务的QPS为1/N. 2、 青铜时代: 复制进程 为解决同步架构的问题, 改进为通过进程的复制同时服务更多的请求和用户。 在进程的复制的过程中, 需要复制进程内部的状态, 对于每个链接都进行这样的复制的话, 相同的状态将会在内存中存在很多份,造成浪费, 并且复制过程要复制较多的数据, 启动 较为缓慢。 预复制: 即预先复制一定数量的基础, 同时将基础复用, 避免进程创建、销毁带来的开销, 但是这个模型并不具备伸缩性, 一 旦并发请求过高, 内存使用随着进程数的增长将会被耗尽。 假设进程上线为M, 这类服务的QPS为M/N; 3、 白银时代: 多线程 为解决进程复杂中的资源浪费问题, 多线程被引入服务模型: 让一个线程服务一个请求。 线程相对进程的开销要小得多, 并且线程 之间可以共享数据, 内存浪费的问题可以得到解决,并且利用线程池可以减少创建和销毁线程的开销。 但是, 多线程也所面临的并发 问题也只是比多进程略好。 因为, 每个线程都拥有自己独立的堆栈, 这个堆栈都需要占用一定的内存空间。 另外, 由于一个CPU核 心在一个时刻只能做一件事情, 操作系统只能通过将CPU切分为时间片的方法, 让线程可以较为均匀地使用CPU资源。 但是, 操作系 统在切换线程的同时也要切换线程的上下文, 当线程数量过多时, 时间将会被耗用在上下文切换中。 忽略掉上下文切换的开销, 假设线程所占用的资源为进程的1/L,其QPS为: M*L/N; 4、 黄金时代: 时间驱动 为解决高并发问题, 基于事件驱动的服务模型出现了, 像Node和Nginx均是基于事件驱动的方式实现, 采用单线程避免了不必要的 内存开销和上下文切换开销。 基于事件的服务模型存在的问题主要表现为: CPU的利用率和进程的健壮性。 由于所有的处理都在单线程上进行, 影响事件驱动服务模型性能的点在于CPU的计算能力, 它的上限决定这类服务模型的性能上限, 但, 不受多进程或多线程模式中的资源上限的影响, 可收缩性较强。 ```