Skip to content

Commit 0f7558b

Browse files
authored
fix: should not ready when call server.listen in sticky mode (#91)
1 parent 78dc832 commit 0f7558b

File tree

7 files changed

+48
-21
lines changed

7 files changed

+48
-21
lines changed

index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const Master = require('./lib/master');
1212

1313
/**
1414
* start egg app
15-
* @method Egg#startCluster
15+
* @function Egg#startCluster
1616
* @param {Object} options {@link Master}
1717
* @param {Function} callback start success callback
1818
*/

lib/app_worker.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ function startServer(err) {
6666
app.emit('server', server);
6767

6868
if (options.sticky) {
69-
server.listen(0, '127.0.0.1');
69+
server.listen(options.stickyWorkerPort, '127.0.0.1');
7070
// Listen to messages sent from the master. Ignore everything else.
7171
process.on('message', (message, connection) => {
7272
if (message !== 'sticky-session:connection') {

lib/master.js

+35-17
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const EventEmitter = require('events');
99
const childprocess = require('child_process');
1010
const cfork = require('cfork');
1111
const ready = require('get-ready');
12-
const detectPort = require('detect-port');
12+
const GetFreePort = require('detect-port');
1313
const ConsoleLogger = require('egg-logger').EggConsoleLogger;
1414
const utility = require('utility');
1515
const semver = require('semver');
@@ -28,7 +28,7 @@ const REALPORT = Symbol('Master#realport');
2828
class Master extends EventEmitter {
2929

3030
/**
31-
* @constructor
31+
* @class
3232
* @param {Object} options
3333
* - {String} [framework] - specify framework that can be absolute path or npm package
3434
* - {String} [baseDir] directory of application, default to `process.cwd()`
@@ -129,17 +129,10 @@ class Master extends EventEmitter {
129129
fs.writeFileSync(this.options.pidFile, process.pid, 'utf-8');
130130
}
131131

132-
detectPort((err, port) => {
133-
/* istanbul ignore if */
134-
if (err) {
135-
err.name = 'ClusterPortConflictError';
136-
err.message = '[master] try get free port error, ' + err.message;
137-
this.logger.error(err);
138-
process.exit(1);
139-
}
140-
this.options.clusterPort = port;
141-
this.forkAgentWorker();
142-
});
132+
this.detectPorts()
133+
.then(() => {
134+
this.forkAgentWorker();
135+
});
143136

144137
// exit when agent or worker exception
145138
this.workerManager.on('exception', ({ agent, worker }) => {
@@ -151,6 +144,28 @@ class Master extends EventEmitter {
151144
});
152145
}
153146

147+
detectPorts() {
148+
// Detect cluster client port
149+
return GetFreePort()
150+
.then(port => {
151+
this.options.clusterPort = port;
152+
// If sticky mode, detect worker port
153+
if (this.options.sticky) {
154+
return GetFreePort();
155+
}
156+
})
157+
.then(port => {
158+
if (this.options.sticky) {
159+
this.options.stickyWorkerPort = port;
160+
}
161+
})
162+
.catch(/* istanbul ignore next */ err => {
163+
this.logger.error(err);
164+
process.exit(1);
165+
});
166+
}
167+
168+
154169
log(...args) {
155170
this.logger[this.logMethod](...args);
156171
}
@@ -445,10 +460,13 @@ class Master extends EventEmitter {
445460
const worker = this.workerManager.getWorker(data.workerPid);
446461
const address = data.address;
447462

448-
// ignore unspecified port
449-
// and it is ramdom port when use sticky
450-
if (!this.options.sticky
451-
&& !isUnixSock(address)
463+
// worker should listen stickyWorkerPort when sticky mode
464+
if (this.options.sticky) {
465+
if (String(address.port) !== String(this.options.stickyWorkerPort)) {
466+
return;
467+
}
468+
// worker should listen REALPORT when not sticky mode
469+
} else if (!isUnixSock(address)
452470
&& (String(address.port) !== String(this[REALPORT]))) {
453471
return;
454472
}

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"scripts": {
77
"autod": "autod",
88
"lint": "eslint .",
9-
"test": "npm run lint && npm run test-local",
9+
"test": "npm run lint -- --fix && npm run test-local",
1010
"test-local": "egg-bin test",
1111
"cov": "egg-bin cov --prerequire --timeout 100000",
1212
"ci": "npm run lint && egg-bin pkgfiles --check && npm run cov",

test/app_worker.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ describe('test/app_worker.test.js', () => {
223223
.expect(200);
224224
throw new Error('should not run');
225225
} catch (err) {
226-
assert(err.code === 'ECONNREFUSED');
226+
assert(/ECONNREFUSED/.test(err.message));
227227
}
228228
});
229229

Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
'use strict';
22

3+
const net = require('net');
4+
35
module.exports = app => {
46
// don't use the port that egg-mock defined
57
app._options.port = undefined;
8+
const server = net.createServer();
9+
server.listen(9500);
10+
11+
app.beforeClose(() => {
12+
return server.close();
13+
});
614
};

test/master.test.js

+1
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,7 @@ describe('test/master.test.js', () => {
828828
after(() => app.close());
829829

830830
it('should online sticky cluster mode startup success', () => {
831+
app.expect('stdout', /app_worker#\d:\d+ started at (?!9500)/);
831832
app.expect('stdout', /egg started on http:\/\/127.0.0.1:17010/);
832833
return request('http://127.0.0.1:17010')
833834
.get('/portal/i.htm')

0 commit comments

Comments
 (0)