-
Notifications
You must be signed in to change notification settings - Fork 52
Expand file tree
/
Copy pathapp_worker.js
More file actions
165 lines (146 loc) · 4.58 KB
/
Copy pathapp_worker.js
File metadata and controls
165 lines (146 loc) · 4.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
'use strict';
// $ node app_worker.js options
const options = JSON.parse(process.argv[2]);
if (options.require) {
// inject
options.require.forEach(mod => {
require(mod);
});
}
let AppWorker;
if (options.startMode === 'worker_threads') {
AppWorker = require('./utils/mode/impl/worker_threads/app').AppWorker;
} else {
AppWorker = require('./utils/mode/impl/process/app').AppWorker;
}
const os = require('os');
const fs = require('fs');
const debug = require('util').debuglog('egg-cluster:app_worker');
const ConsoleLogger = require('egg-logger').EggConsoleLogger;
const consoleLogger = new ConsoleLogger({
level: process.env.EGG_APP_WORKER_LOGGER_LEVEL,
});
const Application = require(options.framework).Application;
debug('new Application with options %j', options);
let app;
try {
app = new Application(options);
} catch (err) {
consoleLogger.error(err);
throw err;
}
const clusterConfig = app.config.cluster || /* istanbul ignore next */ {};
const listenConfig = clusterConfig.listen || /* istanbul ignore next */ {};
const httpsOptions = Object.assign({}, clusterConfig.https, options.https);
const port = options.port = options.port || listenConfig.port;
const debugPort = options.debugPort;
const protocol = (httpsOptions.key && httpsOptions.cert) ? 'https' : 'http';
let reusePort = options.reusePort = options.reusePort || listenConfig.reusePort;
if (reusePort && os.platform() !== 'linux') {
// Currently only linux is supported
reusePort = false;
debug('platform %s is not support currently, set reusePort to false', os.platform());
}
AppWorker.send({
to: 'master',
action: 'realport',
data: {
port,
protocol,
},
});
app.ready(startServer);
function exitProcess() {
// Use SIGTERM kill process, ensure trigger the gracefulExit
AppWorker.kill();
}
// exit if worker start timeout
app.once('startTimeout', startTimeoutHandler);
function startTimeoutHandler() {
consoleLogger.error('[app_worker] start timeout, exiting with code:1');
exitProcess();
}
function startServer(err) {
if (err) {
consoleLogger.error(err);
consoleLogger.error('[app_worker] start error, exiting with code:1');
exitProcess();
return;
}
app.removeListener('startTimeout', startTimeoutHandler);
let server;
let debugPortServer;
// https config
if (httpsOptions.key && httpsOptions.cert) {
httpsOptions.key = fs.readFileSync(httpsOptions.key);
httpsOptions.cert = fs.readFileSync(httpsOptions.cert);
httpsOptions.ca = httpsOptions.ca && fs.readFileSync(httpsOptions.ca);
server = require('https').createServer(httpsOptions, app.callback());
if (debugPort) {
debugPortServer = require('http').createServer(app.callback());
}
} else {
server = require('http').createServer(app.callback());
if (debugPort) {
debugPortServer = server;
}
}
server.once('error', err => {
consoleLogger.error('[app_worker] server got error: %s, code: %s', err.message, err.code);
exitProcess();
});
// emit `server` event in app
app.emit('server', server);
if (options.sticky) {
server.listen(options.stickyWorkerPort, '127.0.0.1');
// Listen to messages sent from the master. Ignore everything else.
AppWorker.on('message', (message, connection) => {
if (message !== 'sticky-session:connection') {
return;
}
// Emulate a connection event on the server by emitting the
// event with the connection the master sent us.
server.emit('connection', connection);
connection.resume();
});
} else {
if (listenConfig.path) {
server.listen(listenConfig.path);
} else {
if (typeof port !== 'number') {
consoleLogger.error('[app_worker] port should be number, but got %s(%s)', port, typeof port);
exitProcess();
return;
}
if (reusePort) {
const listenOptions = { port, reusePort };
if (listenConfig.hostname) {
listenOptions.host = listenConfig.hostname;
}
debug('listen options %s', listenOptions);
server.listen(listenOptions);
} else {
const args = [ port ];
if (listenConfig.hostname) {
args.push(listenConfig.hostname);
}
debug('listen options %s', args);
server.listen(...args);
}
}
if (debugPortServer) {
debug('listen on debug port: %s', debugPort);
debugPortServer.listen(debugPort);
}
}
AppWorker.send({
to: 'master',
action: 'listening',
data: server.address() || { port },
});
}
AppWorker.gracefulExit({
logger: consoleLogger,
label: 'app_worker',
beforeExit: () => app.close(),
});