Как запустить несколько приложений Node на одном порту с помощью Restify?

Мне нужно запустить несколько приложений Node на одном порту. Я узнал, что могу запускать несколько узловых приложений, используя один порт, благодаря этому вопросу SO Запуск нескольких приложений Node (Express) на одном порту Но у меня это не работает, вероятно, потому что. Я использую Restify, если я где-то не сделал что-то не так.

У меня уже есть "app1", работающий на этом одном порту с использованием PM2, созданного с помощью Restify. Я создал другое приложение app2. Пути такие:

/var/www/app1
/var/www/app2

с каждым приложением, имеющим общие маршруты, подобные этим:

app.get('/', func...);
app.get('/about', func...);
app.post('/foo', func...);
app.post('/bar', func...);

Я установил последние строки кода "app1" как: exports.app = app вместо app.listen(8080, function() { ... });

и, где app

var app = restify.createServer({
    name: 'app1'
});

"app2" тоже самое...

Мой файл main.js (сохраненный в /var/www/) тоже построен на Restify:

main
 .use('/app`', require('./app1/index').app)
.listen(8080);

где main

var main = restify.createServer({
    name: 'main'
});

Но я получаю такую ​​ошибку, когда набираю node main.js (я еще не пробовал с PM2):

/var/www/node_modules/restify/node_modules/assert-plus/assert.js:45
                    throw new assert.AssertionError({
                          ^
AssertionError: handler (function) is required
    at process (/var/www/node_modules/restify/lib/server.js:76:24)
    at argumentsToChain (/var/www/node_modules/restify/lib/server.js:84:13)
    at Server.use (/var/www/node_modules/restify/lib/server.js:625:6)
    at Object.<anonymous> (/var/www/main.js:47:8)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)

Примечание. Я отключил все приложения, работающие под управлением PM2. Ни на одном порту не запущено ни одного приложения узла.


person junerockwell    schedule 21.03.2016    source источник
comment
вы не можете .... но вы можете запускать несколько экземпляров одного и того же приложения ... в многоядерной системе!   -  person vkstack    schedule 21.03.2016
comment
app.use() специфичен для экспресса и не может использоваться для пересылки запросов чему-либо, кроме другого экспресс-приложения. См. мой ответ ниже для единственного способа поддержки разнородных серверов.   -  person Rob Raisch    schedule 21.03.2016


Ответы (1)


Единственный способ сделать это эффективно — запустить прокси-сервер HTTP, настроенный для ответа на запросы на одном порту и передачи их на основе шаблонов URL-адресов на серверы, работающие на других портах, простой пример которого можно найти по адресу Прокси-сервер HTTP в 20 строках кода node.js.

По сути, ваш публично видимый прокси-сервер работает на порту 80, и вы запускаете другие серверы для обработки определенных запросов.

Так, например, если вы запускаете три HTTP-сервера, один в качестве прокси-сервера пересылки и два для определенных функций, таких как:

  • прокси на 80 порту
  • server2 на порту 8080 для запросов, соответствующих регулярному выражению:/^\/first(?:\/.*)?$/
  • server3 на порту 8081 для запросов, соответствующих регулярному выражению:/^\/second(?:\/.*)?$/

где единственным сервером, имеющим общедоступное соединение, является ваш прокси.

Когда прокси-сервер получает запрос на /first или /first/index.html, он перенаправляет запрос на server2, который возвращает результирующий документ, который затем прокси-сервер отправляет обратно исходному запрашивающему.

Когда он получает запрос на /second/foo/bar/page.html, он делает то же самое, но использует server3 для получения результата.

https://www.npmjs.com/package/http-proxy — это реализация этой стратегии, использующая https://www.npmjs.com/package/http-proxy-rules для обработки и пересылки запросов на основе шаблонов URL.

ОБНОВИТЬ

Для ясности мы предполагаем, что proxy, server2 и server3 выше представляют экземпляры HTTP-сервера отдельных узлов, прослушивающие один IP-адрес, но разные порты на одном компьютере.

Пример:

var http = require('http'),
    httpProxy = require('http-proxy'),
    HttpProxyRules = require('http-proxy-rules');

// Set up proxy rules instance
//   where 
//     any request for /hostname/app1 will be proxy-ed via SERVER2
//     any request for /hostname/app2 will be proxy-ed via SERVER3
var proxyRules = new HttpProxyRules({
  rules: {
    '.*/app1/': 'http://localhost:8080',  // TO SERVER2
    '.*/app2/': 'http://localhost:8081'   // TO SERVER3
  }
});

// Create reverse proxy instance
var proxy = httpProxy.createProxy();

// Create http server on hostname:80 that leverages reverse 
// proxy instance and proxy rules to proxy requests to 
// different one of two target servers
http.createServer(function(req, res) { // PROXY 

  // a match method is exposed on the proxy rules instance
  // to test a request to see if it matches against one 
  // of the specified rules
  var target = proxyRules.match(req);

  if (target) {
    return proxy.web(req, res, {
      target: target
    });
  }

  res.writeHead(500, { 'Content-Type': 'text/plain' });
  res.end('No rule found for this request');

}).listen(80);

// create a new HTTP server on localhost:8080 to process
// requests sent from the proxy
http.createServer(function (req, res) { // SERVER2
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  var headers=JSON.stringify(req.headers,true,2);
  res.write('request successfully proxy-ed to SERVER2!' + '\n' + headers);
  res.end();
}).listen(8080,'localhost');

// create a new HTTP server on localhost:8081 to process
// requests sent from the proxy
http.createServer(function (req, res) { // SERVER3
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  var headers=JSON.stringify(req.headers,true,2);
  res.write('request successfully proxy-ed to SERVER3!' + '\n' + headers);
  res.end();
}).listen(8081,'localhost');

Используя эту настройку:

  • только прокси-сервер будет доступен извне на порту 80
  • серверы, работающие на портах 8080 и 8081, доступны только на локальном компьютере
  • запросы, полученные на прокси-сервере с именем хоста:80, которые соответствуют пути /app1 (и потомкам), будут обработаны прокси-сервером, работающим на localhost:8080
  • запросы, полученные на прокси-сервере с именем хоста:80, которые соответствуют пути /app2 (и потомкам), будут обслуживаться сервером, работающим на localhost:8081
person Rob Raisch    schedule 21.03.2016
comment
Спасибо за это предложение. Он работает, предоставляя server2 и server3 свои собственные порты. Но руководство https://www.npmjs.com/package/http-proxy-rules показывает, что server2 и server3 могут иметь один и тот же порт. Я попробовал это так, но это не сработало. Мне нужно, чтобы server2 и server3 имели один и тот же порт, где я просто делаю rules: { '.*/test': 'http://localhost:8080/server2', // Rule (1) '.*/test2/': 'http://localhost:8080/server3/' // Rule (2) },, а затем слушаю порт 8000. Вы знаете, как это сделать? - person junerockwell; 22.03.2016
comment
Извините, но вы не можете запускать более одного слушателя на порт, как бы вы ни старались. Это ограничение стека TCP/IP операционной системы, и его невозможно обойти. В приведенном вами примере два сервера не работают на одном порту. Скорее, он перенаправляет на два URL-адреса, обслуживаемые одним и тем же сервером через порт 8080. - person Rob Raisch; 22.03.2016
comment
Привет @Rob Raisch, спасибо за объяснение, но я так и думал; один и тот же сервер на одном и том же порту. Как мне использовать одно и то же имя хоста и номер порта для двухузловых приложений (вы назвали server2 и server3 в своем ответе)? Я не понимаю, как server2 создается как часть URL-адреса и как это работает в http://localhost:8080/server2? Я понимаю, что если я наберу http://localhost:8080/test, он перенаправит на http://localhost:8080/server2. Но я не знаю, как сделать URL-адрес http://localhost:8080/server2, чтобы я мог перенаправить на соответствующее приложение node? .../server2 это каталог? - person junerockwell; 22.03.2016
comment
Возможно, я не ясно выразился. Вы не можете запускать более одного прослушивателя для пары IP-адрес и номер порта TCP, и, поскольку имя хоста localhost является сокращением для IP-адреса (127.0.0.1) сетевого интерфейса обратной связи на хосте вашего сервера, вы не можете запустить более одного процесса на 127.0.0.1:8080. Полная остановка. - person Rob Raisch; 22.03.2016
comment
Что касается примера кода http-proxy-rules, вы заметите, что вместо того, чтобы запускать несколько серверов на одном и том же порту, он описывает проксирование запросов к разным целевым путям на одном сервере, работающем на localhost:8080. - person Rob Raisch; 23.03.2016
comment
не могли бы вы показать демо об этом? Я специально хочу понять, как создаются пути, и как только прокси-сервер перенаправляется на URL-адрес, скажем, localhost:8080/server2, имеет ли приложение узла server2 свой собственный номер порта, кроме 8080? Другими словами, localhost:8080/server2 указывает на localhost:8888 или что-то в этом роде? Как он указывает на правильное приложение узла? Извините, но я новичок во всем, что касается прокси. - person junerockwell; 23.03.2016
comment
Пример, приведенный в README для https://www.npmjs.com/package/http-proxy-rules, запускает один прокси-сервер. сервер на localhost:6010, который проксирует запросы на другой простой http-сервер, который, как предполагается в примере, существует и работает, но конкретно не определен в примере. Решение, что и где проксировать, определяется в объекте proxyRules. Чтобы было ясно, в примере предполагается два сервера: прокси-сервер, который определен, и другой простой http-сервер, который не определен в примере и должен работать на localhost:8080, чтобы пример работал. - person Rob Raisch; 23.03.2016