Apache e Node.js sullo stesso server


352

Voglio usare Node perché è veloce, usa la stessa lingua che sto usando sul lato client ed è non bloccante per definizione. Ma il ragazzo che ho assunto per scrivere il programma per la gestione dei file (salvataggio, modifica, ridenominazione, download, caricamento di file, ecc.), Vuole usare apache. Quindi, devo:

  1. Convincilo a usare Node (sta rinunciando a questo)

  2. Scopri come caricare, scaricare, rinominare, salvare, ecc. File nel nodo o

  3. Devo installare apache e nodo sullo stesso server.

Qual è la situazione più favorevole e come posso attuarla?

Risposte:


704

Ottima domanda!

Ci sono molti siti Web e app Web gratuite implementate in PHP che girano su Apache, molte persone lo usano in modo da poter creare qualcosa di abbastanza semplice e, inoltre, è un modo semplicissimo di servire contenuti statici. Il nodo è veloce, potente, elegante e uno strumento sexy con la potenza pura del V8 e uno stack piatto senza dipendenze integrate.

Voglio anche la facilità / flessibilità di Apache e tuttavia il grugnito e l'eleganza di Node.JS, perché non posso avere entrambi ?

Fortunatamente con la direttiva ProxyPass in Apache httpd.confnon è troppo difficile reindirizzare tutte le richieste su un particolare URL all'applicazione Node.JS.

ProxyPass /node http://localhost:8000

Inoltre, assicurati che le seguenti righe NON siano commentate in modo da ottenere il proxy e il sottomodulo giusti per reindirizzare le richieste http:

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

Quindi esegui l'app Node sulla porta 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');

Quindi puoi accedere a tutta la logica di Node.JS usando il /node/percorso sul tuo URL, il resto del sito Web può essere lasciato ad Apache per ospitare le tue pagine PHP esistenti:

inserisci qui la descrizione dell'immagine

Ora l'unica cosa rimasta è convincere la tua società di hosting a correre con questa configurazione !!!


6
Questa è stata un'ottima risposta, volevo solo aggiungere un link con un po 'più di informazioni sul proxy pass che ho usato per farlo funzionare. Controlla anche i commenti. boriskuzmanovic.wordpress.com/2006/10/20/…
Alex Muro,

11
Ho provato a inserire "ProxyPass / 127.0.0.1:8000 " all'interno di un contenitore di host virtuale e sono stato in grado di reindirizzare correttamente un intero gruppo di domini a un'istanza di nodo. Ho anche provato con "time wget ..." per confrontare la velocità di accesso al nodo direttamente con l'accesso ad Apache. In 30 coppie di prove, la differenza media era di circa 0,56 ms. Il tempo di caricamento più basso è stato di 120 ms sia per Direct che tramite Apache. Il tempo di caricamento più elevato è stato di 154 ms per diretto e 164 tramite Apache. Nessuna differenza significativa. Se avessi il lusso di due IP non attraverserei Apache, ma per ora continuerò con Proxypass
kaan_a

5
Questo proxy non richiede da Apache a Node, mentre toglie i vantaggi della natura non bloccante di Node?
Traccia

2
Ciao @Basj, non ho esperienza di installazione del supporto per i websocket. Detto questo, Apache 2.4.6 sembra avere il supporto per il proxy del traffico dei websocket con l'utilizzo mod_proxy_wstunnel. Vedo che ora hai trovato la tua risposta, per gli altri con lo stesso problema, fai riferimento a: serverfault.com/questions/616370/…
Steven de Salas,

4
Dove lo aggiungo alle distribuzioni basate su debian? Non esiste un file httpd.conf.
santi,

63

Questa domanda appartiene più a Server Fault ma FWIW direi che eseguire Apache davanti a Node.js non è un buon approccio nella maggior parte dei casi.

ProxyPass di Apache è fantastico per molte cose (come esporre i servizi basati su Tomcat come parte di un sito) e se l'app Node.js sta solo svolgendo un ruolo specifico, piccolo o è uno strumento interno che probabilmente avrà solo un numero limitato di utenti allora potrebbe essere più semplice usarlo in modo da farlo funzionare e andare avanti, ma qui non sembra il caso.

Se vuoi sfruttare le prestazioni e le dimensioni che otterrai dall'utilizzo di Node.js - e soprattutto se vuoi usare qualcosa che comporta il mantenimento di una connessione persistente come i socket web - è meglio eseguire sia Apache che il tuo Node. js su altre porte (ad es. Apache su localhost: 8080, Node.js su localhost: 3000) e quindi eseguendo qualcosa come nginx, Varnish o proxy HA di fronte - e instradando il traffico in quel modo.

Con qualcosa come vernice o nginx è possibile instradare il traffico in base al percorso e / o all'host. Entrambi usano molto meno risorse di sistema ed è molto più scalabile rispetto all'utilizzo di Apache per fare la stessa cosa.


13
questa risposta dovrebbe avere più voti. è sicuramente un approccio molto migliore per usare il proxy nginx rispetto a quello di Apache.
riprova il

Sì, ma è ad alta intensità di risorse
Oracle

1
Hai dei numeri per sostenere la tua affermazione che nginx richiederebbe meno risorse rispetto a httpd?
RedShift

Non penso sia abbastanza drammatico. Mentre provo a non collegarmi nelle risposte poiché i collegamenti sono fragili ma puoi trovare alcune discussioni ed esempi tramite Google - ad esempio help.dreamhost.com/hc/en-us/articles/… ... Apache è un ottimo software ma in genere non è un ottimo approccio in un contesto come questo.
Iain Collins,

Questa risposta suona bene, ma allora come accedere a Node.js tramite httpS come è già preso da Apache?
Pierre,

34


Istruzioni per eseguire node serverinsieme apache2(v2.4.xx) server:

Per tubo tutte le richieste in un particolare URL all'applicazione Node.JS creare CUSTOM.conffile all'interno di /etc/apache2/conf-availabledirectory, e aggiungere la seguente riga al file creato:

ProxyPass /node http://localhost:8000/

Modificare 8000 con il numero di porta preferito per node server.
Abilita le configurazioni personalizzate con il seguente comando:

$> sudo a2enconf CUSTOM

CUSTOM è il tuo nome file appena creato senza estensione, quindi abilita proxy_httpcon il comando:

$> sudo a2enmod proxy_http

dovrebbe abilitare sia i moduli proxyche i proxy_httpmoduli. Puoi verificare se il modulo è abilitato o meno con:

$> sudo a2query -m MODULE_NAME

Dopo aver abilitato la configurazione e i moduli, dovrai riavviare il server apache:

$> sudo service apache2 restart

Ora puoi eseguire il nodo server. Tutte le richieste al URL/nodesaranno gestite dal server del nodo.


Funziona come un fascino! :)
Kees Koenen,

15

L'esecuzione di Node e Apache su un server è banale in quanto non sono in conflitto. NodeJS è solo un modo per eseguire il lato server JavaScript. Il vero dilemma deriva dall'accesso sia da Node che da Apache dall'esterno. A mio avviso, hai due possibilità:

  1. Configura Apache per inoltrare tutte le richieste corrispondenti a NodeJS, che eseguirà il caricamento del file e quant'altro nel nodo.

  2. Avere Apache e Nodo su IP diversi: combinazioni di porte (se il tuo server ha due IP, uno può essere associato al tuo listener di nodi, l'altro ad Apache).

Sto anche iniziando a sospettare che questo potrebbe non essere quello che stai effettivamente cercando. Se il tuo obiettivo finale è scrivere la logica dell'applicazione in Nodejs e alcune parti di "gestione dei file" che scarichi a un appaltatore, allora è davvero una scelta di lingua, non un web server.


9

Puoi utilizzare un approccio diverso come la scrittura di un server proxy inverso con nodejs per eseguire il proxy sia di Apache sia di tutte le altre app nodejs.

Per prima cosa devi far funzionare apache su una porta diversa dalla porta 80. es: porta 8080

Quindi puoi scrivere uno script proxy inverso con nodejs come:

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

L'articolo seguente descrive l'intero processo di realizzazione.

ESEGUI APACHE CON NODE JS REVERSE PROXY - UTILIZZANDO REDBIRD


2
ProxyPass /node http://localhost:8000/     
  • questo ha funzionato per me quando ho inserito la voce sopra in httpd-vhosts.conf anziché in httpd.conf
  • Ho XAMPP installato sul mio ambiente e stavo cercando di colpire tutto il traffico su apache sulla porta 80 con l'applicazione NodeJS in esecuzione sulla porta 8080, ad esempio http: // localhost / [nome_di_il_app_nodo]

1

Ho combinato la risposta sopra con certbot SSL cert e CORS access-control-allow-headers e l'ho fatta funzionare, quindi ho pensato di condividere i risultati.

Apache httpd.conf aggiunto nella parte inferiore del file:

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

Impostazioni di Apache VirtualHost (la root del documento per PHP è in Apache e SSL con Certbot, mentre il sito node.js / socket.io funziona sulla porta 3000 - e utilizza il certificato SSL da Apache) Si noti inoltre che il sito node.js utilizza il proxy per la cartella / nodejs, socket.io e ws (websocket):

<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>

Quindi la mia app 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});

Forzo un ascoltatore ip4, ma questo è facoltativo - puoi sostituire:

http.listen(3000);

Il codice dell'app node.js (app.js) continua con:

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

infine, sul lato client (creato come 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 questo esempio, quando viene caricato, JS emetterà al socket un "evento-nome" che invia i dati in JSON al server node.js / socket.io.

Utilizzando io e socket sul server in path / nodejs (connesso dal client), riceve i dati e li invia nuovamente come broadcast. Tutti gli altri utenti nel socket riceveranno i dati con il loro ascoltatore "nome-evento-trasmissione". Si noti che il mittente non riceve la propria trasmissione.


0

Di recente ho riscontrato questo tipo di problema, in cui ho bisogno di comunicare tra client e server utilizzando websocket in un progetto di codeigniter basato su PHP.

Ho risolto questo problema aggiungendo la mia porta (app nodo in esecuzione) in Allow incoming TCP ports&Allow outgoing TCP ports elenchi.

Puoi trovare queste configurazioni nel Firewall Configurationspannello WHM del tuo server.


-1

Stavo cercando le stesse informazioni. Finalmente ho trovato la risposta dal link sulla risposta sopra di @Straseus

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

Ecco la soluzione finale per eseguire il sito Web apache sulla porta 80, il servizio js del nodo sulla porta 8080 e utilizzare .htaccess RewriteRule

Nel DocumentRoot del sito Web apache, aggiungere quanto segue:

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]

Per il reindirizzamento a livello di directory, il link sopra suggerito ha suggerito la regola (. +), Che richiede uno o più caratteri dopo 'nodo /'. Ho dovuto convertirlo in (. *) Che è zero o più perché le mie cose funzionino.

Grazie mille per il link @Straseus


3
Basta notare che il flag [P] richiede che Apache mod_proxysia abilitato.
Simon East,

Questo è inefficiente. Perché invocare il motore di riscrittura su un semplice ProxyPass?
Michael Irigoyen,

-2

Presumo che tu stia creando un'app Web perché ti riferisci ad Apache e Node. Risposta rapida - È possibile - SÌ. È raccomandato - NO. Node raggruppa il proprio server web e la maggior parte dei siti Web funziona sulla porta 80. Suppongo anche che non ci sia attualmente un plug-in Apache supportato da Nodejs e non sono sicuro che la creazione di un host virtuale sia il modo migliore per implementarlo. Queste sono le domande a cui dovrebbero rispondere gli sviluppatori che mantengono Nodejs come i bravi ragazzi di Joyent.

Invece delle porte, sarebbe meglio valutare lo stack tecnologico di Node che è completamente diverso dalla maggior parte degli altri ed è per questo che lo adoro, ma comporta anche alcuni compromessi che dovresti conoscere in anticipo.

Il tuo esempio è simile a un CMS o a un'app Web di condivisione e ci sono centinaia di app disponibili che funzionano perfettamente su Apache. Anche se non ti piace alcuna soluzione readymade, potresti scrivere una webapp in PHP / Java / Python o combinarla con una coppia di app già pronte e sono tutte progettate e supportate per funzionare dietro un'unica istanza di Apache.

È tempo di mettere in pausa e pensare a quello che ho appena detto.

Ora sei pronto per decidere quale techstack utilizzerai. Se il tuo sito Web non utilizzerà mai nessuna delle migliaia di app già pronte che richiedono Apache, scegli Node, altrimenti devi prima eliminare le ipotesi che ho affermato in precedenza.

Alla fine, la tua scelta di Techstack è molto più importante di ogni singolo componente.

Concordo pienamente con @Straseus sul fatto che sia relativamente banale utilizzare l'API del file system node.js per gestire upload e download, ma pensa più a lungo a quello che vuoi dal tuo sito web e quindi scegli il tuo techstack.

L'apprendimento del framework Node è più semplice dell'apprendimento di altri framework ma non è una panacea. Con uno sforzo leggermente maggiore (che può essere uno sforzo utile in sé), puoi imparare anche qualsiasi altro framework. Impariamo tutti l'uno dall'altro e sarai più produttivo se lavori in gruppo piuttosto che se lavori da solo e anche le tue abilità tecniche di backend si svilupperanno più velocemente. Pertanto, non scartare le competenze degli altri membri della tua squadra in modo economico.

Questo post ha circa un anno e è probabile che tu l'abbia già deciso, ma spero che il mio rant aiuti la persona successiva che sta prendendo una decisione simile.

Grazie per aver letto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.