`
haiyupeter
  • 浏览: 426185 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

NodeJS Cluster文档翻译

阅读更多
Cluster 集群
一个独立的Node对象运行在单个线程中。为了更好的利用多核心系统的,用户会尝试启动多个Node处理进程,提供更好的服务。(说明:单个线程总是运行在一个核心上面,cluster是为了更好的利用CPU,充分利用多核CPU的资源)
你可以使用cluster模块,非常容易的创建共享服务端口的多个网络处理应用程序。
(在多个进程中,需要考虑全局变量等的存储及访问)
var cluster = require('cluster');  
var http = require('http');  
var numCPUs = require('os').cpus().length;  
  
if (cluster.isMaster) {  
  // Fork workers.  
  for (var i = 0; i < numCPUs; i++) {  
    var worker = cluster.fork();  
    consolog.log('Worker ' + worker.process.pid + ' online');  
 }  
  
  cluster.on('exit', function(worker, code, signal) {  
    console.log('worker ' + worker.process.pid + ' died');  
  });  
} else {  
  // Workers can share any TCP connection  
  // In this case its a HTTP server  
  http.createServer(function(req, res) {  
    res.writeHead(200);  
    res.end("hello world\n");  
  }).listen(8000);  
} 

引用
% node server.js 
Worker 2438 online 
Worker 2437 online 

这个功能是近期推出的,在后续的版本中可能会继续更改。请尝试并进行反馈。
注意:在windows中,现在还不能在一个worker中启动一个命名管道

它如何工作
worker 进程的创建是通过child_process.fork方法启动的,所以它可以通过IPC和父进程进行双向传递信息。

当你在一个worker中调用server.listen(...)的时候,它将参数序列化,并传递到主进程(master process)中。如果主进程已经有满足workder需求的监听server,则传递handle到这个worker上。如果不存在满足需求的监听server,则主进程创建一个然后将handle传递给子进程。

在边界条件,这将导致三个令人惊讶的情况:
1.server.listen({fd:7}) 因为消息是传递到master中的,父进程应该监听“文件描述为7”,然后传递到worker进行处理,而不是将“文件描述为7”的引入传递到worker中
2.server.listen(handle) 监听明确的处理函数将导致worker使用提供的handle函数处理,而不是与父进程联系,如果worker已经含有了handle,它假设你已经知道你将要做什么。
3.server.listen(0) 通常俯冲下,这会使服务监听一个随机的的端口,但是在cluster中,每一个worker在linten(0)的时候每次将接收同样的随机端口的信息,本质上来说,这个端口在一开始的时候是随机的,并且在在可预见的未来。如果你想监听一个指定的端口,基于cluster worker ID生成一个

当多个进程都在 accept()ing 同样的资源的时候,操作系统的负载均衡非常高效。Node.js没有路由逻辑,个人程序逻辑中也没有,两个worker之前没有共享状态。所以,个人程序,必需被设计得不那么重,比如基于内存的session或者登录相关的数据(这些可以被设计成存储于独立的缓存中,如memcached或者是redis中)。

因为workers都是独力运行的,根据程序的需要,它们可以被独立删除或者重启,它并不影响其他的worker。

只要还存在workers存活,则server将继续接收连接。Node不自动维护workers的数目。为应用程序维护worker池是你的责任。(可以在这里写一下监控,保证服务的持续运行)

cluster.settings
Object 类型
  • exec: [String] 传递给worker的文件路径。(默认=__filename)
  • args: [Array] 传递给worker的数组参数。(默认=process.argv.slice(2))
  • silent: [Boolean] 是否将输出传递到父进程的标准io。(默认=false)

    由.setupMaster存储的settings存储在当前这个settings对象中。这个对象不建议被修改。

cluster.isMaster
Boolean类型
    如果进程是master则返回true。这是由process.env.NODE_UNIQUE_ID决定的。如果
    process.env.NODE_UNIQUE_ID是undefined,isMaster为true
cluster.isWorker
Boolean类型
如果当前进程是一个从master进程fork出来的,则标志位为true。如果process.env.NODE_UNIQUE_ID被设置为一个值,isWorker为true
Event: 'fork'
参数:worker [Worker object]
一个新的worker被cluster模块fork出来,触发一个'fork'事件。这可以被用于记录worker激活,并创建一个时间函数
var timeouts = [];
function errorMsg() {
  console.error(&quot;Something must be wrong with the connection ...&quot;);
}

cluster.on('fork', function(worker) {
  timeouts[worker.id] = setTimeout(errorMsg, 2000);
});
cluster.on('listening', function(worker, address) {
  clearTimeout(timeouts[worker.id]);
});
cluster.on('exit', function(worker, code, signal) {
  clearTimeout(timeouts[worker.id]);
  errorMsg();
});

Event: 'online'
参数:worker [Worker object]

forking一个新的worker之后,此worker应该响应在线的消息。当master接收到此在线消息后,它将触发此事件。'fork'和'online'事件的不同点在于,fork是在master创建新worker的时候触发,而online是在worker被执行的时候触发。

cluster.on('online', function(worker) {
  console.log(&quot;Yay, the worker responded after it was forked&quot;);
});

Event: 'listening'
参数:worker [Workder object], address [Object]

worker调用listen()时,'listening'事件被自动发送到服务server对象中。当server正在监听一个消息,并发送到master进程的时候触发'listening' 事件
cluster.on('listening', function(worker, address) {
  console.log("A worker is now connected to &quot; + address.address + ":"; + address.port);
});

Event: 'disconnect'
参数:worker [Workder object]
当然一个worker的IPC通道失去连接之后触发'disconnect'事件。当worker死掉后发生,经常是在调用.destroy()方法后。

当调用.disconnect(),有可能在disconnect和exit事件之前延迟。此事件经常被用于确认进程是否卡在清理或者长连接中。

cluster.on('disconnect', function(worker) {
  console.log('The worker #' + worker.id + ' has disconnected');
});

Event: 'exit'
参数:
worker [Worker object]
code [Number] 退出码,如果正常退出的话
signal [String] 导致进程退出的信号的名称

worker进程挂掉后cluster模块触发'exit'事件。可以通过调用fork()重新启动该worker
cluster.on('exit', function(worker, code, signal) {
  var exitCode = worker.process.exitCode;
  console.log('worker ' + worker.process.pid + ' died ('+exitCode+'). restarting...');
  cluster.fork();
});

Event: 'setup'
参数:worker [Worker object]
调用.setupMaster()触发此事件。如果.setupMaster()在fork()函数前没有执行,则此函数会调用没有参数的.setupMaster()。

cluster.setupMaster([setting])
参数:settings Object
  • exec: [String] 传递给worker的文件路径。(默认=__filename)
  • args: [Array] 传递给worker的数组参数。(默认=process.argv.slice(2))
  • silent: [Boolean] 是否将输出传递到父进程的标准io。(默认=false)

setupMaster 用于改变默认的'fork'行为。新的settings会立即生效,并且是永远的,不可修改的。

var cluster = require(&quot;cluster&quot;);
cluster.setupMaster({
  exec : &quot;worker.js&quot;,
  args : [&quot;--use&quot;, &quot;https&quot;],
  silent : true
});
cluster.fork();

cluster.fork([env])
  • env [Object] 加入到子进程环境的Key/Value对
  • return [Worker object]

启动一个新的worker进程。只能由主进程调用。(在调用之前判断cluster.isMaster)

cluster.disconnect([callback])
调用此方法的时候,所有的worker将提交一个优雅的结束。当所有的worker都失去全局的连接,并且全局的控件也关闭,没有事件等待,此时主进程(master process)将优雅的结束
结束的时候,这个方法接收一个可配置的callback参数。

cluster.worker
Object类型
对当前worker对象的引用。在主进程程不可用。
var cluster = require('cluster');
if (cluster.isMaster) {
  console.log('I am master');
  cluster.fork();
  cluster.fork();
} else if (cluster.isWorker) {
  console.log('I am worker #' + cluster.worker.id);
}


cluster.workers
Object类型

存储所有workds对象的hash,通过id作为key来标志。非常使得的循环所有的worker。只在主进程中可用。

// Go through all workers
function eachWorker(callback) {
  for (var id in cluster.workers) {
    callback(cluster.workers[id]);
  }
}
eachWorker(function(worker) {
  worker.send('big announcement to all workers');
});


可能你会通过一个交流频道来与worker的引用交流,使用worker的唯一ID可以很快找出worker

socket.on('data', function(id) {
  var worker = cluster.workers[id];
});


Class: Worker
包仿worker所有公共信息和方法的Worker对象。在主进程中可以通过cluster.workers获得。在worker中,可能通过cluster.worker获得

work.id
String类型

每一个Worker提供独立的id,存储在id属性中
当一个worker存活着的时候,这个key标识在cluster.workers中
worker.process
ChildProcess Object 类型

所有的workers都是通过child_process.fork()创建的,它的返回值被存储在process属性中

worker.suicide
Boolean类型

.destroy()后worker挂掉,或者在调用.disconnect()方法后,将设置此属性。否则它的值是undefined

worker.send(message, [sendHandle])
参数:message [Object]
sendHandle [Handle object]

这个方法等同于child_process.fork()。在主进程中,可以使用此方法发送一个消息到指定的worker中。在worker中,一样可以发送一个消息到主进种中,完成同样的功能。

if (cluster.isMaster) {
  var worker = cluster.fork();
  worker.send('hi there');

} else if (cluster.isWorker) {
  process.on('message', function(msg) {
    process.send(msg);
  });
}

worker.destroy()
这个方法杀掉worker,然后通知主进行不再启动一个新的worker。Boolean值suicide让你区分出是正常,或者意外退出。

cluster.on('exit', function(worker, code, signal) {
  if (worker.suicide === true) {
    console.log('Oh, it was just suicide\' – no need to worry').
  }
});

// destroy worker
worker.destroy();

worker.disconnect()
当调用此方法的时候,worker不再接收新的连接请求,但它被其他监听着的worker控制。已存在的连接将会允许正常情的退出。已没有连接存在的情况下,worker的IPC频道将关闭,允许worker优雅的结束。IPC频道关闭时触发disconnect事件,跟着是exit事件,在worker完全退出的时候。


也许有长的存活的连接存在,最好是实现一个timeout函数。示例里,呼叫worker断开连接,并在2秒后结束server。一个可供选择的去执行worker.destroy()在两提前后,但它不能使用worker去正常的执行一些必需的清理工作。

if (cluster.isMaster) {
  var worker = cluster.fork();
  var timeout;

  worker.on('listening', function(address) {
    worker.disconnect();
    timeout = setTimeout(function() {
      worker.send('force kill');
    }, 2000);
  });

  worker.on('disconnect', function() {
    clearTimeout(timeout);
  });

} else if (cluster.isWorker) {
  var net = require('net');
  var server = net.createServer(function(socket) {
    // connection never end
  });

  server.listen(8000);

  server.on('close', function() {
    // cleanup
  });

  process.on('message', function(msg) {
    if (msg === 'force kill') {
      server.destroy();
    }
  });
}

Event: 'message'
参数:message [Object]

这个事件与child_process.fork()提供的相同。在主进程中,可以使用这个事件,在worker中,可以使用process.on('message')

示例,主进程使用消息系统发送多个requrest:

var cluster = require('cluster');  
var http = require('http');  
  
if (cluster.isMaster) {  
  
  // Keep track of http requests  
  var numReqs = 0;  
  setInterval(function() {  
    console.log("numReqs =", numReqs);  
  }, 1000);  
  
  // Count requestes  
  function messageHandler(msg) {  
    if (msg.cmd && msg.cmd == 'notifyRequest') {  
      numReqs += 1;  
    }  
  }  
  
  // Start workers and listen for messages containing notifyRequest  
  var numCPUs = require('os').cpus().length;  
  for (var i = 0; i < numCPUs; i++) {  
    cluster.fork();  
  }  
  
  Object.keys(cluster.workers).forEach(function(id) {  
    cluster.workers[id].on('message', messageHandler);  
  });  
  
} else {  
  
  // Worker processes have a http server.  
  http.Server(function(req, res) {  
    res.writeHead(200);  
    res.end("hello world\n");  
  
    // notify master about the request  
    process.send({ cmd: 'notifyRequest' });  
  }).listen(8000);  
}  

Event: 'online'
与cluster.on('online')相同的事件,指定的worker发生状态改变时触发。

cluster.fork().on('online', function() {
  // Worker is online
};

Event: 'listening'
参数:address Object

与cluster.on('listening')相同的事件,指定的worker发生状态改变时触发。

cluster.fork().on('listening', function(address) {
  // Worker is listening
};


Event: 'disconnect'
与cluster.on('disconnect')相同的事件,指定的worker发生状态改变时触发。

cluster.fork().on('disconnect', function(address) {
  // Worker is listening
};

Event: 'exit'
  • code [Number] 退出码,如果正常退出的话
  • signal [String] 导致进程退出的信号的名称

在个另的worker对象中触发,特别是子进程结束的时候。可以参考:child_process event: 'exit'

var worker = cluster.fork();
worker.on('exit', function(code, signal) {
  if( signal ) {
    console.log(&quot;worker was killed by signal: &quot;+signal);
  } else if( code !== 0 ) {
    console.log(&quot;worker exited with error code: &quot;+code);
  } else {
    console.log(&quot;worker success!&quot;);
  }
};
分享到:
评论

相关推荐

    NodeJS中文文档精编.pdf 全文免费

    NodeJS中文文档精编.pdf 全文免费 NodeJS是 JavaScript 运行时环境,可以让 JavaScript 代码在服务器端执行。NodeJS 实际上是对 ES 标准的一个实现,同时 Node 也是一个 JS 引擎。 Node 只对 ES 标准进行了实现,...

    NodeJS API文档

    NodeJS API文档。Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。 Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型。Node 是一个让 JavaScript 运行在服务端的开发平台,它让 JavaScript 成为与PHP、...

    (完整word版)Nodejs学习文档整理.pdf

    【Node.js 知识点详解】 Node.js 是一种基于 Chrome V8 引擎的 JavaScript 运行环境,设计用于构建可扩展的网络应用。它的主要特点是异步非阻塞I/O和事件驱动,使得它在处理高并发请求时表现优异。...

    nodejs官方文档

    Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。 Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效。 Node.js 的包管理器 npm,是...中英文官方文档,部分不常用模块,未实现英文翻译。

    nodeJS破解谷歌翻译接口

    nodejs通过计算tkk和tk实现破解谷歌翻译api(代码中arguments数组是命令行传入参数)。var request = require('request') 括号中写自己的request模块路径。

    NodeJS整理手册文档

    本"NodeJS整理手册文档"旨在为对NodeJS感兴趣的朋友们提供一个全面、详尽的学习资源,涵盖了NodeJS的基础知识、核心特性以及实践案例。 一、NodeJS基础 NodeJS的基础知识包括安装与环境配置、模块系统、事件驱动...

    NodeJs入门文档介绍

    NodeJs入门学习文档,对于新手刚接触NodeJs有一定的帮助

    nodejs自动批量翻译中文到其它语言.pdf

    nodejs自动批量翻译中文到其它语言.pdf

    Nodejs中解决cluster模块的多进程如何共享数据问题

    本篇文章主要介绍了Nodejs中解决cluster模块的多进程如何共享数据问题,有需要的可以了解一下。

    nodeJS文档

    ### NodeJS基础知识与应用 #### 一、NodeJS概述 **NodeJS** 是一个开源的JavaScript运行环境,它能够在服务器端执行JavaScript代码。这得益于它的轻量级和高效的特性,NodeJS非常适合用来构建高并发、低延迟的应用...

    NodeJs技术经典文档

    资源名称:NodeJs技术经典文档资源目录:【】Node.js开发指南_中文正版【】nodejs开发指南pdf及源码及win安装程序【】nodejs手册中文【】NodeJs教程【】umav4simple【】七天学会NodeJS【】七天学会NodeJS【】深入浅...

    nodejs API 中文文档

    nodejs API 中文文档,这份文档的翻译工作始于 2016年 4月初,由于翻译量较大,加之 Node.js 官方版本更新较快,因而目前尚无法跟上官网的(版本)更新节奏。但整体算是比较新的了。适合新手入门或者当作 使用手册 ...

    Nodejs文档说明

    Nodejs文档说明

    NodeJS_v12.14.0_doc_cn.chm

    NodeJS 中文文档 (Node.js v12.14.0) 源网址:http://nodejs.cn/api/

    NodeJS配置文档

    NodeJS 配置文档 NodeJS 是一个基于 JavaScript runtime 的平台,能够让开发者使用 JavaScript 语言来开发服务器端应用程序。NodeJS 配置是一个非常重要的步骤,对于开发者的开发效率和开发体验有着非常大的影响。...

    docker-nginx-nodejs-cluster-test:docker,nginx,nodejs集群

    docker-nginx-nodejs-集群测试 一个具有nginx + 4个节点进程(2个单进程和2个集群进程)的Docker容器。 因此,在4个TCP端口上,后端总数为6。 Docker容器 Nginx(80) backend1(8000):1个单进程 backend2(8001...

    nodejs不错的文档

    Node.js是一个基于Chrome JavaScript运行时建立的平台, 用于方便地搭建响应速度快、易于扩展的网络应用。Node.js 使用事件驱动, 非阻塞I/O 模型而得以轻量和高效,非常适合在分布式设备上运行的数据密集型的实时...

    nodejs中文帮助文档

    资源名称:nodejs中文帮助文档内容简介:nodejs中文帮助文档,想学习nodejs的朋友可以参考下nodeJS 中文API node.js 中文文档 nodejs中文帮助文档.pdf Node 是一个服务器端 Javascript 解释器,它将改变服务器...

    nodejs-redis-cluster:redis3.0的nodejs扩展,支持集群

    nodejs-redis-cluster redis3.0 的 nodejs 扩展,支持基于 nodejs npm redis url 的集群: : 更改日志 当我们向 redis 集群的一个节点发送命令时,我们可能会收到类似“ERR: MOVED 111 127.0.0.1:6379”的返回错误...

Global site tag (gtag.js) - Google Analytics