Apache und Node.js auf demselben Server


352

Ich möchte Node verwenden, weil es schnell ist, dieselbe Sprache verwendet, die ich auf der Clientseite verwende, und per Definition nicht blockiert. Aber der Typ, den ich beauftragt habe, das Programm für die Dateiverwaltung (Speichern, Bearbeiten, Umbenennen, Herunterladen, Hochladen von Dateien usw.) zu schreiben, möchte Apache verwenden. Also muss ich:

  1. Überzeugen Sie ihn, Node zu benutzen (er gibt wenig Grund dafür auf)

  2. Finden Sie heraus, wie Sie Dateien im Knoten oder hochladen, herunterladen, umbenennen, speichern usw. können

  3. Ich muss Apache und Node auf demselben Server installieren.

Welches ist die günstigste Situation und wie setze ich das um?

Antworten:


704

Gute Frage!

Es gibt viele Websites und kostenlose Web-Apps, die in PHP implementiert sind und auf Apache ausgeführt werden. Viele Leute verwenden es, damit Sie etwas ziemlich Einfaches zusammenstellen können. Außerdem ist es eine einfache Möglichkeit, statische Inhalte bereitzustellen. Node ist schnell, leistungsstark, elegant und ein sexy Tool mit der rohen Leistung von V8 und einem flachen Stack ohne eingebaute Abhängigkeiten.

Ich möchte auch die Leichtigkeit / Flexibilität von Apache und dennoch das Grunzen und die Eleganz von Node.JS. Warum kann ich nicht beides haben ?

Glücklicherweise ist es mit der ProxyPass- Direktive im Apache httpd.confnicht allzu schwierig, alle Anforderungen an eine bestimmte URL an Ihre Node.JS-Anwendung weiterzuleiten.

ProxyPass /node http://localhost:8000

Stellen Sie außerdem sicher, dass die folgenden Zeilen NICHT auskommentiert sind, damit Sie den richtigen Proxy und das richtige Submodul zum Umleiten von http-Anforderungen erhalten:

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

Führen Sie dann Ihre Node-App auf Port 8000 aus!

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

Anschließend können Sie über den /node/Pfad in Ihrer URL auf die gesamte Node.JS-Logik zugreifen. Der Rest der Website kann Apache überlassen werden, um Ihre vorhandenen PHP-Seiten zu hosten:

Geben Sie hier die Bildbeschreibung ein

Jetzt müssen Sie nur noch davon überzeugen, dass Ihr Hosting-Unternehmen Sie mit dieser Konfiguration laufen lässt !!!


6
Dies war eine großartige Antwort. Ich wollte nur einen Link mit ein wenig mehr Informationen zum Proxy-Pass hinzufügen, mit dem ich diese Funktion ausgeführt habe. Überprüfen Sie auch die Kommentare. boriskuzmanovic.wordpress.com/2006/10/20/…
Alex Muro

11
Ich habe getestet, wie "ProxyPass / 127.0.0.1:8000 " in einen virtuellen Host-Container eingefügt wird, und konnte eine gesamte Domänengruppe erfolgreich auf eine Knoteninstanz umleiten. Ich habe auch mit "time wget ..." getestet, um die Geschwindigkeit des direkten Zugriffs auf den Knoten mit dem Zugriff über Apache zu vergleichen. In 30 Versuchspaaren betrug der durchschnittliche Unterschied etwa 0,56 ms. Die niedrigste Ladezeit betrug 120 ms sowohl für direkt als auch über Apache. Die höchste Ladezeit betrug 154 ms für Direct und 164 ms für Apache. Kein signifikanter Unterschied. Wenn ich den Luxus von zwei IPs hätte, würde ich nicht durch Apache routen, aber jetzt bleibe ich bei Proxypass
kaan_a

5
Fordert dieser Proxy nicht von Apache an Node an, während er die Vorteile der nicht blockierenden Natur von Node beeinträchtigt?
Trace

2
Hallo @Basj, ich habe selbst keine Erfahrung mit der Installation von Support für Websockets. Trotzdem scheint Apache 2.4.6 Unterstützung für das Proxying von Websockets-Verkehr mit using zu haben mod_proxy_wstunnel. Ich sehe, Sie haben jetzt Ihre Antwort gefunden. Für andere mit demselben Problem siehe: serverfault.com/questions/616370/…
Steven de Salas

4
Wo füge ich dies bei Debian-basierten Distributionen hinzu? Es gibt keine httpd.conf-Datei.
Santi

63

Diese Frage gehört eher zu Server Fault, aber FWIW Ich würde sagen, dass das Ausführen von Apache vor Node.js in den meisten Fällen kein guter Ansatz ist.

Der ProxyPass von Apache eignet sich hervorragend für viele Dinge (z. B. das Bereitstellen von Tomcat-basierten Diensten als Teil einer Website) und wenn Ihre Node.js-App nur eine bestimmte, kleine Rolle spielt oder ein internes Tool ist, das wahrscheinlich nur eine begrenzte Anzahl von Benutzern hat dann ist es vielleicht einfacher, es einfach zu benutzen, damit Sie es zum Laufen bringen und weitermachen können, aber das klingt hier nicht so.

Wenn Sie die Leistung und Skalierbarkeit nutzen möchten, die Sie durch die Verwendung von Node.js erhalten - und insbesondere, wenn Sie eine dauerhafte Verbindung wie Web-Sockets aufrechterhalten möchten -, sollten Sie sowohl Apache als auch Ihren Node ausführen. js auf anderen Ports (z. B. Apache auf localhost: 8080, Node.js auf localhost: 3000) und dann etwas wie nginx, Varnish oder HA-Proxy vor sich ausführen - und den Verkehr auf diese Weise weiterleiten.

Mit etwas wie Lack oder Nginx können Sie den Verkehr basierend auf Pfad und / oder Host weiterleiten. Beide verbrauchen viel weniger Systemressourcen und sind viel skalierbarer als die Verwendung von Apache, um dasselbe zu tun.


13
Diese Antwort sollte mehr positive Stimmen haben. Es ist definitiv ein viel besserer Ansatz, Nginx-Proxy zu verwenden als Apache One.
Rerich

Ja, aber es ist ressourcenintensiv
Das Orakel

1
Haben Sie einige Zahlen, die Ihre Aussage stützen, dass Nginx weniger ressourcenintensiv als httpd wäre?
RedShift

Ich denke nicht, dass es ziemlich dramatisch ist. Ich versuche zwar, in Antworten keine Links zu erstellen , da Links fragil sind, aber Sie können einige Diskussionen und Beispiele über Google finden - z. B. help.dreamhost.com/hc/en-us/articles/…… Apache ist eine großartige Software, aber normalerweise keine Toller Ansatz in einem solchen Kontext.
Iain Collins

Diese Antwort klingt gut, aber wie kann man dann über httpS auf Node.js zugreifen, da es bereits von Apache übernommen wurde?
Pierre

34


Anweisungen zu laufen node serverentlang apache2(v2.4.xx) server:

Um Rohr alle Anfragen auf einer bestimmte URL zu Ihrer Node.JS Anwendung erstellen CUSTOM.confDatei im /etc/apache2/conf-availableVerzeichnis, und fügen Sie die erstellten Datei folgende Zeile:

ProxyPass /node http://localhost:8000/

Ändern Sie 8000 in die bevorzugte Portnummer für node server.
Aktivieren Sie benutzerdefinierte Konfigurationen mit folgendem Befehl:

$> sudo a2enconf CUSTOM

CUSTOM ist Ihr neu erstellter Dateiname ohne Erweiterung. Aktivieren Sie ihn dann proxy_httpmit dem folgenden Befehl:

$> sudo a2enmod proxy_http

es sollte sowohl proxyals auch proxy_httpModule aktivieren . Sie können überprüfen, ob das Modul aktiviert ist oder nicht mit:

$> sudo a2query -m MODULE_NAME

Nachdem Konfiguration und Module aktiviert wurden, müssen Sie den Apache-Server neu starten:

$> sudo service apache2 restart

Jetzt können Sie den Knotenserver ausführen. Alle Anfragen an URL/nodewerden vom Knotenserver bearbeitet.


Klappt wunderbar! :)
Kees Koenen

15

Das Ausführen von Node und Apache auf einem Server ist trivial, da sie keine Konflikte verursachen. NodeJS ist nur eine Möglichkeit, die JavaScript-Serverseite auszuführen. Das eigentliche Dilemma besteht darin, von außen auf Node und Apache zuzugreifen. Aus meiner Sicht haben Sie zwei Möglichkeiten:

  1. Richten Sie Apache so ein, dass alle übereinstimmenden Anforderungen an NodeJS weitergeleitet werden, wodurch die Datei hochgeladen wird und was auch immer im Knoten vorhanden ist.

  2. Haben Sie Apache und Node auf unterschiedlichen IP: Port-Kombinationen (wenn Ihr Server zwei IPs hat, kann eine an Ihren Node Listener gebunden sein, die andere an Apache).

Ich fange auch an zu vermuten, dass dies möglicherweise nicht das ist, wonach Sie tatsächlich suchen. Wenn Ihr Endziel darin besteht, dass Sie Ihre Anwendungslogik in Nodejs und einen Teil der "Dateiverwaltung" schreiben, den Sie an einen Auftragnehmer abladen, dann ist es wirklich eine Wahl der Sprache, kein Webserver.


9

Sie können einen anderen Ansatz verwenden, z. B. das Schreiben eines Reverse-Proxy-Servers mit NodeJS, um sowohl Apache- als auch alle anderen NodeJS-Apps zu vertreten.

Zuerst müssen Sie Apache auf einem anderen Port als Port 80 ausführen lassen. Beispiel: Port 8080

Anschließend können Sie ein Reverse-Proxy-Skript mit nodejs wie folgt schreiben:

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

Der folgende Artikel beschreibt den gesamten Herstellungsprozess.

RUN APACHE MIT NODE JS REVERSE PROXY - MIT REDBIRD


2
ProxyPass /node http://localhost:8000/     
  • Dies funktionierte für mich, als ich den obigen Eintrag in httpd-vhosts.conf anstelle von httpd.conf vorgenommen habe
  • Ich habe XAMPP über meine Umgebung installiert und wollte den gesamten Datenverkehr bei Apache auf Port 80 mit NodeJS-Anwendung auf 8080-Port abrufen, dh http: // localhost / [name_of_the_node_application].

1

Ich habe die obige Antwort mit Certbot-SSL-Zertifikaten und CORS-Headern für die Zugriffskontrolle kombiniert und sie zum Laufen gebracht, sodass ich dachte, ich würde die Ergebnisse teilen.

Apache httpd.conf am Ende der Datei hinzugefügt:

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

Apache VirtualHost-Einstellungen (doc root für PHP befindet sich unter Apache und SSL mit Certbot, während die Site node.js / socket.io auf Port 3000 ausgeführt wird - und das SSL-Zertifikat von Apache verwendet). Beachten Sie auch, dass die Site node.js den Proxy für den Ordner verwendet / nodejs, socket.io und 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>

Dann meine node.js App (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});

Ich erzwinge einen IP4-Listener, aber das ist optional - Sie können ersetzen:

http.listen(3000);

Der App-Code von node.js (app.js) wird fortgesetzt mit:

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

Schließlich auf der Clientseite (erstellt als 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'
});

In diesem Beispiel sendet der JS beim Laden ein "Named-Event" an den Socket, das die Daten in JSON an den Server node.js / socket.io sendet.

Empfängt die Daten unter Verwendung von io und Socket auf dem Server unter path / nodejs (vom Client verbunden) und sendet sie dann erneut als Broadcast. Alle anderen Benutzer im Socket würden die Daten mit ihrem Listener "Named-Event-Broadcast" empfangen. Beachten Sie, dass der Absender keine eigene Sendung empfängt.


0

Ich bin kürzlich auf dieses Problem gestoßen, bei dem ich mithilfe von Websocket in einem PHP-basierten Codeigniter-Projekt zwischen Client und Server kommunizieren muss.

Ich habe dieses Problem behoben, indem ich meinen Port (auf dem die Knoten-App ausgeführt wird) zu Allow incoming TCP ports& Allow outgoing TCP portslist hinzugefügt habe .

Sie finden diese Konfigurationen im Firewall ConfigurationsWHM-Bereich Ihres Servers.


-1

Ich suchte nach den gleichen Informationen. Schließlich fand die Antwort von dem Link auf die Antwort oben von @Straseus

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

Hier ist die endgültige Lösung, um die Apache-Website auf Port 80, den Knoten-JS-Dienst auf Port 8080 auszuführen und .htaccess RewriteRule zu verwenden

Fügen Sie im DocumentRoot der Apache-Website Folgendes hinzu:

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]

Für die Umleitung auf Verzeichnisebene schlug der Link oben die (. +) Regel vor, die ein oder mehrere Zeichen nach dem 'Knoten /' erfordert. Ich musste es in (. *) Konvertieren, was null oder mehr ist, damit meine Sachen funktionieren.

Vielen Dank für den Link @Straseus


3
Beachten Sie nur, dass für das [P] -Flag Apache mod_proxyaktiviert sein muss.
Simon East

Das ist ineffizient. Warum die Rewrite-Engine über eine einfache Version aufrufen ProxyPass?
Michael Irigoyen

-2

Ich gehe davon aus, dass Sie eine Web-App erstellen, weil Sie sich auf Apache und Node beziehen. Schnelle Antwort - Ist es möglich - JA. Wird es empfohlen - NEIN. Node bündelt seinen eigenen Webserver und die meisten Websites laufen auf Port 80. Ich gehe auch davon aus, dass es derzeit kein Apache-Plugin gibt, das von Nodejs unterstützt wird, und ich bin nicht sicher, ob das Erstellen eines virtuellen Hosts der beste Weg ist, dies zu implementieren. Dies sind die Fragen, die von Entwicklern beantwortet werden sollten, die Nodejs wie die guten Leute bei Joyent pflegen.

Anstelle von Ports ist es besser, den Tech-Stack von Node zu bewerten, der sich von den meisten anderen völlig unterscheidet. Deshalb liebe ich ihn, aber er beinhaltet auch einige Kompromisse, die Sie im Voraus kennen sollten.

Ihr Beispiel ähnelt einem CMS oder einer Freigabe-Webanwendung, und es stehen Hunderte von sofort einsatzbereiten Apps zur Verfügung, die unter Apache problemlos ausgeführt werden können. Selbst wenn Sie keine vorgefertigte Lösung mögen, können Sie eine Webanwendung in PHP / Java / Python schreiben oder sie mit einigen vorgefertigten Apps kombinieren, die alle so konzipiert und unterstützt werden, dass sie hinter einer einzelnen Instanz von Apache ausgeführt werden.

Es ist Zeit innezuhalten und darüber nachzudenken, was ich gerade gesagt habe.

Jetzt können Sie entscheiden, welchen Techstack Sie verwenden möchten. Wenn Ihre Website niemals eine der Tausenden von vorgefertigten Apps verwendet, für die Apache erforderlich ist, wählen Sie Node. Andernfalls müssen Sie zuerst die zuvor genannten Annahmen beseitigen.

Am Ende ist Ihre Wahl des Techstacks viel wichtiger als jede einzelne Komponente.

Ich stimme @Straseus voll und ganz zu, dass es relativ trivial ist, die Dateisystem-API von node.js für die Verarbeitung von Uploads und Downloads zu verwenden, aber überlegen Sie sich auf lange Sicht mehr, was Sie von Ihrer Website erwarten, und wählen Sie dann Ihren Techstack aus.

Das Lernen des Node-Frameworks ist einfacher als das Erlernen anderer Frameworks, aber kein Allheilmittel. Mit etwas mehr Aufwand (was an sich schon ein lohnendes Unterfangen sein kann) können Sie auch jedes andere Framework lernen. Wir alle lernen voneinander und Sie werden produktiver, wenn Sie als kleines Team arbeiten, als wenn Sie alleine arbeiten, und Ihre technischen Fähigkeiten im Backend werden sich auch schneller entwickeln. Reduzieren Sie daher die Fähigkeiten anderer Mitglieder Ihres Teams nicht so billig.

Dieser Beitrag ist ungefähr ein Jahr alt und es besteht die Möglichkeit, dass Sie sich bereits entschieden haben, aber ich hoffe, dass mein Schimpfen der nächsten Person hilft, die eine ähnliche Entscheidung trifft.

Danke fürs Lesen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.