【原创】学习NodeJs多进程(二)

前文介绍了NodeJs子进程创建和进程间通信,但让开发者处理多进程的管理是比较麻烦的事情,通常开发者只希望关注业务代码的实现。本文介绍了多进程管理相关的cluster模块、工具、负载均衡等。

相关文章

目录

  • cluster模块
  • 负载均衡
  • 进程管理工具
  • cluster不适用的场景

cluster模块

cluster模块是对多进程创建、消息传递、共享端口的封装。以下为官方的使用示例,根据cpu数量创建工作进程,并监听同一个端口8000

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`)
}

在前文介绍的多进程监听同一端口中,主进程创建服务器,并将服务器句柄传递给子进程,子进程再根据句柄还原服务器实例,请求到来时由操作系统调度机制决定交给哪个进程处理。以上由于保留了多个服务器实例直接监听同一端口,会造成资源浪费,并且请求转发不可控。

cluster模块中默认以轮询的方式处理请求,父进程创建内部服务器并监听端口,所有请求先经过该服务器,再转发给子进程处理。由于父进程负责转发,因此父进程可以指定负载均衡策略,另外父进程不直接处理业务逻辑,可以保证父进程的稳定性。

cluster模块提供丰富的api用来管理子进程,以下示例为子进程挂掉后自动创建新的进程:

const cluster = require('cluster')
const http = require('http')

cluster.schedulingPolicy = cluster.SCHED_RR

function listen (worker) {
  worker.on('message', (msg) => {
    console.log(`worker ${worker.process.pid}:`, msg)
  })
}

if (cluster.isMaster) {
  console.log(`master process ${process.pid} is running`)
  for (let i = 0; i < 4; i++) {
    cluster.fork()
  }

  for (const id in cluster.workers) {
    listen(cluster.workers[id])
  }

  cluster.on('exit', (worker, code, signal) => {
    console.log(`worker process ${worker.process.pid} is exited`)
    listen(cluster.fork())
  })
} else {
  http.createServer((req, res) => {
    res.writeHead(200)
    res.end('hello world')

    process.send('handled request')
  }).listen(8000)

  console.log(`worker process ${process.pid} is running`)
}

访问localhost:8000,再手动kill掉某一进程,执行结果如下:

master process 8616 is running
worker process 16332 is running
worker process 4624 is running
worker process 8084 is running
worker process 16352 is running
worker 16332: handled request
worker 15172: handled request
worker process 15172 is exited
worker process 2260 is running
worker 16332: handled request
worker 8084: handled request
worker 2260: handled request

可以看到,只要有子进程退出,会自动创建子进程。只要有工作进程存在,就能继续处理请求。

负载均衡

cluster模块提供两种负载均衡策略

  • cluster.SCHED_RR

    轮询分发(除Windows外所有平台的默认方法),由主进程负责监听端口,接收新连接后再将连接循环分发给工作进程。在分发中使用了一些内置技巧防止工作进程任务过载。

  • cluster.SCHED_NONE

    使用操作系统调度机制,主进程创建监听socket后发送给感兴趣的工作进程,由工作进程负责直接接收连接。由于操作系统调度机制的难以捉摸,可能会使分发变得不稳定。在cluster模块出现之前,多进程共同监听同一端口的调度方式都是用该机制。

使用cluster.schedulingPolicy可指定以上两种策略,也可以使用NODE_CLUSTER_SCHED_POLICY环境变量,对应以上的两种策略的取值为rrnone

cluster不支持自定义负载均衡策略,可参考cluster的源码,实现自己的负载均衡策略。根据cluster模块源码学习来理解多进程的负载均衡算法,文章地址:http://www.cnblogs.com/accordion/p/7207740.html

进程管理工具

在生产环境中,除了使用多进程充分利用cpu性能外,还需考虑进程异常退出的自动重启,多个工作进程共享资源,以及多进程之间的调度。cluster模块只是对多进程创建、消息传递、共享端口的简单封装,下面介绍一些目前成熟的进程管理工具。

  • Pandora.js

    Pandora.js 是一个 Node.js 应用监控管理器,它集成了多种类型的能力诸如:监控、链路追踪、调试、进程管理等等。它提供多进程模型、多进程管理以及自定义进程扩展能力。开发者只需关注具体的业务逻辑实现即可。

  • pm2

    是一个进程管理工具,维护一个进程列表,可以用它来管理你的node进程,负责所有正在运行的进程,并查看node进程的状态,也支持性能监控,自动重启,负载均衡等功能,而且使用非常简单。

  • Egg

    Egg虽然是企业级的NodeJs开发框架,但集成了egg-cluster模块实现多进程的管理,自带服务管理的cli,不需要其他的进程管理工具来管理进程了。另外提供Agent进程来处理不适合用多进程处理的场景,如定时任务、websocket等。

cluster不适用的场景

这里的cluster不止指node的cluster模块,也包括通过第三方库实现的多进程管理工具。cluster虽然能充分利用服务器cpu资源,提高服务的健壮性,但并不是所有场景都适合用多进程来处理,比如:

  • 定时任务

    定时任务应该只被一个进程调用,如果以多进程的模式启动,会造成定时任务的重复执行。通常应该单独创建一个进程来处理定时任务,并且该进程应该保证稳定性,在发生异常错误时记录错误而不自动退出。

  • socket.io

    socket.io是在websocket上封装的,在客户端未提供websocket功能的基础上使用xhr polling、jsonp或forever iframe的方式进行兼容,同时在建立ws连接前往往通过几次http轮询确保websocket服务可用。在建立连接前的几次http轮询如果被转发到了不同的进程,会导致ws服务连接失败。socket.io官方提供了nginx反向代理 + iphash的方式来保证同一个客户端的多次请求定位到后端同一个服务进程。关于socket.io的集群策略,可参考:https://segmentfault.com/a/1190000009622158

    • session和内存缓存

    使用cluster模块通常是无状态应用,因为在进程中缓存的数据无法直接与其他进程共享,理论上可以在主进程上维护统一的缓存数据,然后子进程从父进程中获取,但逻辑上比较复杂,并且增加了父进程的负担。因此常常使用第三方工具来共享应用状态,如redis

总结

本文介绍了cluster模块和常用的多进程管理工具,希望对想要使用多进程来提升服务的性能和健壮性的小伙伴有一些帮助。

本文参考资源如下

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容

  • 在三年以前,如果要给自己贴个标签的话,我是怎么都不会给自己贴上“学习”的,这是因为,从小学、初中、高中的学习经历都...
    巨晓松阅读 804评论 1 3
  • 为什么感觉看了那么多的书,工作了那么多年,写了那么多代码,自己在一开始的进步明显后,到现在基本停止进步?我想是因为...
    聪安阅读 516评论 0 0
  • 一面 一面的电话是8月13日打来的,约了14号下午7点,结果7点半才打来。主要内容: 自我介绍 看你项目用了Vue...
    C脖子阅读 3,900评论 8 50
  • KVC: KVC也就是key-value-coding,即键值编码,通常是用来给某一个对象的属性进行赋值,例如有人...
    春暖花已开阅读 491评论 0 3
  • 当今社会,教育一直是家庭和社会中的大问题。学校被誉为教书育人之地,但目前传授知识为主,育人为辅。父母对子女的教育,...
    云在风中谁在听阅读 192评论 0 0