当 Node 遇到多核

Node.js® is a JavaScript runtime built on Chrome’s V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient.

Node 是单线程, Event IO 模型,但服务器是 32 核心的,怎么充分利用。

Q: 进程,线程和 CPU 内核的对应关系?

线程只是用于分配单个处理器处理时间的一种机制。但假如操作系统本身支持多个 CPU/内核,那么每个线程都可以得到一个不同自己的 CPU/内核,实现真正的 并行运算。在这种情况下,多线程程序可以提高资源使用效率。

  • 单进程,单线程
  • 单进程,多线程
  • 多进程,单线程
  • 多进程,多线程

操作系统才会关心进程,CPU 是没有进程的概念的?

  • 线程是进程的一部分
  • CPU 调度的是线程
  • 系统为进程分配资源,不对线程分配资源

线程是cpu调度的一个基本单位,一个cpu同时只能执行一个线程的任务,同样一个线程任务也只能在一个cpu上执行

Q: Node 的单线程

Node 是单线程程序,它只有一个 event loop,也只占用一个 CPU/内核。现在大部分服务器都是多 CPU 或多核的,当 Node 程序的 event loop 被 CPU 密集型的任务占用,导致有其它任务被阻塞时,却还有 CPU/内核 处于闲置的状态,造成资源的浪费。

同时一旦这个进程崩掉,那么整个 web 服务就崩掉了。

单线程的好处:

  • 安全: 避免多个线程同时操作
  • 简单: 不用并发锁
  • 性能: 避免了频繁的线程切换开销

Q: Event-driven

Q: Non-blocking I/O Model

如何做到异步/非阻塞 I/O的呢?

其实 Node 在底层访问 I/O 还是多线程的,有兴趣的朋友可以翻看 Node 的 fs 模块的源码,里面会用到 libuv 来处理 I/O,所以在我们看来 Node 的代码就是非阻塞和异步形式的。

Q: Node 单线程和多核

如何更好的利用多个 CPU/内核,答案就是启动多进程。有两种方案:

  • Nginx
  • Culster/Webworker

这两种方案其实都是如何做反向代理和负载均衡。只是分发的工作谁来做 Nginx 天生是做这件事的,非常适合,但成本会比较高,毕竟每次都要配置。

Culster 成本就低不少,通过 PM2,只要启动时加一个参数,就可以指定 worker 的数量。而且支持自动创建新的 worker。

Q: Cluster 是什么,如何做到的

Taobao 有一篇好文,《当我们谈论 cluster 时我们在谈论什么 》,详细讲解了 cluster 的原理。

Q: CPU/内核 和 Node 进程最佳配置

一般来说,有多少内核就分配多少个 worker。

Q: Node 的多线程

I/O 的多线程就是通过 libuv 来实现的。

Q: Docker 怎么利用多核?

Docker 不关心这些,给 Container 分配多少,就用多少,和在 host 中跑没有区别。

Q: Node 的适用场景

其实主要是 EventIO 的适用场景,大量 IO,网络请求的操作。

特别适合 API。

Q: 注意事项

  • 一定不要阻塞线程
  • 把运算型的方法,通过空间换时间。

Node.js软肋之CPU密集型任务
http://www.infoq.com/cn/articles/nodejs-weakness-cpu-intensive-tasks

Node.js的线程和进程
https://github.com/DoubleSpout/threadAndPackage/blob/master/chapter.7.thread_and_process.md

http://taobaofed.org/blog/2015/10/29/deep-into-node-1/