nodejs事件循环与多进程(六)——Nginx是HTTP和反向代理服务器& 正向代理-不知客户端需代理、反向代理-不知服务器需代理& cluster中的优雅退出和进程守护& IPC通信是进程间的通信
nginx proxy
Nginx 是俄罗斯人编写的十分轻量级的 HTTP 服务器,Nginx,它的发音为“engine X”,是一个高性能的HTTP和反向代理服务器。异步非阻塞I/O,而且能够高并发。
正向代理: 客户端为代理,服务器不知道客户端是谁。
反向代理: 服务器为代理,客户端不知道服务器是谁。
nginx配置demo:
http {
upstream cluster {
server 127.0.0.1:3000; // 挂掉
server 127.0.0.1:3001; // 挂掉
server 127.0.0.1:3002;
server 127.0.0.1:3003;
}
server {
listen 80;
server_name www.domain.com;
location / {
proxy_pass http://cluster;
}
}
}
nginx的实际应用场景:比较适合稳定的服务
- 静态资源服务器: js, css, html
- 企业级集群
守护进程: 退出命令行窗口之后,服务一直处于运行状态
cluster多进程调度模型
cluster是由master监听请求,再通过round-robin
算法分发给各个worker,避免了惊群现象的发生。
round-robin 轮询调度算法的原理是每一次把来自用户的请求轮流分配给内部中的服务器
cluster调度模型简易demo
master.js
cluster\master.js
const net = require('net');
const fork = require('child_process').fork; // cluster简易版本,cluster就是基于child_process封装的
var workers = [];
for (var i = 0; i < 4; i++) {
workers.push(fork('./worker')); // cluster workers
}
var handle = net._createServerHandle('0.0.0.0', 3000); //master
handle.listen();
handle.onconnection = function (err,handle) {
var worker = workers.pop();
worker.send({
},handle);
workers.unshift(worker); //通过prop和unshift实现一个简易的轮询
}
cluster\worker.js
const net = require('net');
process.on('message', function (m, handle) {
start(handle);
});
var buf = 'hello Node.js';
var res = ['HTTP/1.1 200 OK','content-length:'+buf.length].join('\r\n')+'\r\n\r\n'+buf;
function start(handle) {
console.log('got a connection on worker, pid = %d', process.pid);
var socket = new net.Socket({
handle: handle
});
socket.readable = socket.writable = true;
socket.end(res);
}
打开终端,执行命令
node .\master.js
worker.js文件的console内容都能打印
cluster中的优雅退出
- 关闭异常 Worker 进程所有的 TCP Server(将已有的连接快速断开,且不再接收新的连接),断开和 Master 的 IPC 通道,不再接受新的用户请求。
- Master 立刻 fork 一个新的 Worker 进程,保证在线的『工人』总数不变。
- 异常 Worker 等待一段时间,处理完已经接受的请求后退出。
if (cluster.isMaster) {
cluster.fork()
} else {
// 出错之后
process.disconnect(); // exit()
}
进程守护
master 进程除了负责接收新的连接,分发给各 worker 进程处理之外,还得像天使一样默默地守护着这些 worker 进程,保障整个应用的稳定性。一旦某个 worker 进程异常退出就 fork 一个新的子进程顶替上去。
这一切 cluster 模块都已经好处理了,当某个 worker 进程发生异常退出或者与 master 进程失去联系(disconnected)时,master 进程都会收到相应的事件通知。
cluster.on('exit', function () {
clsuter.fork();
});
cluster.on('disconnect', function () {
clsuter.fork();
});
IPC通信
IPC通信就是进程间的通信。
虽然每个 Worker 进程是相对独立的,但是它们之间始终还是需要通讯的,叫进程间通讯(IPC)。下面是 Node.js 官方提供的一段示例代码
'use strict';
const cluster = require('cluster');
if (cluster.isMaster) {
const worker = cluster.fork();
worker.send('hi there');
worker.on('message', msg => {
console.log(`msg: ${
msg} from worker#${
worker.id}`);
});
} else if (cluster.isWorker) {
process.on('message', (msg) => {
process.send(msg);
});
}
细心的你可能已经发现 cluster 的 IPC 通道只存在于 Master 和 Worker 之间,Worker 与 Worker 进程互相间是没有的。那么 Worker 之间想通讯该怎么办呢?通过 Master 来转发。
核心: worker直接的通信,靠master转发,利用workder的pid。