【我可以你也可以的Node.js】第二十篇 - Node Cluster 让你的 Thread 不再孤军奋战

我们都知道 Node 是一个 single thread 并且非同步的语言,
那...假使面临排山倒海的使用者请求时你能想像那一个 thread 孤军奋战的感受吗?

没有 ! 你只想到你自己。(好久以前的梗)

所以后来官方提出了这个模组,好让你可以开启更多的 process 去减轻那个可怜 Thread 的负担~
避免以下经典动图的发生。

这让我想到我上一支手机 Sony Z5P 拥有当年的旗舰 CPU ,在游戏效能上根本烂到炸,标榜八核心但是实际上只有 4 颗小核心在跑 ,只有在跑分的时候另外四颗大核心才会抛头露面刷存在感... (后来以 Root 自行改设定才解决)


此篇学习目标 ◑ω◐ :

Cluster 他怎么运作的实战在 Hello World使用 pm2 让管理 cluster 更容易

Cluster 他怎么运作的?

他主要是使用 child_process.fork() 产生新的 proccess 藉此与父进程沟通。
而 Cluster 由两种分配方式决定如何分配进来的请求。
而这两种都是经由 master process 倾听一个 port 然后分配到不同的 process
如图所示

第一种配发方式

The first one (and the default one on all platforms except Windows), is the round-robin approach, where the master process listens on a port, accepts new connections and distributes them across the workers in a round-robin fashion, with some built-in smarts to avoid overloading a worker process.

是经由 round-robin approach 来决定 ,简单来说就有点像是老师分派值日生擦黑板,前提是一天只有一件事就是擦黑板且一天只需要擦一次就可以换下一个人。
所以就是当一个请求进来的时候进到 master process 然后由他去轮流指派 一个 process 的概念。(有错或是举例错误请纠正我)

Note:
除了 Windows 之外其余都是预设第一种配发方式。
就你最特别这样。

第二种配发方式

The second approach is where the master process creates the listen socket and sends it to interested workers. The workers then accept incoming connections directly.

简单来说一样是由 master process 监听接口,然后直接配发到有兴趣的 process ,就是谁有兴趣就配给谁。

在现实生活中感觉可以徵求意见,但是在这边其实我不知道这个机制要如何知道谁有兴趣谁没兴趣,如果有人知道的可以跟我分享一下实际案例,感恩。
如果你也不知道也没关係我看完也是一个...

官方还特地说明了第二种配发方式

The second approach should, in theory, give the best performance. In practice however, distribution tends to be very unbalanced due to operating system scheduler vagaries. Loads have been observed where over 70% of all connections ended up in just two processes, out of a total of eight.

理论上,第二种方式效能会是最好的,但是实际上会造成其实负载平衡很不平衡的状况,假使在高併发的情况下总共有八个 process 但却会有 70% 的连线都只会落在两个 proccess 在处理。
让我感觉到能者过劳死的悲痛。
俗话说的好...

你强,你来。


实战在 Hello World

我们用之前 第二篇 写的 Hello world 和官方给的範例来实测看看差别。
我这边使用 loadtest 这工具来简单测试一下。

single thread


实测结果: 平均 22 ms 的处理时间

cluster multi-core systems

官方 Hello world 範例

const cluster = require('cluster');const http = require('http');const numCPUs = require('os').cpus().length;if (cluster.isMaster) {  console.log(`Master ${process.pid} is running`);  // Fork workers.  for (let i = 0; i < numCPUs; i++) {    cluster.fork();  }  cluster.on('exit', (worker, code, signal) => {    console.log(`worker ${worker.process.pid} died`);  });} else {  // Workers can share any TCP connection  // In this case it is an HTTP server  http.createServer((req, res) => {    res.writeHead(200);    res.end('hello world\n');  }).listen(8000);  console.log(`Worker ${process.pid} started`);}

实测结果: 平均 26.9 ms 的处理时间

嗯...

跟我想像中的结果不一样啊啊啊啊啊! 目前我还在寻找这未知的谜题...
目前我的猜测是因为其实他一下就做完了,然后我开了 cluster 导致他要花时间去分配,造成处理时间更长。
另外看了 stack overflow 的这个讨论串
Node.js clustering is slower than single threaded mode
但是还是有点违背我的想像 ~~
如果你知道为什么拜託告诉我。


使用 pm2 让管理 cluster 更容易

我另外看了一下好像大多数人不会直接使用原生的 cluster 而是使用这个 pm2 因为设定简单,然后...好像弄的很不错(?)

用法很简单就是
pm2 start -i <数量> --name <tagName> <path>

然后我再次的挑战上面那个谜题

详细用法我这边就不再赘述有兴趣可以自行看官方文件唷~

实测结果: 平均 13.4 ms 的处理时间

这才是我要的结果xDDD
至于原因嘛...可能是还有更多设定方面和处理其实不太一样,导致效能受影响(?)

所以我觉得...嗯...我还是直接用 pm2 好了 (X

如果有兴趣研究的可以跟我说...我可以听你的研究成果 xD


结语

另外看到满多人提说其实很不建议使用这种方式来做 load balance ,原因是如上面所讲的这个机制是透过 master process 来倾听一个 port 再去分配 worker ,那其实透过 Nginx 来做 LB 然后还有各自的 port 效能来得更优异。

我发现之后开开心心的想说可以用在我前几週发的麦当劳报报自动领取的 server,殊不知我一看我 aws 的目前使用配置...

没错...就是 1 配个...毛? XDDD

感谢收看。


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章