进程原则:
1.普通程序不能创建进程,只有系统程序才能创建进程
2.普通程序的进程是分裂出来的,只有主进程能分裂
3.分裂出来的两个进程执行的是同一套代码
4.父子进程之间可以共享句柄
创建一个简单的进程程序:
const cluster = require('cluster')
if(cluster.isMaster){//判断是否为主进程
cluster.fork()
}
console.log('一个进程')
执行后发现报错,这是因为违反了第二个进程原则,打印出来的"一个进程"是主进程也就是第一个进程打印的,而子进程也就是第二个进程在执行这份代码的时候,已经不能再创建子子进程,因此报错
所以要加一个判断:
const cluster = require('cluster')
if(cluster.isMaster){//判断是否为主进程
cluster.fork()
}
console.log('一个进程')
结果console了两遍:
那么要开多少个进程才能最大效率的利用资源呢,这取决于你的cpu核数
const cluster = require('cluster')
const os = require('os')
if(cluster.isMaster){//判断是否为主进程
for(let i = 0;i < os.cpus().length;i++){//os.cpus返回系统cpu核数
cluster.fork()
}
console.log('主进程')
}else{
console.log('子进程')
}
看一下结果
一般情况下主进程用来监视,子进程用来干活,所以我们升级一下程序,用子进程来进行网络操作
const http = require('http')
const cluster = require('cluster')
const os = require('os')
const process = require('process')
if(cluster.isMaster){//判断是否为主进程
for(let i = 0;i < os.cpus().length;i++){//os.cpus返回系统cpu核数
cluster.fork()
}
console.log('主进程')
}else{
let server = http.createServer((req,res)=>{
res.write('hhh')
res.end()
})
server.listen(5000)
console.log('子进程服务器' + process.pid + '已启动,在端口5000上')
}
看一下结果,四个子进程公用一个端口,这符合进程第四个原则,"句柄"在这里就是端口
改一下代码,看一下当客户端发起请求时,哪一个子进程服务器执行了响应
let server = http.createServer((req,res)=>{
console.log('子进程服务器' + process.pid + '在干活')
res.write('hhh')
res.end()
})
发起多次请求,结果发现是同一个子进程服务器执行了响应
这是因为,进程调度之间存在开销,如果频繁切换执行响应的进程,会造成过多开销,所以会先用一个进程,如果这个进程资源占满,再开启第二个,这样最高效
多个进程:第一个满了->启动第二个->第二个也满了->启动第三个->......