如何玩转足球 盘子 pdf子进程child

Node——玩转进程
Node基于V8引擎构建,与类似,我们的JS将会运行在单个进程的单个线程上,他带来的好处是:程序状态是单一的,没有锁和线程同步问题,没有上下文切换CPU使用率高。但是还是有别的问题:CPU的多核无法利用,单线程上有异常并没有被捕获的情况下,服务器就无法继续提供服务了。
多进程架构
Node提供了child_process模块,这个模块可以做到打开新的进程来执行任务。最理想的状态应该是每个进程各自利用一个CPU:
var fork = require('child_process').
var cpus = require('os').cpus();
for (var i = 0; i & cpus. i++) {
fork('./worker.js');
worker.js中就可以执行:
var http = require('http');
var port = Math.round((1 + Math.random()) * 1000);
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end(port+&&);
}).listen(port, '127.0.0.1');
console.log(&PORT:&+port);
这个就是主从模式,主进程用来调度各个工作进程,不负责处理具体的业务逻辑,这个进程应该是很稳定的。工作进程负责具体的业务处理。
我们上面用到的fork方法创建的进程是独立的,在这个进程中有一个全新的V8实例,它需要额外的启动时间和内存。fork的代价是昂贵的,但是如果是为了充分调动CPU而不是处理单个的请求,就是值得的。
创建子进程
child_process模块提供了4个方法来创建子进程。spawn()、exec()、execFile()。
spawn:启动一个子进程来执行命令 exec:启动一个子进程来执行命令 ,有一个回调函数来获得子进程的状态 execFile:启动一个进程来执行可执行文件 fork:这个是专门来执行JS的
var cp = require('child_process');
cp.spawn('node', ['./worker.js']);
cp.exec('node ./worker.js', function (err, stdout, stderr) {
console.log(&exec:&+stdout);
console.log(err);
//使用execFile直接执行JS文件要在文件前加上#!/usr/bin/env node
cp.execFile('./worker.js', function (err, stdout, stderr) {
console.log(&execFile:&+stdout);
cp.fork('./worker.js');
进程间通信
这个就像是WebWorker,使用事件来监听子进程或父进程发来的消息,使用send方法给对方发送消息:
cp.fork('./worker.js');
var n = cp.fork('./sub.js');
n.on('message', function (m) {
console.log('PARENT got message:', m);
n.send({hello: 'world'});
process.on('message', function (m) {
console.log('CHILD got message:', m);
process.send({foo: 'bar'});
我们先来看看使用句柄可以达到什么样的效果,假如我想有多个进程同时监听8080端口,同时处理这个端口的请求,那在每一个进程里监听8080是不行的,会报错。但是我们可以通过句柄将服务器对象传递到子进程里,这样每个子进程都可以处理这个端口的请求:
var cp = require('child_process');
var child1 = cp.fork('./jubing-child.js');
var child2 = cp.fork('./jubing-child.js');
// Open up the server object and send the handle
var server = require('net').createServer();
server.listen(1337, function () {
child1.send('server', server);
child2.send('server', server);
server.close();
var http = require('http');
var server = http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('handled by child, pid is ' + process.pid + '\n');
process.on('message', function (m, tcp) {
if (m === 'server') {
tcp.on('connection', function (socket) {
server.emit('connection', socket);
句柄的发送与还原
send并没有直接把服务器对象发送给子进程,他只是将对象类型,文件描述符等信息拼成字符串传给了子进程。send方法只能发送如下几种句柄类型:
net.Socket:TCP套接字 net.Server:TCP服务器 net.Native:C++层面的TCP套接字 dgram.Socket:UDP套接字 dgram.Native:C++层面的UDP套接字
send将这几种句柄发送到子进程时,子进程会使用对象类型和文件描述符来还原出一个对应的对象,这个文件描述符会被新的对象和父进程中的对象同时监听,这就达到了同时监听的效果。但是文件描述符同一时间只能被某一个进程所用,所以只有一个线程可以抢到连接。
集群稳定之路
这里充分利用CPU资源已经做到了,但是还有一些细节要考虑:
性能问题 多个工作进程的存活状态管理 工作进程的平滑重启 配置或静态数据的动态重新载入 单个工作进程的稳定性
error:当子进程无法被复制创建,无法被杀死,无法发送消息时触发该事件 exit:子进程退出时,正常退出时,这个事件第一个参数是退出码,通过kill()杀死时第二个参数为杀死进程时的信号 close:子进程的标准输入输出流终止时触发 disconnect:在父进程中调用disconnect()方法时触发,将关闭监听IPC通道
父进程除了可以使用send()外,还可以使用kill方法给子进程发送消息,kill方法并不能真正的杀死进程,它只是给子进程发送一个SIGTERM信号:
child.kill([signal]);
// 指定进程
process.kill(pid, [signal]);
每个进程都可以监听这些事件,并作出应做的反应:
process.on('SIGTERM', function() {
console.log('Got a SIGTERM, exiting...');
process.exit(1);
有了这些事件,我们就可以创建一些需要的进程管理的机制了。比如有个进程挂了,我们自动重启他。
// master.js
var fork = require('child_process').
var cpus = require('os').cpus();
var server = require('net').createServer();
server.listen(1337);
var workers = {};
var createWorker = function () {
var worker = fork(__dirname + '/auto_reboot-worker.js');
//子进程退出时重新启动新的进程
worker.on('exit', function () {
console.log('Worker ' + worker.pid + ' exited.');
delete workers[worker.pid];
createWorker();
// 句柄转发
worker.send('server', server);
workers[worker.pid] =
console.log('Create worker. pid: ' + worker.pid);
for (var i = 0; i & cpus. i++) {
createWorker();
// 进程自出时有工作进程出
process.on('exit', function () {
for (var pid in workers) {
workers[pid].kill();
这时,如果子进程出错退出或主动杀死一个子进程都会再创建一个新的子进程。
在子进程中如果出错也需要做一些处理:
process.on('uncaughtException', function () {
worker.close(function () {
process.exit(1);
停止接收新的连接,等待现有连接关闭后退出,告诉主进程以便主进程调度。
这里有个极端情况,如果所有的子进程都出错了,都停止接收新的连接且在等待当前连接关闭,那就没有进程服务用户了。我们应该把通知主进程的过程提前:
process.on('uncaughtException', function () {
process.send({act: 'suicide'});
worker.close(function () {
process.exit(1);
在主进程中,创建新线程的时机也提前:
worker.on('message', function (message) {
if (message.act === 'suicide') {
console.log(worker.pid+'suicide')
createWorker();
worker.on('exit', function () {
console.log('Worker ' + worker.pid + ' exited.');
delete workers[worker.pid];
如果我们处理的是长连接,等待长连接断开的时间会比较久,设置一个超时是合理的:
process.on('uncaughtException', function () {
process.send({act: 'suicide'});
worker.close(function () {
process.exit(1);
setTimeout(function () {
process.exit(1);
通过自杀信号告知主进程可以使得新连接总是有进程服务,但是还是存在一种极端情况,就是程序是有问题的,这就会导致刚一启动就发生错误,或一有连接就发生错误,这样会导致短时间内大量重启进程,这是我们不希望看到的。
我们在每次创建新的进程前先检查一下,是否创建的太过频繁:
var limit = 20;
// 时间单位
var during = 60000;
var restart = [];
var isTooFrequently = function () {
// 记录重启时间
var time = Date.now();
var length = restart.push(time);
if (length & limit) {
// 取出10录
restart = restart.slice(limit * -1);
// 重启前10重启间的时间间
return restart.length &= limit && restart[restart.length - 1] - restart[0] &
这个是一个比较复杂的问题,自己实现比价复杂,Node在专门处理多进程的模块cluster中设置了策略可以直接启用:
cluster.schedulingPolicy = cluster.SCHED_RR
这个策略叫做Round-Robin,轮叫调度,这个的工作方式是由主进程接受连接,将其依次分发给工作进程,分发的策略是在N个工作进程中,每次选择第i = (i + 1) mod n个进程发送连接。
多个线程可能需要共享一些数据,比如配置文件等。将这些要共享的东西放在第三方,比如缓存里,有一个单独的进程负责轮询,看这些要共享的东西是否发生了变化,如果有就通知所有工作进程到缓存里去取。
Cluster模块
这个模块就是child_process模块和net模块的组合使用,具体的就不介绍了,可以去看官方文档。新手,求问父进程与子进程执行顺序的问题_linux吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:168,690贴子:
新手,求问父进程与子进程执行顺序的问题收藏
#include &sys/wait.h&#include &sys/types.h&#include &stdio.h&#include &unistd.h&#include &stdlib.h&int value = 5;int main(){ pid_pid = fork();if (pid == 0) { printf(&child process, value1 : %d\n&, value);value += 15;printf(&child process, value2 : %d\n&, value);}else if (pid & 0) { printf(&parent process, value3 : %d\n&, value);wait(NULL);printf(&parent process, value4 : %d\n&, value);exit(0); }}代码是这样的 老师给的答案是child process, value1 :5child process, value2 :20parent process, value3:5parent process, value4 :5或者parent process, value3:5child process, value1 :5child process, value2 :20parent process, value4 :5我想请问一下 ,为什么答案不可能是child process, value1 :5parent process, value3:5child process, value2 :20parent process, value4 :5这样呢?我在网上查到父进程和子进程是遵循进程调度的,按理说应该有子进程执行到一半被父进程抢占了CPU这种情况才对啊。。。
尚观linux培训,[120天入门到精通年薪10W入职],签订《就业协议》,法律有效!,企业项目实战授课.毕业直接增长2年工作经验,2017linux培训&十佳机构&,业内好口碑
别沉啊。。。。
你可以通过wait来等待直到子进程退出
登录百度帐号推荐应用
为兴趣而生,贴吧更懂你。或Node.js中child_process实现多进程
投稿:hebedich
字体:[ ] 类型:转载 时间:
这篇文章主要介绍了Node.js中child_process实现多进程,需要的朋友可以参考下
var http = require('http');
function fib (n) {
&&& if (n & 2) {
&&&&&&& return 1;
&&& } else {
&&&&&&& return fib(n - 2) + fib(n - 1);
var server = http.createServer(function (req, res) {
&&& var num = parseInt(req.url.substring(1), 10);
&&& res.writeHead(200);
&&& res.end(fib(num) + "\n");
server.listen(8000);
以上示例提供了一个斐波纳契数列的计算服务,由于此计算相当耗时,且是单线程,当同时有多个请求时只能处理一个,通过child_process.fork()就可以解决此问题
这里引用一下官网上的一个示例,通过这个例子可以很好的理解fork()的功能
var cp = require('child_process');
var n = cp.fork(__dirname + '/sub.js');
n.on('message', function(m) {
& console.log('PARENT got message:', m);
n.send({ hello: 'world' });
执行上述代码片段的运行结果:
PARENT got message: { foo: 'bar' }
CHILD got message: { hello: 'world' }
sub.js的内容如下:
process.on('message', function(m) {
& console.log('CHILD got message:', m);
process.send({ foo: 'bar' });
在子进程中process对象有send()方法,同时它在每一次接收到消息时都会发布消息对象
有点晕的是:child.send()发送的消息,是由process.on()方法接收的,process.send()方法发送的消息是由child.on()方法接收的
参照这个例子我们就可以把第一个提供斐波纳契数据的服务进行改进,使每一个请求都有单独的一个新的进程来处理
var http = require('http');
var cp = require('child_process');
var server = http.createServer(function(req, res) {
&&& var child = cp.fork(__dirname + '/fibonacci-calc.js');//每个请求都单独生成一个新的子进程
&&& child.on('message', function(m) {
&&&&&&& res.end(m.result + '\n');
&&& var input = parseInt(req.url.substring(1));
&&& child.send({input : input});
server.listen(8000);
fibonacci-calc.js
function fib(n) {
&&& if (n & 2) {
&&&&&&& return 1;
&&& } else {
&&&&&&& return fib(n - 2) + fib(n - 1);
process.on('message', function(m) {
&&& process.send({result: fib(m.input)});
启动服务后,访问就可以计算出9的斐波纳契数列的值
以上就是本文的全部内容了,希望大家能够喜欢。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具Please note that GitHub no longer supports old versions of Internet Explorer.
We recommend upgrading to the latest , , or .
If you are using IE 11, make sure you .
JavaScript
Nothing to show
Nothing to show
New pull request
Fetching latest commit…
Cannot retrieve the latest commit at this time.
child-exec
一个简单的node环境执行子进程的npm模块。
var exec = require("child-exec");
exec("node server");
You can't perform that action at this time.
You signed in with another tab or window.
to refresh your session.
You signed out in another tab or window.
to refresh your session.

我要回帖

更多关于 玩转足球 盘子 pdf 的文章

 

随机推荐