Apache i Node.js na tym samym serwerze

352

Chcę użyć węzła, ponieważ jest szybki, używa tego samego języka, którego używam po stronie klienta i z definicji nie jest blokujący. Ale facet, którego zatrudniłem do napisania programu do obsługi plików (zapisywanie, edycja, zmiana nazwy, pobieranie, przesyłanie plików itp.), Chce używać apache. Więc muszę:

  1. Przekonaj go, aby używał Węzła (poświęca na tym niewiele miejsca)

  2. Dowiedz się, jak przesyłać, pobierać, zmieniać nazwy, zapisywać itp. Pliki w węźle lub

  3. Muszę zainstalować apache i węzeł na tym samym serwerze.

Która sytuacja jest najkorzystniejsza i jak ją wdrożyć?

Matt
źródło

Odpowiedzi:

704

Świetne pytanie!

Istnieje wiele stron internetowych i darmowych aplikacji internetowych zaimplementowanych w PHP, które działają na Apache, wiele osób korzysta z niego, dzięki czemu można zmiksować coś całkiem łatwego, a poza tym jest to bezproblemowy sposób dostarczania treści statycznych. Węzeł jest szybkim, potężnym, eleganckim i seksownym narzędziem o surowej mocy V8 i płaskim stosie bez wbudowanych zależności.

Chcę także łatwości / elastyczności Apache, a jednocześnie chrząknięcia i elegancji Node.JS, dlaczego nie mogę mieć obu ?

Na szczęście dzięki dyrektywie ProxyPass w Apache httpd.confprzesyłanie wszystkich żądań pod określonym adresem URL do aplikacji Node.JS nie jest zbyt trudne.

ProxyPass /node http://localhost:8000

Upewnij się również, że następujące wiersze NIE są komentowane, aby uzyskać odpowiedni serwer proxy i submoduł do przekierowywania żądań http:

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

Następnie uruchom aplikację Node na porcie 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');

Następnie możesz uzyskać dostęp do całej logiki Node.JS przy użyciu /node/ścieżki w adresie URL, resztę strony można pozostawić Apache, aby hostowała istniejące strony PHP:

wprowadź opis zdjęcia tutaj

Teraz jedyne, co pozostało, to przekonanie firmy hostingowej, aby pozwoliła Ci uruchomić tę konfigurację !!!

Steven de Salas
źródło
6
To była świetna odpowiedź, chciałem tylko dodać link z nieco więcej informacji na temat przepustki proxy, której użyłem, aby to zadziałało. Sprawdź również komentarze. boriskuzmanovic.wordpress.com/2006/10/20/20/…
Alex Muro
11
Przetestowałem umieszczenie „ProxyPass / 127.0.0.1:8000 ” w wirtualnym kontenerze hosta i udało mi się przekierować całą grupę domen do instancji węzła. Przetestowałem również za pomocą „wget czasowy ...”, aby porównać szybkość dostępu do węzła bezpośrednio do dostępu do niego przez Apache. W 30 parach prób średnia różnica wynosiła około 0,56 ms. Najniższy czas ładowania wynosił 120 ms zarówno dla bezpośredniego, jak i poprzez Apache. Najwyższy czas ładowania wyniósł 154ms dla bezpośredniego i 164 przez Apache. Nie znacząca różnica. Gdybym miał luksus dwóch adresów IP, nie przeszedłbym trasy przez Apache, ale na razie pozostanę przy Proxypassie
kaan_a
5
Czy ten serwer proxy nie wysyła żądań z Apache do węzła, podczas gdy odbiera korzyści z nieblokującej natury węzła?
Śledź
2
Cześć @Basj, sam nie mam doświadczenia w instalowaniu obsługi gniazd sieciowych. To powiedziawszy, Apache 2.4.6 wydaje się mieć wsparcie dla proxy ruchu z websockets przy użyciu mod_proxy_wstunnel. Widzę, że znalazłeś już swoją odpowiedź. W przypadku innych osób mających ten sam problem odwiedź stronę: serverfault.com/questions/616370/…
Steven de Salas,
4
Gdzie mogę to dodać w dystrybucjach opartych na Debianie? Nie ma pliku httpd.conf.
santi
63

To pytanie należy bardziej do błędu serwera, ale FWIW powiedziałbym, że uruchomienie Apache przed Node.js nie jest dobrym podejściem w większości przypadków.

ProxyPass firmy Apache jest niesamowity do wielu rzeczy (takich jak udostępnianie usług opartych na Tomcat jako część witryny) i jeśli twoja aplikacja Node.js wykonuje określoną, niewielką rolę lub jest narzędziem wewnętrznym, które może mieć tylko ograniczoną liczbę użytkowników wtedy może być łatwiej po prostu go użyć, abyś mógł go uruchomić i przejść dalej, ale to nie wygląda tak jak tutaj.

Jeśli chcesz skorzystać z wydajności i skali, jaką uzyskasz przy użyciu Node.js - a zwłaszcza jeśli chcesz użyć czegoś, co wymaga utrzymywania trwałego połączenia, takiego jak gniazda sieciowe - lepiej jest uruchomić zarówno Apache, jak i swój Węzeł. js na innych portach (np. Apache na localhost: 8080, Node.js na localhost: 3000), a następnie uruchamiając coś takiego jak nginx, Varnish lub HA proxy z przodu - i przekierowując ruch w ten sposób.

Za pomocą czegoś takiego jak lakier lub nginx możesz kierować ruchem na podstawie ścieżki i / lub hosta. Oba zużywają znacznie mniej zasobów systemowych i są znacznie bardziej skalowalne niż używanie Apache do tego samego.

Iain Collins
źródło
13
ta odpowiedź powinna mieć więcej głosów pozytywnych. zdecydowanie lepsze jest użycie proxy nginx niż apache.
ponownie
Tak, ale wymaga dużych zasobów
Wyrocznia
1
Czy masz jakieś liczby na poparcie swojego oświadczenia, że ​​nginx byłby mniej zasobochłonny niż httpd?
RedShift
Nie wydaje mi się, żeby to było dość dramatyczne. Chociaż staram się nie zamieszczać linków w odpowiedziach, ponieważ linki są delikatne, ale można znaleźć dyskusję i przykłady za pośrednictwem Google - np. Help.dreamhost.com/hc/en-us/articles/...… Apache to świetne oprogramowanie, ale zazwyczaj nie jest świetne podejście w takim kontekście.
Iain Collins,
Ta odpowiedź brzmi dobrze, ale jak uzyskać dostęp do Node.js przez httpS, ponieważ jest już zajęty przez Apache?
Pierre
34


Instrukcje do uruchomienia node serverwzdłuż apache2(v2.4.xx) server:

W celu rury wszystkie żądania dotyczące konkretnego adresu URL do aplikacji node.js utworzyć CUSTOM.confplik w /etc/apache2/conf-availablekatalogu i dodać następujący wiersz do utworzonego pliku:

ProxyPass /node http://localhost:8000/

Zmień 8000 na preferowany numer portu dla node server.
Włącz niestandardowe konfiguracje za pomocą następującego polecenia:

$> sudo a2enconf CUSTOM

CUSTOM to nowo utworzona nazwa pliku bez rozszerzenia, a następnie włącz proxy_httpza pomocą polecenia:

$> sudo a2enmod proxy_http

powinna umożliwić zarówno proxyi proxy_httpmodułów. Możesz sprawdzić, czy moduł jest włączony, czy nie:

$> sudo a2query -m MODULE_NAME

Po włączeniu konfiguracji i modułów konieczne będzie zrestartowanie serwera Apache:

$> sudo service apache2 restart

Teraz możesz uruchomić serwer węzła. Wszystkie żądania do URL/nodebędą obsługiwane przez serwer węzła.

krmld
źródło
Działa jak marzenie! :)
Kees Koenen
15

Uruchamianie Node i Apache na jednym serwerze jest banalne, ponieważ nie powodują konfliktów. NodeJS to tylko sposób na uruchomienie strony JavaScript. Prawdziwy dylemat wynika z dostępu zarówno do Węzła, jak i Apache z zewnątrz. Widzę, że masz dwie możliwości:

  1. Skonfiguruj Apache do proxy wszystkich pasujących żądań do NodeJS, które wykonają przesyłanie plików i cokolwiek innego w węźle.

  2. Posiadaj Apache i Węzeł na różnych kombinacjach adresów IP: port (jeśli twój serwer ma dwa adresy IP, jeden może być powiązany z odbiornikiem węzła, drugi z Apache).

Zaczynam też podejrzewać, że to może nie być to, czego tak naprawdę szukasz. Jeśli Twoim ostatecznym celem jest napisanie logiki aplikacji w Nodejs i części „obsługi plików”, którą odciążysz kontrahenta, to naprawdę jest to wybór języka, a nie serwer WWW.

Yarek T.
źródło
9

Możesz zastosować inne podejście, np. Napisać odwrotny serwer proxy z nodejs do proxy zarówno apache, jak i wszystkich innych aplikacji nodejs.

Najpierw musisz uruchomić apache na innym porcie niż port 80. np .: port 8080

Następnie możesz napisać skrypt odwrotnego proxy za pomocą nodejs jako:

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");

Poniższy artykuł opisuje cały proces tworzenia tego.

URUCHOM APACHE Z NODE JS PROXY ODWRÓCONY - ZA POMOCĄ REDBIRD

wathmal
źródło
2
ProxyPass /node http://localhost:8000/     
  • zadziałało to dla mnie, gdy zrobiłem powyższy wpis w httpd-vhosts.conf zamiast httpd.conf
  • Mam XAMPP zainstalowany w moim środowisku i chciałem trafić do całego ruchu w apache na porcie 80 z aplikacją NodeJS działającą na porcie 8080, tj. Http: // localhost / [nazwa_aplikacji_węzła]
Rahul Shukla
źródło
1

Połączyłem powyższą odpowiedź z certbot SSL cert i CORS kontrola dostępu-zezwól-nagłówki i sprawiłem, że działało, więc pomyślałem, że podzielę się wynikami.

Apache httpd.conf dodano na dole pliku:

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

Ustawienia VirtualHost Apache (katalog główny dla PHP znajduje się w Apache i SSL z Certbot, podczas gdy witryna node.js / socket.io działa na porcie 3000 - i używa certyfikatu SSL z Apache). Należy również zauważyć, że witryna node.js używa proxy dla folderu / nodejs, socket.io i 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>

Następnie moja aplikacja 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});

Wymuszam słuchanie ip4, ale jest to opcjonalne - możesz zastąpić:

http.listen(3000);

Kod aplikacji node.js (app.js) kontynuuje:

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...
});

wreszcie po stronie klienta (utworzony jako 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'
});

W tym przykładzie po załadowaniu JS wyśle ​​do gniazda „nazwane zdarzenie” wysyłające dane w JSON do serwera node.js / socket.io.

Używając io i socket na serwerze pod path / nodejs (połączonym przez klienta), odbiera dane, a następnie wysyła je ponownie jako transmisję. Każdy inny użytkownik w gnieździe odbierałby dane ze swoim odbiornikiem „named-event-broadcast”. Pamiętaj, że nadawca nie odbiera własnej transmisji.

Dr Aaron Dishno
źródło
0

Niedawno natknąłem się na ten problem, w którym muszę komunikować się między klientem a serwerem przy użyciu websocket w projekcie kodu opartego na PHP.

Rozwiązałem ten problem, dodając mój port (uruchomiona aplikacja węzła) do Allow incoming TCP ports& Allow outgoing TCP portslist.

Możesz znaleźć te konfiguracje w Firewall Configurationspanelu WHM swojego serwera.

Paritosh Pandey
źródło
-1

Szukałem tych samych informacji. W końcu znalazłem odpowiedź z linku na powyższej odpowiedzi autorstwa @Straseus

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

Oto ostatnie rozwiązanie do uruchomienia strony Apache na porcie 80, usługi węzła JS na porcie 8080 i użycia .htaccess RewriteRule

W DocumentRoot witryny apache dodaj następujące elementy:

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]

W przypadku przekierowania na poziomie katalogu powyższy link sugeruje regułę (. +), Która wymaga jednego lub więcej znaków po „węźle /”. Musiałem przekonwertować go na (. *), Który wynosi zero lub więcej, aby moje rzeczy działały.

Wielkie dzięki za link @Straseus

pd1980
źródło
3
Pamiętaj tylko, że flaga [P] wymaga mod_proxywłączenia Apache .
Simon East
To jest nieefektywne. Po co wywoływać silnik Rewrite w prosty sposób ProxyPass?
Michael Irigoyen,
-2

Zakładam, że tworzysz aplikację internetową, ponieważ odwołujesz się do Apache i Node. Szybka odpowiedź - Czy to możliwe - TAK. Czy to jest zalecane - NIE. Węzeł zawiera własny serwer WWW, a większość stron internetowych działa na porcie 80. Zakładam również, że obecnie nie ma wtyczki Apache obsługiwanej przez Nodejs i nie jestem pewien, czy stworzenie wirtualnego hosta jest najlepszym sposobem na wdrożenie tego. Na te pytania powinni odpowiedzieć programiści, którzy utrzymują Nodejsa jak dobrych ludzi w Joyent.

Zamiast portów lepiej byłoby ocenić stos technologiczny Node, który jest zupełnie inny niż większość innych i dlatego go uwielbiam, ale wymaga również kilku kompromisów, o których powinieneś wiedzieć wcześniej.

Twój przykład wygląda podobnie do CMS lub udostępniającej aplikacji internetowej. Istnieją setki gotowych aplikacji, które będą działać dobrze na Apache. Nawet jeśli nie podoba Ci się żadne gotowe rozwiązanie, możesz napisać aplikację internetową w PHP / Java / Python lub połączyć ją z kilkoma gotowymi aplikacjami, a wszystkie one są zaprojektowane i obsługiwane tak, aby działały za jedną instancją Apache.

Czas się zatrzymać i pomyśleć o tym, co właśnie powiedziałem.

Teraz możesz zdecydować, którego zestawu technologii będziesz używać. Jeśli Twoja witryna nigdy nie będzie używać żadnej z tysięcy gotowych aplikacji wymagających Apache, wybierz Node, w przeciwnym razie musisz najpierw wyeliminować założenia, które przedstawiłem wcześniej.

Ostatecznie wybór technologii stosu jest o wiele ważniejszy niż jakikolwiek pojedynczy element.

Całkowicie zgadzam się z @Straseus, że używanie interfejsu API systemu plików node.js do obsługi przesyłania i pobierania jest stosunkowo proste, ale na dłuższą metę pomyśl więcej o tym, czego chcesz od strony internetowej, a następnie wybierz swój pakiet technologii.

Uczenie się frameworka Node jest łatwiejsze niż uczenie się innych frameworków, ale nie jest to panaceum. Przy odrobinie wysiłku (co może być samo w sobie warte zachodu) możesz nauczyć się także innych ram. Wszyscy uczymy się od siebie i będziesz bardziej produktywny, jeśli pracujesz jako mały zespół, niż jeśli pracujesz sam, a umiejętności techniczne zaplecza również będą się rozwijać szybciej. Dlatego nie obniżaj tak tanio umiejętności innych członków swojego zespołu.

Ten post ma około roku i są szanse, że już zdecydowałeś, ale mam nadzieję, że mój rant pomoże kolejnej osobie, która podejmie podobną decyzję.

Dziękuje za przeczytanie.

RHT
źródło