9.nodejs的控制生产线上环境,触发子进程

1.进程与线程的关系

 

  1. 进程是正在运⾏的程序的实例,我们启动⼀个服务,运⾏⼀个实例,就是开⼀个服务进程。进程是线程的容器。进程包括⽂本区域(text region)、数据区域(data region)和堆栈(stackregion)。
  2. 线程是操作系统能够进⾏运算调度的最⼩单位。它被包含在进程之中,是进程中的实际运作单位。⼀个进程可以由⼀个或者多个线程组成,每条线程并⾏执⾏不同的任务
  3. 进程包含线程

2.process和cross-env进程

1.命令

  1. process.env 返回包含⽤户环境的对象,可设置环境变量,例如Process.env.NODE_ENV
  2. process.pid 返回进程的pid
  3. process.platform 返回当前进程的操作系统平台
  4. process.title 获取或指定进程名称
  5. process.on(‘uncaughtException’,cb) 捕获异常信息
  6. process.on(‘exit’,cb) 监听进程退出
  7. process.cwd() 返回当前进程的⼯作⽬录
  8. process.uptime() 返回当前进程运⾏时间秒⻓

2.其他环境:

  1. windows上设置环境变量⽤set:set NODE_ENV=development && node index.js
  2. mac上设置环境变量⽤export: export NODE_ENV=development && node index.js
  3. 两个平台都可以用:安装cross-env, npm i cross-env --save-dev
  4. cross-env NODE_ENV=development node index.jschild_process.exec() 启动⼀个⼦进程执⾏命令,与spawn不同地⽅的是有⼀个回调函数获知

3.

1.package.json
 "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "cross-env NODE_ENV=development node index.js",
    "pro": "cross-env NODE_ENV=production node index.js"
  },

2.index.js
    console.log(process.env.NODE_ENV)
3. 启动命令:npm run dev


其他命令:
const http = require('http')
// const server = http.createServer()
// server.listen(3000,()=>{
//     console.log("服务器启动了,看看是什么进程吧")
// })
console.log(process.env.NODE_ENV)
console.log(process.pid)
console.log(process.title)
console.log(process.cwd())

//为了多花费时间
let sum;
for(let i = 0;i<1000;i++){
  sum += i
}
console.log(process.uptime())


process.on('exit', (code) => {
  console.log(`退出码: ${code}`);
});

process.on('uncaughtException',(err)=>{
    console.log('捕获异常 '+ err)
  })
  //自己捕获异常了,a没有定义会出现异常
  try {
    console.log(a)
  }catch(e){
    console.log("catch异常 " + e)
  }
  //用上面的异常:uncaughtException
  console.log(b)
  

结果截图:

               

child_process创建⼦进程及常⽤操作

创建⼦进程的4个⽅式

  1. child_process.exec() :启动⼀个⼦进程执⾏命令,与spawn不同地⽅的是有⼀个回调函数获知 
  2. child_process.spawn() 启动⼀个⼦进程执⾏命令⼦进程状况
  3. child_process.execFile() 启动⼀个⼦进程来执⾏可执⾏⽂件
  4. child_process.fork() 衍⽣⼀个新的 Node.js 进程,并调⽤⼀个指定的模块

测试代码:index2.js

const http = require('http')
const {spawn,exec,execFile,fork} = require('child_process')

const server = http.createServer((req,res)=>{
  if(req.url== '/compute'){
    const work = spawn('node',['work.js'])
    work.stdout.on('data', (data) => {
      console.log(`stdout: ${data}`);
    });
    exec('node work1.js',(err,stdout,stderr)=>{
      if(err) throw err
      console.log(stdout)
    })
    execFile('node',['work2.js'],(err,stdout,stderr)=>{
      if(err) throw err
      console.log(stdout)
      console.log(stderr)
    })
    fork('work3.js')
  }else{
    res.end('ok')
  }
})

server.listen(3000,()=>{
  console.log('listen sucess')
})

工作进程:work.js

process.title = '计算0'

let sum = 0;
for(let i = 0;i<10000;i++){
  sum += i
}

console.log("计算0:"+ sum)

console.error('计算0:错误信息测试')

结果:网页访问这个路径:http://localhost:3000/compute,触发进程

        

cluster创建⼦进程

const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  console.log(`主进程 ${process.pid} 正在运行`);

  // 创建工作进程。小于cpu的核数
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', (worker, code, signal) => {
    console.log(`工作进程 ${worker.process.pid} 已退出`);
  });
} else {
  // 工作进程可以共享任何 TCP 连接。在本例子中,共享的是 HTTP 服务器。
  http.createServer((req, res) => {
    res.writeHead(200);
    res.end('你好世界\n');
  }).listen(8000);

  console.log(`工作进程 ${process.pid} 已启动`);
}

进程间的通信⽅式


⼦进程通过send⽅法讲结果发送给主进程,主进程通过message监听到信息后处理并退出
进程间通信原理

⽗进程baba.js⽂件

const http = require('http')
const { spawn, exec, execFile, fork } = require('child_process')

const server = http.createServer((req, res) => {
  if (req.url == '/compute') {
    const work = fork('erzi.js')
    work.send('发送给子进程的信息')
    work.on('message', data => {
      console.log('父进程接收子进程的消息:' + data)
    })
  } else {
    res.end('ok')
  }
})

server.listen(3000, () => {
  console.log('listen sucess')
})

⼦进程erzi.js

process.title = '计算'

let sum = 0;
for(let i = 0;i<1e10;i++){
  sum += i
}

console.log(sum)

console.error('出错')

process.on('message',(data)=>{
  console.log('接收父进程的消息:'+data)
})

process.send(sum)

结果页:

      

 

进程间通信原理:

  1. IPC的全称是Inter-Process Communication,即进程间通信。它的⽬的是为了让不同的进程能够互相访问资源并进⾏协调⼯作。
  2. ⽗进程在实际创建⼦进程之前,会创建IPC通道并监听它,然后才真正的创建出⼦进程。此过程中会通过环境变量(NODE_CHANNEL_FD)告诉⼦进程这个IPC通道的⽂件描述符。⼦进程在启动的过程中,根据⽂件描述符连接这个IPC通道,从⽽完成⽗⼦进程之间的连接。

 


版权声明:本文为m0_37657725原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。