Apache та Node.js на одному сервері


352

Я хочу використовувати Node, оскільки він швидкий, використовує ту саму мову, яку я використовую на стороні клієнта, і це не блокує за визначенням. Але хлопець, якого я найняв, щоб написати програму для обробки файлів (збереження, редагування, перейменування, завантаження, завантаження файлів тощо), він хоче використовувати апаш. Отже, я повинен:

  1. Переконайте його в застосуванні Node (він на цьому мало поступається)

  2. З'ясуйте, як завантажувати, завантажувати, перейменовувати, зберігати тощо файли у вузлі чи

  3. Я повинен встановити apache та вузол на одному сервері.

Яка ситуація є найбільш сприятливою, і як я це втілю?

Відповіді:


704

Чудове запитання!

У PHP існує багато веб-сайтів та безкоштовних веб-додатків, які працюють на Apache, багато людей використовують це, щоб ви могли розтопити щось досить просто, і до того ж, це не без розуму спосіб подачі статичного контенту. Вузол - швидкий, потужний, елегантний та сексуальний інструмент із сильною силою 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 " розміщується всередині віртуального хост-контейнера, і вдалося успішно перенаправити всю доменну групу до екземпляра вузла. Я також перевірив "wget ​​time ..." для порівняння швидкості доступу до вузла безпосередньо до доступу до нього через 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 у більшості випадків не є хорошим підходом.

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

Якщо ви хочете скористатись ефективністю та масштабом, який ви отримаєте за допомогою Node.js - і особливо, якщо ви хочете використовувати щось, що передбачає підтримання стійкого з'єднання, наприклад, веб-розетки - вам краще працювати як Apache, так і ваш Node. js на інших портах (наприклад, Apache на localhost: 8080, Node.js на localhost: 3000), а потім працює щось на кшталт nginx, Varnish або HA proxy попереду - і маршрутизує трафік таким чином.

За допомогою лаку або nginx ви можете маршрутизувати трафік на основі шляху та / або хоста. Вони обидва використовують набагато менше системних ресурсів і набагато масштабніші, ніж використання Apache для того ж самого.


13
ця відповідь повинна мати більше результатів. Однозначно набагато кращий підхід використовувати nginx проксі, ніж один.
реріх

Так, але це ресурсомістке
The 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волі будуть оброблятися сервером вузлів.


Працює як шарм! :)
Kees

15

Запуск Node та Apache на одному сервері тривіально, оскільки вони не конфліктують. NodeJS - це лише спосіб виконання JavaScript-сервера. Справжня дилема виникає з доступу до Вузла та 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");

Наступна стаття описує весь процес її виготовлення.

ЗАПУСНУЙТЕ АПАХ З НОДУ JS ОБОВ'ЯЗКОВИЙ ПРОКС - ВИКОРИСТОВУВАТИ КРАЩУ


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-контролем доступу-дозволів-заголовків, і я працював так, що я подумав, що поділюся результатами.

Apache httpd.conf додано внизу файлу:

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

Параметри Apache VirtualHost (корінь doc для 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 і socket на сервері під шлях / nodejs (підключений клієнтом), отримує дані, а потім надсилає їх як широкомовні. Будь-які інші користувачі в сокеті отримували б дані зі свого слухача "з назвою-подія-трансляція". Зауважте, що відправник не отримує власного мовлення.


0

Нещодавно я зіткнувся з цією проблемою, де мені потрібно спілкуватися між клієнтом і сервером за допомогою websocket в проекті кодового дизайну на основі 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 на апаші додайте наступне:

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]

Для переадресації рівня каталогів посилання вище пропонується (. +) Правило, яке вимагає одного або більше символів після 'вузла /'. Мені довелося перетворити його на (. *), Що дорівнює нулю або більше, щоб мої речі працювали.

Дякую за посилання @Straseus


3
Просто зауважте, що прапор [P] вимагає mod_proxyвключення Apache .
Саймон Іст

Це неефективно. Навіщо викликати движок Rewrite над простим ProxyPass?
Майкл Ірігойен

-2

Я припускаю, що ви робите веб-додаток, оскільки ви посилаєтесь на Apache та Node. Швидка відповідь - Чи можливо - ТАК. Чи рекомендується - НІ. Вузольні пакети - це власний веб-сервер, а більшість веб-сайтів працює на порту 80. Я також припускаю, що в даний час немає плагіна Apache, який підтримується Nodejs, і я не впевнений, що створення віртуальної хости є найкращим способом її реалізації. Це питання, на які слід відповісти розробникам, які підтримують Nodejs, як хороші люди в Joyent.

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

Ваш приклад схожий на CMS або веб-додаток для спільного використання, і є сотні доступних програм, які працюватимуть чудово на Apache. Навіть якщо вам не подобається якесь готове рішення, ви можете написати webapp в PHP / Java / Python або змішати n зіставити його з парою готових додатків, і всі вони розроблені та підтримуються, щоб працювати за одним екземпляром Apache.

Пора зробити паузу і подумати над тим, що я щойно сказав.

Тепер ви готові вирішити, який технологічний стек ви будете використовувати. Якщо ваш веб-сайт ніколи не використовує жодного з тисяч готових додатків, які потребують Apache, тоді перейдіть на Node, інакше вам слід спочатку усунути припущення, про які я вже говорив раніше.

Зрештою, ваш вибір технічного стека набагато важливіший, ніж будь-який окремий компонент.

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

Вивчити рамки Вузола простіше, ніж вивчити інші рамки, але це не панацея. Трохи доклавши більше зусиль (що, можливо, є вагомим починанням), ви також можете навчитися будь-яким іншим рамкам. Всі ми вчимося один у одного, і ви будете більш продуктивними, якщо працюєте в невеликій команді, ніж якщо ви працюєте в самоті, а ваші технічні навички також будуть розвиватися швидше. Тому не варто знижувати навички інших членів вашої команди так дешево.

Цій посаді близько року, і швидше за все, ви вже вирішили, але я сподіваюся, що мій рент допоможе наступній людині, яка переживає подібне рішення.

Дякуємо за прочитане

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.