众所周知Node的单线程设计,在多核CPU的及其背景下,我们有什么方法充分的让我们的nodejs程序‘榨干’多核机器的性能呢?
我了解到的方式有三种:
- pm2 + nginx
 
- kubernetes
 
- nodejs cluster
 
pm2 + nginx
通过pm2启动多实例,然后交给nginx的upstream配置帮我们把用户的连接分发到各个实例上,从而实现负载均衡。
以下为一个pm2+nginx的demo
nodejs 程序
app.js
1 2 3 4 5
   | const http = require('http') const port = process.env.PORT || 8080 http.createServer((req, res) => {   res.end('hello world\n') }).listen(port)
  | 
 
pm2启动多实例配置
pm2_config.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
   | [{   "name": "app-1",   "script": "./app.js",   "env": {     "NODE_ENV": "production",     "PORT: "8080"   } }, {   "name": "app-2",   "script": "./app.js",   "env": {     "NODE_ENV": "production",     "PORT: "8081"   } }]
  | 
 
nginx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
   | upstream app.server {   server localhost:8080 weight=1;   server localhost:8081 weight=1; } server {     listen 0.0.0.0:80;     server_name youdomain.com;     access_log /var/log/nginx/project.log;     error_log /var/log/nginx/project_err.log;
      location / {         proxy_pass http://app.server;         proxy_set_header X-Real-IP $remote_addr;         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;         proxy_set_header Host $http_host;         proxy_set_header X-NginX-Proxy true;         proxy_http_version 1.1;         proxy_redirect off;     } }
  | 
 
虽然以上方法我们可以非常简单的实现一个负载均衡的方案,但是有几个弊端:
1.我们需要监听多个端口
2.分发策略完全由nginx控制,并且需要引入pm2管理启动程序(这个有可能不是问题)
Kubernetes 容器化负载均衡
待续…
nodejs cluster
那有没有更好的方法让我们通过nodejs本身就能实现负载均衡?根据cpu和数部署多个实例呢? 
其实从nodejs v0.8开始,Node新增了一个内置模块——“cluster”,其可通过一个父进程启动多个子进程并管理,从实现集群的功能。
最小 cluster demo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
   | const cluster = require('cluster') const http = require('http') const numCpus = require('os').cpus().length
  if (cluster.isMaster) {   console.log(`主进程 ${process.pid} 正在运行`)      for (let i = 0; i < numCpus; i++) {     cluster.fork()   } } else {   http.createServer((req, res) => {     res.end('hello world\n')   }).listen(8000)   console.log(`工作进程 ${process.pid} 已启动`) }
 
  | 
 
通过isMaster属性,判断是否Master进程,是则fork子进程,否则启动一个server。每个HTTP server都能监听到同一个端口