|
1 |
| -/* This example spawns two worker threads, each with their own |
2 |
| - * server listening to the same port (Linux feature). */ |
| 1 | +/* This example shows two different approaches to multi-core load balancing. |
| 2 | + * The first approach (the oldest) requires Linux and will only work on Linux. |
| 3 | + * This approach listens to port 4000 on all CPUs. That's it. That's all you do. |
| 4 | + * Listening to the same port from many worker threads will work on Linux. |
| 5 | + * The second approach will work on all platforms; you set up a main acceptorApp and register all child apps |
| 6 | + * (worker apps) with it. The acceptorApp will listen to port 9001 and move sockets in round-robin fashion to |
| 7 | + * the registered child apps. |
| 8 | + * Note that, in this example we only create 2 worker threads. Ideally you should create as many as there are CPUs |
| 9 | + * in your system. But by only creating 2 here, it is simple to see the perf. gain on a system of 4 cores, as you can then |
| 10 | + * run the client side on the remaining 2 cores without interfering with the server side. */ |
3 | 11 |
|
4 | 12 | const uWS = require('../dist/uws.js');
|
5 | 13 | const port = 9001;
|
6 |
| -const { Worker, isMainThread, threadId } = require('worker_threads'); |
| 14 | +const { Worker, isMainThread, threadId, parentPort } = require('worker_threads'); |
7 | 15 | const os = require('os');
|
8 | 16 |
|
9 | 17 | if (isMainThread) {
|
| 18 | + |
| 19 | + /* The acceptorApp only listens, but must be SSL if worker apps are SSL and likewise opposite */ |
| 20 | + const acceptorApp = uWS./*SSL*/App({ |
| 21 | + key_file_name: 'misc/key.pem', |
| 22 | + cert_file_name: 'misc/cert.pem', |
| 23 | + passphrase: '1234' |
| 24 | + }).listen(port, (token) => { |
| 25 | + if (token) { |
| 26 | + console.log('Listening to port ' + port + ' from thread ' + threadId + ' as main acceptor'); |
| 27 | + } else { |
| 28 | + console.log('Failed to listen to port ' + port + ' from thread ' + threadId); |
| 29 | + } |
| 30 | + }); |
| 31 | + |
10 | 32 | /* Main thread loops over all CPUs */
|
11 | 33 | /* In this case we only spawn two (hardcoded) */
|
12 | 34 | /*os.cpus()*/[0, 1].forEach(() => {
|
| 35 | + |
13 | 36 | /* Spawn a new thread running this source file */
|
14 |
| - new Worker(__filename); |
| 37 | + new Worker(__filename).on("message", (workerAppDescriptor) => { |
| 38 | + acceptorApp.addChildAppDescriptor(workerAppDescriptor); |
| 39 | + }); |
15 | 40 | });
|
16 | 41 |
|
17 | 42 | /* I guess main thread joins by default? */
|
18 | 43 | } else {
|
19 | 44 | /* Here we are inside a worker thread */
|
20 |
| - const app = uWS.SSLApp({ |
| 45 | + const app = uWS./*SSL*/App({ |
21 | 46 | key_file_name: 'misc/key.pem',
|
22 | 47 | cert_file_name: 'misc/cert.pem',
|
23 | 48 | passphrase: '1234'
|
24 | 49 | }).get('/*', (res, req) => {
|
25 | 50 | res.end('Hello Worker!');
|
26 |
| - }).listen(port, (token) => { |
27 |
| - if (token) { |
28 |
| - console.log('Listening to port ' + port + ' from thread ' + threadId); |
29 |
| - } else { |
30 |
| - console.log('Failed to listen to port ' + port + ' from thread ' + threadId); |
31 |
| - } |
| 51 | + }).listen(4000, (token) => { |
| 52 | + if (token) { |
| 53 | + console.log('Listening to port ' + 4000 + ' from thread ' + threadId); |
| 54 | + } else { |
| 55 | + console.log('Failed to listen to port ' + 4000 + ' from thread ' + threadId); |
| 56 | + } |
32 | 57 | });
|
| 58 | + |
| 59 | + /* The worker sends back its descriptor to the main acceptor */ |
| 60 | + parentPort.postMessage(app.getDescriptor()); |
33 | 61 | }
|
0 commit comments