背景
eggjs 默认是 cluster 模式启动服务,而 clinic 不支持 cluster 模式,找了一下网上的文章尝试解决问题,并未找到直接清晰的结论,最终翻阅源码找到解决方式记录分享以期为后来者节省时间。
先说结论
通过重写一个单进程启动文件进行性能分析代码如下:
const path = require('path')
const egg = require('egg')
const singleProcessApp = async (options = {}) => {
options.env = options.env || 'local'
options.baseDir = path.resolve('./')
const app = await egg.start(options)
app.listen(7001)
return app
}
singleProcessApp()
npm clinc script
"clinic":"clinic doctor --on-port 'autocannon -c 100 -d 10 -p 10 localhost:$PORT' -- node singleProcess.js"
对应源码
竟然五年前就存在了,有种知识断层的感觉!
'use strict';
const path = require('path');
module.exports = async (options = {}) => {
options.baseDir = options.baseDir || process.cwd();
options.mode = 'single';
// get agent from options.framework and package.egg.framework
if (!options.framework) {
try {
options.framework = require(path.join(options.baseDir, 'package.json')).egg.framework;
} catch (_) {
// ignore
}
}
let Agent;
let Application;
if (options.framework) {
Agent = require(options.framework).Agent;
Application = require(options.framework).Application;
} else {
Application = require('./application');
Agent = require('./agent');
}
const agent = new Agent(Object.assign({}, options));
await agent.ready();
const application = new Application(Object.assign({}, options));
application.agent = agent;
agent.application = application;
await application.ready();
// emit egg-ready message in agent and application
application.messenger.broadcast('egg-ready');
return application;
};
对应测试代码
/**
* start app with single process mode
*
* @param {String} baseDir - base dir.
* @param {Object} [options] - optional
* @return {App} app - Application object.
*/
exports.singleProcessApp = async (baseDir, options = {}) => {
if (!baseDir.startsWith('/')) baseDir = path.join(__dirname, 'fixtures', baseDir);
options.env = options.env || 'unittest';
options.baseDir = baseDir;
const app = await egg.start(options);
app.httpRequest = () => request(app.callback());
return app;
};