Apache и Node.js на одном сервере

352

Я хочу использовать Node, потому что он быстрый, использует тот же язык, который я использую на стороне клиента, и по определению неблокируемый. Но парень, которого я нанял написать программу для обработки файлов (сохранение, редактирование, переименование, загрузка, выгрузка файлов и т. Д.), Он хочет использовать apache. Итак, я должен:

  1. Убедите его использовать Node (он отказывается от этого)

  2. Узнайте, как загружать, загружать, переименовывать, сохранять и т. Д. Файлы в узле или

  3. Я должен установить Apache и узел на одном сервере.

Какая ситуация наиболее благоприятная и как мне ее реализовать?

Matt
источник

Ответы:

704

Отличный вопрос!

Существует множество веб-сайтов и бесплатных веб-приложений, реализованных на PHP, которые работают на Apache, многие используют его, чтобы вы могли сделать что-то довольно простое и, кроме того, это простой способ предоставления статического контента. Node - это быстрый, мощный, элегантный и привлекательный инструмент с мощным V8 и плоским стеком без встроенных зависимостей.

Я также хочу легкость / гибкость Apache и все же ворчание и элегантность Node.JS, почему я не могу иметь и то и другое ?

К счастью, с помощью директивы ProxyPass в Apache httpd.confне слишком сложно передать все запросы по определенному URL-адресу в приложение Node.JS.

ProxyPass /node http://localhost:8000

Кроме того, убедитесь, что следующие строки НЕ закомментированы, чтобы вы получили правильный прокси и субмодуль для перенаправления http-запросов:

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

Затем запустите приложение Node на порту 8000!

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello Apache!\n');
}).listen(8000, '127.0.0.1');

Затем вы можете получить доступ ко всей логике Node.JS, используя /node/путь в вашем URL, а остальную часть сайта можно оставить Apache для размещения ваших существующих страниц PHP:

введите описание изображения здесь

Теперь осталось только убедить вашу хостинговую компанию позволить вам работать с этой конфигурацией !!!

Стивен де Салас
источник
6
Это был отличный ответ, я просто хотел добавить ссылку с немного большей информацией о передаче прокси, которую я использовал для этой работы. Проверьте комментарии также. boriskuzmanovic.wordpress.com/2006/10/20/…
Алекс Муро
11
Я проверил размещение ProxyPass / 127.0.0.1:8000 внутри контейнера виртуального хоста и смог успешно перенаправить всю группу домена на экземпляр узла. Я также проверил с помощью «time wget ...», чтобы сравнить скорость доступа к узлу напрямую с доступом через Apache. В 30 парах испытаний средняя разница составляла около 0,56 мс. Минимальное время загрузки составило 120 мс как для прямой, так и для Apache. Максимальное время загрузки составило 154 мс для прямой и 164 мсек через Apache. Не существенная разница. Если бы у меня была роскошь двух IP-адресов, я бы не маршрутизировал через Apache, но сейчас я буду придерживаться Proxypass
kaan_a
5
Разве этот прокси не запрашивает у Apache к Node, в то время как устраняет преимущества неблокирующей природы Node?
Трассировка
2
Привет @Basj, у меня нет опыта установки поддержки веб-сокетов самостоятельно. Сказав это, Apache 2.4.6, похоже, поддерживает передачу трафика веб-сокетов с использованием mod_proxy_wstunnel. Я вижу, что вы уже нашли свой ответ, для других с такой же проблемой, пожалуйста, обратитесь к: serverfault.com/questions/616370/…
Стивен де Салас
4
Где я могу добавить это в дистрибутивы на основе Debian? Там нет файла httpd.conf.
Санти
63

Этот вопрос больше относится к отказу сервера, но FWIW я бы сказал, что запуск Apache перед Node.js в большинстве случаев не очень хороший подход.

Apache ProxyPass отлично подходит для многих вещей (например, для предоставления сервисов на основе Tomcat как части сайта), и если ваше приложение Node.js выполняет определенную небольшую роль или является внутренним инструментом, который может иметь ограниченное количество пользователей. тогда может быть проще просто использовать его, чтобы вы могли заставить его работать и двигаться дальше, но это не похоже на случай здесь.

Если вы хотите воспользоваться преимуществами производительности и масштабируемости, которые вы получите от использования Node.js - и особенно если вы хотите использовать что-то, что подразумевает поддержание постоянного соединения, например, веб-сокеты, - вам лучше использовать Apache и ваш Node. js на других портах (например, Apache на localhost: 8080, Node.js на localhost: 3000), а затем запускать что-то вроде прокси nginx, Varnish или HA впереди - и таким образом маршрутизировать трафик.

С помощью чего-то вроде лака или nginx вы можете маршрутизировать трафик в зависимости от пути и / или хоста. Они оба используют гораздо меньше системных ресурсов и гораздо более масштабируемы, чем Apache, чтобы сделать то же самое.

Иэн Коллинз
источник
13
этот ответ должен иметь больше голосов. безусловно, гораздо лучше использовать прокси nginx, чем apache.
переписать
Oracle
1
Есть ли у вас цифры, подтверждающие ваше утверждение, что nginx будет менее ресурсоемким, чем httpd?
RedShift
Я не думаю, что это довольно драматично. Хотя я стараюсь не ссылаться в ответах, так как ссылки хрупки, но вы можете найти некоторые обсуждения и примеры через Google - например, help.dreamhost.com/hc/en-us/articles/…… Apache - отличное программное обеспечение, но обычно это не отличный подход в таком контексте.
Иэн Коллинз
Этот ответ звучит хорошо, но тогда как получить доступ к Node.js через httpS, поскольку он уже используется Apache?
Пьер
34


Инструкции для запуска node serverвместе apache2(v2.4.xx) server:

Для того , чтобы трубы все запросы на определенном URL для вашего приложения Node.js создать CUSTOM.confфайл в /etc/apache2/conf-availableдиректории, и добавьте следующую строку в созданный файл:

ProxyPass /node http://localhost:8000/

Измените 8000 на предпочтительный номер порта для node server.
Включите пользовательские конфигурации с помощью следующей команды:

$> sudo a2enconf CUSTOM

CUSTOM - это ваше вновь созданное имя файла без расширения, затем включите его proxy_httpс помощью команды:

$> sudo a2enmod proxy_http

он должен включить как proxyи proxy_httpмодули. Вы можете проверить, включен ли модуль с помощью:

$> sudo a2query -m MODULE_NAME

После настройки и включения модулей вам нужно будет перезапустить сервер Apache:

$> sudo service apache2 restart

Теперь вы можете выполнить узел сервера. Все запросы к URL/nodeсерверу будут обрабатываться узлом сервера.

krmld
источник
Работает как шарм! :)
Кис Коенен
15

Запуск Node и Apache на одном сервере тривиален, так как они не конфликтуют. NodeJS - это просто способ выполнить серверную часть JavaScript. Настоящая дилемма возникает из-за доступа к Node и Apache извне. На мой взгляд, у вас есть два варианта:

  1. Настройте Apache на прокси всех соответствующих запросов к NodeJS, который будет выполнять загрузку файлов и все остальное в узле.

  2. Установите Apache и Node на разные комбинации IP: порт (если у вашего сервера два IP-адреса, то один может быть привязан к слушателю вашего узла, а другой - к Apache).

Я также начинаю подозревать, что это может быть не то, что вы на самом деле ищете. Если ваша конечная цель заключается в том, чтобы вы написали логику приложения на Nodejs и какую-то часть «обработки файлов», которую вы передаете подрядчику, тогда это действительно выбор языка, а не веб-сервер.

Ярек Т
источник
9

Вы можете использовать другой подход, такой как написание обратного прокси-сервера с nodejs для прокси как apache, так и всех других приложений nodejs.

Сначала необходимо настроить Apache на другой порт, отличный от порта 80. Например: порт 8080.

Затем вы можете написать скрипт обратного прокси с nodejs как:

var proxy = require('redbird')({port: 80, xfwd: false);

proxy.register("mydomain.me/blog", "http://mydomain.me:8080/blog");
proxy.register("mydomain.me", "http://mydomain.me:3000");

Следующая статья описывает весь процесс создания этого.

RUN APACHE с NODE JS REVERSE PROXY - ИСПОЛЬЗОВАНИЕ REDBIRD

wathmal
источник
2
ProxyPass /node http://localhost:8000/     
  • это сработало для меня, когда я сделал выше запись в httpd-vhosts.conf вместо httpd.conf
  • Я установил XAMPP в своей среде и собирался поразить весь трафик на apache через порт 80 с приложением NodeJS, работающим на порту 8080, то есть http: // localhost / [name_of_the_node_application]
рахул шукла
источник
1

Я объединил ответ выше с certbot SSL cert и CORS access-control-allow-headers и заставил его работать, поэтому я решил поделиться результатами.

Apache httpd.conf добавлен в конец файла:

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

Настройки Apache VirtualHost (корень документа для PHP находится под Apache и SSL с Certbot, а сайт node.js / socket.io работает на порту 3000 - и использует SSL-сертификат от Apache). Также обратите внимание, что сайт node.js использует прокси-сервер для папки / nodejs, socket.io и ws (websockets):

<IfModule mod_ssl.c>
<VirtualHost *:443>
    ServerName www.example.com
    ServerAlias www.example.com
    DocumentRoot /var/html/www.example.com
    ErrorLog /var/html/log/error.log
    CustomLog /var/html/log/requests.log combined
    SSLCertificateFile /etc/letsencrypt/live/www.example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/www.example.com/privkey.pem
    Include /etc/letsencrypt/options-ssl-apache.conf

    RewriteEngine On
    RewriteCond %{REQUEST_URI}  ^socket.io          [NC]
    RewriteCond %{QUERY_STRING} transport=websocket [NC]
    RewriteRule /{.*}       ws://localhost:3000/$1  [P,L]

    RewriteCond %{HTTP:Connection} Upgrade [NC]
    RewriteRule /(.*) ws://localhost:3000/$1 [P,L]

    ProxyPass /nodejs http://localhost:3000/
    ProxyPassReverse /nodejs http://localhost:3000/

    ProxyPass /socket.io http://localhost:3000/socket.io
    ProxyPassReverse /socket.io http://localhost:3000/socket.io

    ProxyPass /socket.io ws://localhost:3000/socket.io
    ProxyPassReverse /socket.io ws://localhost:3000/socket.io

</VirtualHost>
</IfModule>

Тогда мое приложение node.js (app.js):

var express = require('express');
var app = express();
    app.use(function(req, res, next) {
        res.header("Access-Control-Allow-Origin", "*");
        res.header("Access-Control-Allow-Headers", "X-Requested-With");
        res.header("Access-Control-Allow-Headers", "Content-Type");
        res.header("Access-Control-Allow-Methods", "PUT, GET, POST, DELETE, OPTIONS");
        next();
    });
var http = require('http').Server(app);
var io = require('socket.io')(http);

http.listen({host:'0.0.0.0',port:3000});

Я заставляю слушателя ip4, но это необязательно - вы можете заменить:

http.listen(3000);

Код приложения node.js (app.js) продолжается:

io.of('/nodejs').on('connection', function(socket) {
    //optional settings:
    io.set('heartbeat timeout', 3000); 
    io.set('heartbeat interval', 1000);

    //listener for when a user is added
    socket.on('add user', function(data) {
         socket.join('AnyRoomName');
         socket.broadcast.emit('user joined', data);
    });

    //listener for when a user leaves
    socket.on('remove user', function(data) {
         socket.leave('AnyRoomName');
         socket.broadcast.emit('user left', data);
    });

    //sample listener for any other function
    socket.on('named-event', function(data) {
         //code....
         socket.broadcast.emit('named-event-broadcast', data);
    });

    // add more listeners as needed... use different named-events...
});

наконец, на стороне клиента (создается как nodejs.js):

//notice the /nodejs path
var socket = io.connect('https://www.example.com/nodejs');

//listener for user joined
socket.on('user joined', function(data) {
    // code... data shows who joined...
});

//listener for user left
socket.on('user left', function(data) {
    // code... data shows who left...
});

// sample listener for any function:
socket.on('named-event-broadcast', function(data) {
    // this receives the broadcast data (I use json then parse and execute code)
    console.log('data1=' + data.data1);
    console.log('data2=' + data.data2);
});

// sample send broadcast json data for user joined:
socket.emit('user joined', {
    'userid': 'userid-value',
    'username':'username-value'
});

// sample send broadcast json data for user left 
//(I added the following with an event listener for 'beforeunload'):
// socket.emit('user joined', {
//     'userid': 'userid-value',
//     'username':'username-value'
// });

// sample send broadcast json data for any named-event:
socket.emit('named-event', {
    'data1': 'value1',
    'data2':'value2'
});

В этом примере при загрузке JS он отправляет в сокет «именованное событие», отправляя данные в JSON на сервер node.js / socket.io.

Используя io и сокет на сервере в path / nodejs (подключенный клиентом), получает данные и затем повторно отправляет их как широковещательную рассылку. Любые другие пользователи в сокете будут получать данные со своим слушателем «named-event-broadcast». Обратите внимание, что отправитель не получает собственную рассылку.

Доктор Аарон Дишно
источник
0

Недавно я столкнулся с такой проблемой, когда мне нужно общаться между клиентом и сервером, используя websocket в проекте codeigniter на основе PHP.

Я решил эту проблему, добавив свой порт (на котором запущено приложение узла) в списки Allow incoming TCP ports& Allow outgoing TCP ports.

Вы можете найти эти конфигурации в Firewall Configurationsпанели WHM вашего сервера.

Паритош Пандей
источник
-1

Я искал ту же информацию. Наконец-то нашел ответ по ссылке на ответ выше @Straseus

http://arguments.callee.info/2010/04/20/running-apache-and-node-js-together/

Вот окончательное решение для запуска веб-сайта apache на порту 80, службы узла js на порту 8080 и использования .htaccess RewriteRule

В DocumentRoot веб-сайта apache добавьте следующее:

Options +FollowSymLinks -MultiViews

<IfModule mod_rewrite.c>

RewriteEngine on

# Simple URL redirect:
RewriteRule ^test.html$ http://arguments.callee.info:8000/test/ [P]

# More complicated (the user sees only "benchmark.html" in their address bar)
RewriteRule ^benchmark.html$ http://arguments.callee.info:8000/node?action=benchmark [P]

# Redirect a whole subdirectory:
RewriteRule ^node/(.*) http://arguments.callee.info:8000/$1 [P]

Для перенаправления на уровне каталога, ссылка выше предложила (. +) Правило, которое требует один или несколько символов после 'node /'. Я должен был преобразовать его в (. *), Который равен нулю или больше, чтобы мои вещи работали.

Большое спасибо за ссылку @Straseus

pd1980
источник
3
Просто отметьте, что флаг [P] требует, чтобы Apache mod_proxyбыл включен.
Саймон Ист
Это неэффективно. Зачем вызывать переписать движок поверх простого ProxyPass?
Майкл Иригойен
-2

Я предполагаю, что вы делаете веб-приложение, потому что вы ссылаетесь на Apache и Node. Быстрый ответ - возможно ли это - ДА. Рекомендуется - НЕТ. Node связывает свой собственный веб-сервер, и большинство веб-сайтов работают на порте 80. Я также предполагаю, что в настоящее время нет плагина Apache, который поддерживается Nodejs, и я не уверен, является ли создание виртуального хоста лучшим способом для реализации этого. На эти вопросы должны ответить разработчики, которые поддерживают Nodejs как хороших людей в Joyent.

Вместо портов было бы лучше оценить технический стек Node, который полностью отличается от большинства других, и именно поэтому я люблю его, но он также включает в себя несколько компромиссов, о которых вы должны знать заранее.

Ваш пример похож на CMS или веб-приложение для обмена, и есть сотни готовых приложений, которые будут отлично работать на Apache. Даже если вам не нравится какое-либо готовое решение, вы можете написать веб-приложение на PHP / Java / Python или смешать и сопоставить его с парой готовых приложений, и все они разработаны и поддерживаются для работы за одним экземпляром Apache.

Пришло время остановиться и подумать о том, что я только что сказал.

Теперь вы готовы решить, какой стэк вы собираетесь использовать. Если на вашем веб-сайте никогда не будут использоваться какие-либо из тысяч готовых приложений, для которых требуется Apache, то перейдите к Node, в противном случае вы должны сначала устранить предположения, которые я высказал ранее.

В конце концов, ваш выбор techstack гораздо важнее, чем любой отдельный компонент.

Я полностью согласен с @Straseus в том, что относительно просто использовать api файловой системы node.js для обработки загрузок и загрузок, но подумайте о том, что вы хотите от своего веб-сайта в долгосрочной перспективе, а затем выберите свой технический стэк.

Изучение структуры Node проще, чем изучение других структур, но это не панацея. Приложив немного больше усилий (что само по себе может быть полезным), вы также можете изучить любую другую среду. Мы все учимся друг у друга, и вы будете более продуктивными, если будете работать небольшой командой, чем если вы работаете в одиночку, и ваши технические навыки бэкэнда также будут развиваться быстрее. Поэтому не стоит сбрасывать со счетов навыки других членов вашей команды так дешево.

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

Спасибо за чтение.

RHT
источник