Как обещал ранее, я публикую исходный код, демонстрирующий, как построить HTTP-сервер в режиме prefork, используя Web Workers и новый API
В master.js мы создаём сокет, прикрепленный к порту 8080, и порождаем 4 рабочих процесса для обработки запросов. Мы отправляем сообщение каждому обработчику со текстом, которую нужно будет использовать для всех ответов на запросы, а также файловый дескриптор нашего сокета.
В worker.js мы создаём экземпляр HTTP-сервера, но не вызываем
Когда мы запускаем master.js, мы можем использовать curl для проверки, что запросы были обработаны разными процессами.
Очень просто.
net.Server.listenFD()
. Я надеюсь, что этот код будет хорошим примером того, как легко нагрузить несколько ядер сервера, комбинируя пересылку файловых дескрипторов и Web Workers.В master.js мы создаём сокет, прикрепленный к порту 8080, и порождаем 4 рабочих процесса для обработки запросов. Мы отправляем сообщение каждому обработчику со текстом, которую нужно будет использовать для всех ответов на запросы, а также файловый дескриптор нашего сокета.
- var path = require('path');
- var netBindings = process.binding('net');
- var Worker = require('webworker').Worker;
-
- var fd = netBindings.socket('tcp4');
- netBindings.bind(fd, 8080);
- netBindings.listen(fd, 128);
-
- for (var i = 0; i < 3; i++) {
- var w = new Worker(path.join(__dirname, 'worker.js'));
- w.postMessage({ 'banner' : 'Hello, world!' }, fd);
- }
В worker.js мы создаём экземпляр HTTP-сервера, но не вызываем
listen()
. Вместо этого мы ожидаем принятия сообщений от родительского процесса. При получении события иы забираем файловый дескриптор из сообщения и используем его для привязки нашего экземпляра http.Server к сокету. Как только будет вызван http.Server.listenFD()
, этот процесс начнёт обрабатывать запросы.
- var assert = require('assert');
- var http = require('http');
-
- var banner = undefined;
-
- var srv = http.createServer(function(req, resp) {
- resp.writeHead(200, {'Content-Type' : 'text/plain'});
- resp.write(banner + ' (pid ' + process.pid + ')\n');
- resp.end();
- });
-
- onmessage = function(msg) {
- assert.ok(msg.fd && msg.fd > 0);
-
- banner = msg.data.banner;
-
- srv.listenFD(msg.fd);
- };
Когда мы запускаем master.js, мы можем использовать curl для проверки, что запросы были обработаны разными процессами.
- % curl 'http://localhost:8080'
- Hello, world! (pid 27727)
- % curl 'http://localhost:8080'
- Hello, world! (pid 27728)
- % curl 'http://localhost:8080'
- Hello, world! (pid 27729)
- % curl 'http://localhost:8080'
- Hello, world! (pid 27727)
Очень просто.