Apache et Node.js sur le même serveur

352

Je veux utiliser Node car il est rapide, utilise le même langage que j'utilise du côté client, et il n'est pas bloquant par définition. Mais le gars que j'ai embauché pour écrire le programme de gestion des fichiers (sauvegarde, édition, renommage, téléchargement, téléchargement de fichiers, etc.), il veut utiliser apache. Je dois donc:

  1. Le convaincre d'utiliser Node (il abandonne peu de terrain là-dessus)

  2. Découvrez comment télécharger, télécharger, renommer, enregistrer, etc. des fichiers dans un nœud ou

  3. Je dois installer apache et node sur le même serveur.

Quelle est la situation la plus favorable et comment puis-je la mettre en œuvre?

Mat
la source

Réponses:

704

Grande question!

Il existe de nombreux sites Web et applications Web gratuites implémentés en PHP qui fonctionnent sur Apache, beaucoup de gens l'utilisent pour que vous puissiez créer quelque chose d'assez facile et en plus, c'est une façon simple de servir du contenu statique. Node est rapide, puissant, élégant et un outil sexy avec la puissance brute du V8 et une pile plate sans dépendances intégrées.

Je veux aussi la facilité / flexibilité d'Apache et pourtant le grognement et l'élégance de Node.JS, pourquoi ne puis-je pas avoir les deux ?

Heureusement, avec la directive ProxyPass dans Apache, httpd.confil n'est pas trop difficile de diriger toutes les demandes d'une URL particulière vers votre application Node.JS.

ProxyPass /node http://localhost:8000

Assurez-vous également que les lignes suivantes ne sont PAS mises en commentaire afin que vous obteniez le bon proxy et le sous-module pour rediriger les requêtes http:

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

Exécutez ensuite votre application Node sur le port 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');

Ensuite, vous pouvez accéder à toute la logique Node.JS en utilisant le /node/chemin sur votre URL, le reste du site Web peut être laissé à Apache pour héberger vos pages PHP existantes:

entrez la description de l'image ici

Maintenant, il ne reste plus qu'à convaincre votre hébergeur de laisser courir avec cette configuration !!!

Steven de Salas
la source
6
C'était une excellente réponse, je voulais juste ajouter un lien avec un peu plus d'informations sur le proxy pass que j'ai utilisé pour faire ce travail. Vérifiez également les commentaires. boriskuzmanovic.wordpress.com/2006/10/20/…
Alex Muro
11
J'ai testé mettre "ProxyPass / 127.0.0.1:8000 " dans un conteneur d'hôte virtuel et j'ai réussi à rediriger un groupe de domaine entier vers une instance de nœud. J'ai également testé avec "time wget ..." pour comparer la vitesse d'accès au nœud directement à l'accès via Apache. Dans 30 paires d'essais, la différence moyenne était d'environ 0,56 ms. Le temps de chargement le plus bas était de 120 ms, à la fois directement et via Apache. Le temps de chargement le plus élevé était de 154 ms en direct et de 164 via Apache. Pas une différence significative. Si j'avais le luxe de deux adresses IP, je ne passerais pas par Apache, mais pour l'instant je m'en tiendrai à Proxypass
kaan_a
5
Ce proxy ne demande-t-il pas d'Apache à Node, alors qu'il enlève les avantages de la nature non bloquante de Node?
Trace
2
Salut @Basj, je n'ai aucune expérience de l'installation du support pour les websockets moi-même. Cela dit, Apache 2.4.6 semble prendre en charge le proxy de trafic Websockets à l'aide de mod_proxy_wstunnel. Je vois que vous avez maintenant trouvé votre réponse, pour les autres personnes ayant le même problème, veuillez consulter: serverfault.com/questions/616370/…
Steven de Salas
4
Où dois-je ajouter ceci sur les distributions basées sur Debian? Il n'y a pas de fichier httpd.conf.
santi
63

Cette question appartient plus à Server Fault mais FWIW Je dirais que l'exécution d'Apache devant Node.js n'est pas une bonne approche dans la plupart des cas.

Le ProxyPass d'Apache est génial pour beaucoup de choses (comme exposer des services basés sur Tomcat dans le cadre d'un site) et si votre application Node.js ne fait qu'un petit rôle spécifique ou est un outil interne qui ne devrait avoir qu'un nombre limité d'utilisateurs alors il pourrait être plus facile de simplement l'utiliser pour que vous puissiez le faire fonctionner et continuer, mais cela ne ressemble pas au cas ici.

Si vous souhaitez profiter des performances et de l'échelle que vous obtiendrez en utilisant Node.js - et surtout si vous souhaitez utiliser quelque chose qui implique de maintenir une connexion persistante comme les sockets Web - vous feriez mieux d'exécuter Apache et votre nœud. js sur d'autres ports (par exemple Apache sur localhost: 8080, Node.js sur localhost: 3000), puis exécutez quelque chose comme nginx, Varnish ou proxy HA en avant - et acheminez le trafic de cette façon.

Avec quelque chose comme vernis ou nginx, vous pouvez acheminer le trafic en fonction du chemin et / ou de l'hôte. Ils utilisent tous deux beaucoup moins de ressources système et sont beaucoup plus évolutifs que l'utilisation d'Apache pour faire la même chose.

Iain Collins
la source
13
cette réponse devrait avoir plus de votes positifs. il est nettement préférable d'utiliser le proxy nginx qu'apache one.
retravailler le
Ya mais il est gourmand en ressources
L'Oracle
1
Avez-vous des chiffres pour confirmer votre affirmation selon laquelle nginx consomme moins de ressources que httpd?
RedShift
Je ne pense pas que ce soit assez dramatique. Bien que j'essaie de ne pas créer de liens dans les réponses, car les liens sont fragiles, mais vous pouvez trouver des discussions et des exemples via Google - par exemple help.dreamhost.com/hc/en-us/articles/…… Apache est un excellent logiciel, mais généralement ce n'est pas un grande approche dans un contexte comme celui-ci.
Iain Collins
Cette réponse semble bonne, mais alors comment accéder à Node.js via httpS car il est déjà pris par Apache?
Pierre
34


Instructions à node serversuivre apache2(v2.4.xx) server:

Pour acheminer toutes les demandes d'une URL particulière vers votre application Node.JS, créez le CUSTOM.conffichier dans le /etc/apache2/conf-availablerépertoire et ajoutez la ligne suivante au fichier créé:

ProxyPass /node http://localhost:8000/

Remplacez 8000 par le numéro de port préféré pour node server.
Activez les configurations personnalisées avec la commande suivante:

$> sudo a2enconf CUSTOM

CUSTOM est votre nom de fichier nouvellement créé sans extension, puis activez proxy_httpavec la commande:

$> sudo a2enmod proxy_http

il doit activer les modules proxyet proxy_http. Vous pouvez vérifier si le module est activé ou non avec:

$> sudo a2query -m MODULE_NAME

Une fois la configuration et les modules activés, vous devrez redémarrer le serveur apache:

$> sudo service apache2 restart

Vous pouvez maintenant exécuter le serveur de nœuds. Toutes les demandes au URL/nodeseront traitées par le serveur de noeud.

krmld
la source
Fonctionne comme un charme! :)
Kees Koenen
15

L'exécution de Node et Apache sur un serveur est triviale car elles n'entrent pas en conflit. NodeJS est juste un moyen d'exécuter côté serveur JavaScript. Le vrai dilemme vient de l'accès à Node et Apache de l'extérieur. Selon moi, vous avez deux choix:

  1. Configurez Apache pour proxy toutes les demandes correspondantes vers NodeJS, qui effectuera le téléchargement des fichiers et tout ce qui se trouve dans le nœud.

  2. Avoir Apache et Node sur différentes combinaisons IP: ports (si votre serveur a deux IP, alors l'un peut être lié à votre écouteur de nœud, l'autre à Apache).

Je commence également à soupçonner que ce n'est peut-être pas ce que vous recherchez. Si votre objectif final est que vous écriviez votre logique d'application dans Nodejs et une partie de la «gestion de fichiers» que vous déchargiez vers un entrepreneur, alors c'est vraiment un choix de langue, pas un serveur Web.

Yarek T
la source
9

Vous pouvez utiliser une approche différente telle que l'écriture d'un serveur proxy inverse avec nodejs pour proxy à la fois apache et toutes les autres applications nodejs.

Vous devez d'abord exécuter apache sur un autre port que le port 80. ex: port 8080

Ensuite, vous pouvez écrire un script de proxy inverse avec nodejs comme:

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'article suivant décrit l'ensemble du processus de fabrication.

RUN APACHE AVEC NODE JS REVERSE PROXY - UTILISATION DE REDBIRD

wathmal
la source
2
ProxyPass /node http://localhost:8000/     
  • cela a fonctionné pour moi quand j'ai fait l'entrée ci-dessus dans httpd-vhosts.conf au lieu de httpd.conf
  • J'ai installé XAMPP sur mon environnement et cherchais à frapper tout le trafic sur apache sur le port 80 avec l'applicatin NodeJS fonctionnant sur le port 8080, à savoir http: // localhost / [name_of_the_node_application]
rahul shukla
la source
1

J'ai combiné la réponse ci-dessus avec certbot SSL cert et CORS access-control-allow-headers et je l'ai fait fonctionner, alors j'ai pensé partager les résultats.

Apache httpd.conf ajouté au bas du fichier:

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

Paramètres Apache VirtualHost (la racine du document pour PHP est sous Apache et SSL avec Certbot, tandis que le site node.js / socket.io s'exécute sur le port 3000 - et utilise le certificat SSL d'Apache) Notez également que le site node.js utilise le proxy pour le dossier / nodejs, socket.io et 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>

Ensuite, mon application 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});

Je force un écouteur ip4, mais c'est facultatif - vous pouvez remplacer:

http.listen(3000);

Le code de l'application node.js (app.js) se poursuit avec:

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

enfin, côté client (créé en tant que 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'
});

Dans cet exemple, lorsque le JS se charge, il émet vers le socket un "événement nommé" envoyant les données en JSON au serveur node.js / socket.io.

À l'aide de l'io et du socket sur le serveur sous path / nodejs (connecté par le client), reçoit les données et les renvoie en tant que diffusion. Tous les autres utilisateurs du socket recevraient les données avec leur écouteur "named-event-broadcast". Notez que l'expéditeur ne reçoit pas sa propre émission.

Dr. Aaron Dishno
la source
0

J'ai récemment rencontré ce problème, où je dois communiquer entre le client et le serveur à l'aide de websocket dans un projet de codeigniter basé sur PHP.

J'ai résolu ce problème en ajoutant mon port (application de nœud exécutée sur) dans les listes Allow incoming TCP ports& Allow outgoing TCP ports.

Vous pouvez trouver ces configurations dans Firewall Configurationsle panneau WHM de votre serveur.

Paritosh Pandey
la source
-1

Je cherchais les mêmes informations. Enfin trouvé la réponse à partir du lien sur la réponse ci-dessus par @Straseus

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

Voici la solution finale pour exécuter le site Web apache sur le port 80, le service node js sur le port 8080 et utiliser .htaccess RewriteRule

Dans DocumentRoot du site Web Apache, ajoutez ce qui suit:

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]

Pour la redirection au niveau du répertoire, le lien ci-dessus suggère la règle (. +), Qui nécessite un ou plusieurs caractères après le 'nœud /'. J'ai dû le convertir en (. *) Qui est zéro ou plus pour que mes affaires fonctionnent.

Merci beaucoup pour le lien @Straseus

pd1980
la source
3
Notez simplement que le drapeau [P] nécessite l'activation d'Apache mod_proxy.
Simon East
C'est inefficace. Pourquoi invoquer le moteur de réécriture sur un simple ProxyPass?
Michael Irigoyen du
-2

Je suppose que vous créez une application Web car vous faites référence à Apache et Node. Réponse rapide - Est-ce possible - OUI. Est-il recommandé - NON. Node regroupe son propre serveur Web et la plupart des sites Web fonctionnent sur le port 80. Je suppose également qu'il n'y a actuellement aucun plugin Apache pris en charge par Nodejs et je ne suis pas sûr que la création d'un hôte virtuel soit la meilleure façon de l'implémenter. Ce sont les questions auxquelles les développeurs qui maintiennent Nodejs comme les bons employés de Joyent devraient répondre.

Au lieu de ports, il serait préférable d'évaluer la pile technologique de Node qui est complètement différente de la plupart des autres et c'est pourquoi je l'adore, mais cela implique également quelques compromis que vous devez connaître à l'avance.

Votre exemple ressemble à un CMS ou à une application Web de partage et il existe des centaines d'applications prêtes à l'emploi qui fonctionneront très bien sur Apache. Même si vous n'aimez aucune solution prête à l'emploi, vous pouvez écrire une webapp en PHP / Java / Python ou la mélanger avec quelques applications prêtes à l'emploi et elles sont toutes conçues et prises en charge pour fonctionner derrière une seule instance d'Apache.

Il est temps de faire une pause et de réfléchir à ce que je viens de dire.

Vous êtes maintenant prêt à décider de la technologie que vous allez utiliser. Si votre site Web n'utilisera jamais l'une des milliers d'applications prêtes à l'emploi qui nécessitent Apache, optez pour Node, sinon vous devez d'abord éliminer les hypothèses que j'ai énoncées précédemment.

Au final, votre choix de techstack est bien plus important que n'importe quel composant individuel.

Je suis entièrement d'accord avec @Straseus qu'il est relativement trivial d'utiliser l'api du système de fichiers node.js pour gérer les téléchargements et les téléchargements, mais réfléchissez davantage à ce que vous voulez de votre site Web à long terme, puis choisissez votre techstack.

L'apprentissage du framework de Node est plus facile que l'apprentissage d'autres frameworks mais ce n'est pas une panacée. Avec un peu plus d'efforts (ce qui peut être un effort intéressant en soi), vous pouvez également apprendre tout autre cadre. Nous apprenons tous les uns des autres et vous serez plus productif si vous travaillez en petite équipe que si vous travaillez seul et vos compétences techniques backend se développeront également plus rapidement. Par conséquent, ne négligez pas les compétences des autres membres de votre équipe à un prix aussi avantageux.

Ce message a environ un an et il est probable que vous ayez déjà décidé, mais j'espère que ma diatribe aidera la prochaine personne qui traverse une décision similaire.

Merci d'avoir lu.

RHT
la source