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.