架构机制
Egg.js 源码探秘
代码加载与依赖注入
集群模式的启动逻辑
首先是
// 封装参数
this.serverBin = path.join(__dirname, '../start-cluster');
...
const eggArgs = [
...(execArgv || []),
this.serverBin,
clusterOptions,
`--title=${argv.title}`
];
...
// 启动执行进程
spawn('node', eggArgs, options);
然后
// start-cluster
require(options.framework).startCluster(options);
exports.startCluster = function(options, callback) {
new Master(options).ready(callback);
};
┌────────┐
│ parent │
/└────────┘\
/ | \
/ ┌────────┐ \
/ │ master │ \
/ └────────┘ \
/ / \ \
┌───────┐ ┌───────┐
│ agent │ ------- │ app │
└───────┘ └───────┘
在
// AgentWorker 创建完毕后创建 AppWorkers
this.once("agent-start", this.forkAppWorkers.bind(this));
// 使用 fork 创建新的 AgentWorker
const agentWorker = childprocess.fork(agentWorkerFile, args, opt);
在
cfork({
exec: appWorkerFile,
args,
silent: false,
count: this.options.workers,
// don't refork in local env
refork: this.isProduction
});
cluster.on('fork', worker => {
...
this.workerManager.setWorker(worker);
...
});
// 子进程开始监听后,发送 app-start 消息
cluster.on('listening', (worker, address) => {
this.messenger.send({
action: 'app-start',
...
});
});
// enable all workers when app started
for (const id in cluster.workers) {
const worker = cluster.workers[id];
worker.disableRefork = false;
}
// manager.js
startMasterSocketServer(cb) {
// Create the outside facing server listening on our port.
require('net').createServer({ pauseOnConnect: true }, connection => {
if (!connection.remoteAddress) {
connection.close();
} else {
const worker = this.stickyWorker(connection.remoteAddress);
worker.send('sticky-session:connection', connection);
}
}).listen(this[REALPORT], cb);
}
这里的
// app_worker.js
const Application = require(options.framework).Application;
const app = new Application(options);
应用创建完毕后会调用
// app_worker.js
if (options.https) {
const httpsOptions = Object.assign({}, options.https, {
key: fs.readFileSync(options.https.key),
cert: fs.readFileSync(options.https.cert)
});
server = require("https").createServer(httpsOptions, app.callback());
} else {
server = require("http").createServer(app.callback());
}
如果是
// app_worker.js
if (options.sticky) {
server.listen(0, "127.0.0.1");
} else {
server.listen(...args);
}