Skip to content

Commit 9a44604

Browse files
authored
Merge pull request #68 from godaddy/v2
V2
2 parents cda05de + 5d2a734 commit 9a44604

37 files changed

+1263
-129
lines changed

.npmrc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
registry=http://registry.npmjs.org/

CHANGELOG.md

+33-9
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,35 @@
1+
## v2.0.0 - TBD
2+
3+
### Features:
4+
5+
* High worker restart concurrency to speed up upgrades/restarts via `restartConcurrencyRatio`
6+
* Proxy support with dynamic app versioning
7+
* Central proxy config file, promotions persisted to disk to survive service restarts
8+
* Isolated worker processes per version
9+
* On demand versioning via `x-version` header
10+
* Version promotion brings up worker count for desired version and brings down worker count of old version
11+
* Worker process downgrade from root via `workerGid` & `workerUid`
12+
* Backward compatibility with `v1.x`! Who does that with a major release?!
13+
14+
### Enhancements:
15+
16+
* Refactored communication between processes
17+
* Worker processes may now trigger commands (same) and wait for response (new).
18+
The new message bus enables RPC and other flows like this between processes
19+
20+
### Fixes:
21+
22+
* Worker process.send crash
23+
24+
125
## v1.0.0 - 5/8/2014
226

3-
Features:
27+
### Features:
428

529
* #56. Ability to restart web server gracefully under load with no code
630
* No code required to enable net statistics
731

8-
Fixes:
32+
### Fixes:
933

1034
* Prevent additional commands in CLI while in progress to resolve state issues
1135
* Handle failed `start` command gracefully
@@ -16,17 +40,17 @@ Fixes:
1640
* Allow numeric accessKey's
1741
* Fix crash if no command provided in REST call
1842
* #57. Cannot use '--run' and '--config' together
19-
* #58. Custom events from master & workers
43+
* #58. Custom events from master & workers
2044

2145

2246

2347
## v0.10.0 - 5/2/2014
2448

25-
Legacy:
49+
### Legacy:
2650

2751
* Dropped support for 'ready' flag, was causing support/complexity issues
2852

29-
Features:
53+
### Features:
3054

3155
* Ability to start without worker
3256
* Ability to support multiple versions of cservice through shared state
@@ -36,13 +60,13 @@ Features:
3660

3761
## v0.9.0 - 2/17/2014
3862

39-
Features:
63+
### Features:
4064

4165
* #51. Lockdown "help" command to "local" by default
4266
* #49. Support for multiple keys within 'accessKey' option. (Undocumented,experimental)
4367
* #54. Allow REST command to originate from body
4468

45-
Fixes:
69+
### Fixes:
4670

4771
* #46. Expect API response even on "shutdown" or "exit"
4872
* #52. processDetails not returned during message floods
@@ -52,15 +76,15 @@ Fixes:
5276

5377
## v0.8.0 - 1/13/2014
5478

55-
Features:
79+
### Features:
5680

5781
* #40. Net statistics support
5882

5983

6084

6185
## v0.7.0 - 1/3/2014
6286

63-
Features:
87+
### Features:
6488

6589
* #39. Support for hidden(internal) commands
6690
* #38. Option 'commands' support

README.md

+88-16
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ http://x.co/bpnode
2525
Video:
2626

2727
http://x.co/bpnodevid
28-
29-
28+
29+
3030
## Getting Started
3131

3232
Your existing application, be it console app or service of some kind:
@@ -77,7 +77,7 @@ or for a full list of commands...
7777
or for help on a specific command:
7878

7979
help {command}
80-
80+
8181
We can also issue commands from a seperate process, or even a remote machine (assuming proper access):
8282

8383
npm install -g cluster-service
@@ -144,14 +144,19 @@ Or within your node app:
144144
(in bytes), the process will be restarted gracefully. Only one worker will be restarted at a time.
145145
* `restartOnUpTime` (default: disabled) - If a worker process exceeds the specified uptime threshold
146146
(in seconds), the process will be restarted gracefully. Only one worker will be restarted at a time.
147+
* `restartConcurrencyRatio` (default `0.33`) - The ratio of workers that can be restarted concurrently
148+
during a restart or upgrade process. This can greatly improve the speed of restarts for applications
149+
with many concurrent workers and/or slow initializing workers.
147150
* `commands` - A single directory, an array of directories, or a comma-delimited list of directories
148151
may be provided to auto-register commands found in the provided folders that match the ".js"
149152
extension. If the module exposes the "id" property, that will be the name of the command,
150153
otherwise the filename (minus the extension) will be used as the name of the command. If relative
151154
paths are provided, they will be resolved from process.cwd().
152155
* `master` - An optional module to execute for the master process only, once ```start``` has been completed.
153-
154-
156+
* `proxy` - Optional path to a JSON config file to enable Proxy Support.
157+
* `workerGid` - Group ID to assign to child worker processes (recommended `nobody`).
158+
* `workerUid` - User ID to assign to child worker processes (recommended `nobody`).
159+
155160

156161
## Console & REST API
157162

@@ -177,7 +182,7 @@ Or better yet, use the ```run``` option to do the work for you:
177182
cservice "help" --accessKey "lksjdf982734"
178183
// same as
179184
cservice --run "help" --accessKey "lksjdf982734"
180-
185+
181186

182187

183188
## Cluster Commands
@@ -210,12 +215,12 @@ Or if you prefer to manually do so via code:
210215
// can also fire custom events
211216
cservice.trigger("on.custom.complete", 1, 2, 3);
212217
};
213-
218+
214219
cservice.on("test", function(evt, cb, testScript, timeout) { // we're overriding the "test" command
215220
// arguments
216221
// do something, no callback required (events may optionally be triggered)
217-
};
218-
222+
};
223+
219224
// can also issue commands programatically
220225
cservice.trigger("custom", function(err) { /* my callback */ }, "arg1value", "arg2value");
221226

@@ -253,8 +258,8 @@ Additionally, a worker may optionally perform cleanup tasks prior to exit, via:
253258
process.exit(); // we're responsible for exiting if we register this cb
254259
}
255260
});
256-
257-
261+
262+
258263

259264
## Access Control
260265

@@ -275,8 +280,75 @@ Or may be overriden at runtime via:
275280
require("cluster-service").control({ "exit": "local" });
276281
```
277282

278-
279-
283+
## Proxy Support
284+
285+
Proxy mode specifically caters to Web Servers that you want to enable automatic
286+
versioning of your service. Any version requested (via `versionHeader`) that is
287+
not yet loaded will automatically have a worker process spun up with the new
288+
version, and after ready, the proxy will route to that worker.
289+
290+
Every version of your app *must* adhere to the `PROXY_PORT` environment
291+
variable like so:
292+
293+
require("http").createServer(function(req, res) {
294+
res.writeHead(200);
295+
res.end("Hello world!");
296+
}).listen(process.env.PROXY_PORT || 3000 /* port to use when not running in proxy mode */);
297+
298+
### Proxy Options
299+
300+
* `versionPath` (default: same directory as proxy JSON config) - Can override
301+
to point to a new version folder.
302+
* `defaultVersion` - The version (folder name) that is currently active/live.
303+
If you do not initially set this option, making a request to the Proxy without
304+
a `versionHeader` will result in a 404 (Not Found) since there is no active/live
305+
version.
306+
Upgrades will automatically update this option to the latest upgraded version.
307+
* `versionHeader` (default: `x-version`) - HTTP Header to use when determining
308+
non-default version to route to.
309+
* `workerFilename` (default: `worker.js`) - Filename of worker file.
310+
* `bindings` (default: `[{ port: 80, workerCount: 2 }]`) - An array of `Proxy Bindings`.
311+
* `versionPorts` (default: `11000-12000`) - Reserved port range that can be used to
312+
assign ports to different App versions via `PROXY_PORT`.
313+
* `nonDefaultWorkerCount` (default: 1) - If a version is requested that is not
314+
a default version, this will be the number of worker processes dedicated to
315+
that version.
316+
* `nonDefaultWorkerIdleTime` (default: 3600) - The number of seconds of inactivity
317+
before a non-default version will have its workers shut down.
318+
319+
### Proxy Bindings
320+
321+
Binding options:
322+
323+
* `port` - Proxy port to bind to.
324+
* `workerCount` (default: 2) - Number of worker processes to use for this
325+
binding. Typically more than 2 is unnecessary for a proxy, and less than 2
326+
is a potential failure point if a proxy worker ever goes down.
327+
* `tlsOptions` - TLS Options if binding for HTTPS.
328+
* `key` - Filename that contains the Certificate Key.
329+
* `cert` - Filename that contains the Certificate.
330+
* `pem` - Filename that contains the Certificate PEM if applicable.
331+
332+
A full list of TLS Options: https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener
333+
334+
### Proxy Commands
335+
336+
Work like any other `Cluster Commands`.
337+
338+
* `proxy start configPath` - Start the proxy using the provided JSON config file.
339+
* `proxy stop` - Shutdown the proxy service.
340+
* `proxy version workerVersion workerCount` - Set a given App version to the
341+
desired number of worker processes. If the version is not already running,
342+
it will be started. If 2 workers for the version are already running, and you
343+
request 4, 2 more will be started. If 4 workers for the version are already
344+
running, and you request 2, 2 will be stopped.
345+
* `proxy promote workerVersion workerCount` - Works identical to the
346+
`proxy version` command, except this will flag the version as active/live,
347+
resulting in the Proxy Config file being updated with the new `defaultVersion`.
348+
* `proxy info` - Fetch information about the proxy service.
349+
350+
351+
280352
## Tests & Code Coverage
281353

282354
Download and install:
@@ -285,20 +357,20 @@ Download and install:
285357
cd node-cluster-service
286358
npm install
287359

288-
Now test:
360+
Now test:
289361

290362
npm test
291363

292364
View code coverage in any browser:
293365

294366
coverage/lcov-report/index.html
295367

296-
368+
297369
## Change Log
298370

299371
[Change Log](https://github.com/godaddy/node-cluster-service/blob/master/CHANGELOG.md)
300372

301-
373+
302374

303375
## License
304376

cluster-service.js

+10-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ exports.debug = require("./lib/util").debug;
1010
exports.log = require("./lib/util").log;
1111
exports.error = require("./lib/util").error;
1212
exports.results = require("./lib/util").results;
13+
exports.processSafeSend = require("./lib/util").processSafeSend;
14+
exports.msgBus = require("./lib/message-bus");
1315

1416
exports.workerReady = require("./lib/worker-ready");
1517

@@ -56,16 +58,22 @@ exports.trigger = require("./lib/trigger");
5658
exports.start = require("./lib/start");
5759
exports.netServers = require("./lib/net-servers");
5860
exports.netStats = require("./lib/net-stats");
61+
exports.proxy = require('./lib/proxy');
5962

6063
if (
6164
cluster.isWorker === true
6265
&& typeof (cluster.worker.module) === "undefined"
6366
){
6467
// intermediate state to prevent 2nd call while async in progress
6568
cluster.worker.module = {};
69+
cluster.worker.env = process.env;
70+
71+
var workers = require("./lib/workers");
72+
73+
workers.demote();
6674

6775
// load the worker if not already loaded
68-
// async, in case worker loads cluster-service, we need to return before
76+
// async, in case worker loads cluster-service, we need to return before
6977
// it's avail
7078
setImmediate(function() {
7179
cluster.worker.module = require(process.env.worker);
@@ -80,5 +88,5 @@ if (
8088
});
8189

8290
// start worker monitor to establish two-way relationship with master
83-
require("./lib/workers").monitor();
91+
workers.monitor();
8492
}

examples/certs/test1-cert.pem

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIDXTCCAkWgAwIBAgIJAPWc702VeGKyMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
3+
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
4+
aWRnaXRzIFB0eSBMdGQwHhcNMTMxMjE3MjExMzIwWhcNMTQwMTE2MjExMzIwWjBF
5+
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
6+
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
7+
CgKCAQEApEyXSJ43EqU1Xz4UrLzc84AfwX6WPNvldGtucagk0fTWjq0dSt65kJwk
8+
x3pN+JOA3MjuPP6BUiO4DF02tzAlP/ILia0yANvndZ1C6BsWsZxooFSOYhXEDn3t
9+
AcYRLa5Y4APomrOLc2oIwCPJrZqfnO3tbCbmumOEuI56ib9ADjvcR0DI7VFQUEJy
10+
QLZXXF8HUy97UgyRBhUX/6VO5qpjEmTXV6ZjILcpMMNPDTuzPmC49J/6InVaDQih
11+
R+orRpVYaG2pC+Y4jj5FpcUsCHd/RR6aA7ZPsQHfQfzfjn1YkEIzl3isXZscda9o
12+
GUEtMwAhOMlwB3N4fSw43850G1ulcQIDAQABo1AwTjAdBgNVHQ4EFgQUo61sHkQA
13+
/AVAPvGP8XpXzaMgmWAwHwYDVR0jBBgwFoAUo61sHkQA/AVAPvGP8XpXzaMgmWAw
14+
DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAWEKBAkRkBzS8AiW01SG+
15+
bC24XgVAsLMbckNlYHr2uIGeCfBIBSQGSmIw18zM5FxEwqIV/U3ps19oGBE+M8PR
16+
nflsvOMYJcE8if815UAjN3Qo17wtYqT1X48717S/gLBXP2z3XvmIDr+HtjwKgaxf
17+
WkImDb5qG6H96bwv7mFW7B4r4DIZ8ovVkectaWpvXuK+0pfkYYDJk4ooFkns3dnn
18+
TZUxtz0LAfOOcAhIrTokOsR7+NgFy+DWtlw/YwRF24Cj+WpKb+/f9UncRM67/wT/
19+
gzWSoMjWRbA68La0FGyuxPTTYV2PBe+S5TTeSoqdRXub9W+7Wu0Sz656Dc+QSnTN
20+
RQ==
21+
-----END CERTIFICATE-----

examples/certs/test1-key.pem

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
-----BEGIN RSA PRIVATE KEY-----
2+
MIIEowIBAAKCAQEApEyXSJ43EqU1Xz4UrLzc84AfwX6WPNvldGtucagk0fTWjq0d
3+
St65kJwkx3pN+JOA3MjuPP6BUiO4DF02tzAlP/ILia0yANvndZ1C6BsWsZxooFSO
4+
YhXEDn3tAcYRLa5Y4APomrOLc2oIwCPJrZqfnO3tbCbmumOEuI56ib9ADjvcR0DI
5+
7VFQUEJyQLZXXF8HUy97UgyRBhUX/6VO5qpjEmTXV6ZjILcpMMNPDTuzPmC49J/6
6+
InVaDQihR+orRpVYaG2pC+Y4jj5FpcUsCHd/RR6aA7ZPsQHfQfzfjn1YkEIzl3is
7+
XZscda9oGUEtMwAhOMlwB3N4fSw43850G1ulcQIDAQABAoIBAFdJoa4g8F1ljD93
8+
egBzrmdnkHd6S1M1+Gerk9eqXzV0gHD4o/Fc9vVPH3MjFT2VEAc8cOXSyN3cwDFB
9+
bIpSd9fLPjn82+385rFjxWIO0jW2RRe5FJQjwC9602n30rSURf9t1Cwsa0/76345
10+
BTLITThQZ6zn1fj8Wky61XtNMjjc1o1W+ZCE8QIU5WAoU4zf4DeNuRd6jxPEChUM
11+
DvBlbTmCKV+rLOBhurYr0ejggKtdcjmVhZ89jGZS/ostF0LfRnArHJkrb9JYmgff
12+
lGcv6Z/Ys5iKiTajaLpbEbw5PtDaJi7a3Yy4lSZt7GoZDnEwXgpGCUPq/scNaVbL
13+
4jv/s0kCgYEA1Q90bavDdkYuQtOnFuPlIni44GjXVdBUrbDfcPzN5Voqhh2tOZz/
14+
4/uiWljSdUh21WdRj3KlGx0wEw6Qg3YxC916oGRMx9EU0mpHl1Fkv0SYj7ZET89z
15+
I6XIUX2h5wTmjTTc8taMVra0NH9CHzuz9bCDXT7t/y3RLeGPzqfljtcCgYEAxWlf
16+
V2RyCIO0dZ7ABfNPwYk7rWLozhxkVVwYOtiUhwVjv+XXe86iNGaBHIzdwN2mQ2+a
17+
n8QvoBgRk0gDiiO4pvQUN6okoYglqwyZW1DTqNBgfNh7ADXuM96k5phqbXws4VwW
18+
FRWMbY1unX4LwXf17kBwZdo1qh2bazElAgFhTPcCgYEAwEytqhrAVWzsbhZ4Ffnl
19+
IqLRQoJ98I8TDp24XlNeRqaGAPyiD4D7mLrSgzbt5TtdPil9fLpd+MX0UQ7xMiYo
20+
CGyDNGaywhqc73lLWnD1PIjeJb+9kkdLxZ3o2lxJF6jdqg9PaMJqcg1/Qm6lsGkD
21+
eToypqOYzZt91Cpk0IHLeIsCgYBIehhL4I/ROnF9oWwEg0Dr4DNtw9uPGHNpt2cZ
22+
67wUGlF1+a90P/fjXyLV1Y3wqi/JoGbXc1K85zlEpnLOO7EmcoQdr7TFLVQPCZAg
23+
K3uaBe72xw/ZkvNCTeKi2qBwU9+yWXmuAfxNmFhdMBKm1CEReM0LR+Ld8wLFhwR8
24+
SP9tHwKBgET/wCASds1wvEat2BjjccSyTVwBRaqugwtI+EBN6wJSfpqWUIkcBVtC
25+
hI71RuP/HzFDHjFP+xCbnWbvHOSUzCBnW8I6KO0L5DOeYKHecwrvQ2CEkr3pA6RQ
26+
LIJlSft7D73FbrwbhNqQRZHSW0WO3M0wR+h26tDgR1UE9/j5hXdr
27+
-----END RSA PRIVATE KEY-----

examples/certs/test1-pubkey.pem

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
-----BEGIN PUBLIC KEY-----
2+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApEyXSJ43EqU1Xz4UrLzc
3+
84AfwX6WPNvldGtucagk0fTWjq0dSt65kJwkx3pN+JOA3MjuPP6BUiO4DF02tzAl
4+
P/ILia0yANvndZ1C6BsWsZxooFSOYhXEDn3tAcYRLa5Y4APomrOLc2oIwCPJrZqf
5+
nO3tbCbmumOEuI56ib9ADjvcR0DI7VFQUEJyQLZXXF8HUy97UgyRBhUX/6VO5qpj
6+
EmTXV6ZjILcpMMNPDTuzPmC49J/6InVaDQihR+orRpVYaG2pC+Y4jj5FpcUsCHd/
7+
RR6aA7ZPsQHfQfzfjn1YkEIzl3isXZscda9oGUEtMwAhOMlwB3N4fSw43850G1ul
8+
cQIDAQAB
9+
-----END PUBLIC KEY-----

examples/certs/test1.txt

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
Step 1: Create CSR request
2+
3+
openssl req -x509 -newkey rsa:2048 -keyout test1-key.pem -out test1-cert.pem
4+
5+
pass phrase: test1
6+
7+
8+
9+
Step 2: Remove passphrase
10+
11+
openssl rsa -in test1-key.pem -out test1-key.pem
12+
13+
14+
15+
Step 3: Get Public Key
16+
17+
openssl rsa -in test1-key.pem -pubout > test1-pubkey.pem
18+

0 commit comments

Comments
 (0)