Apache e Node.js no mesmo servidor


352

Eu quero usar o Node porque é rápido, usa o mesmo idioma que estou usando no lado do cliente e não é bloqueador por definição. Mas o cara que eu contratei para escrever o programa para manipulação de arquivos (salvar, editar, renomear, baixar, fazer upload de arquivos etc.), ele quer usar o apache. Então, eu devo:

  1. Convencê-lo a usar o Node (ele está desistindo pouco disso)

  2. Descubra como fazer upload, download, renomear, salvar etc. arquivos no nó ou

  3. Eu devo instalar o apache e o nó no mesmo servidor.

Qual é a situação mais favorável e como implemento isso?

Respostas:


704

Ótima pergunta!

Existem muitos sites e aplicativos da web gratuitos implementados em PHP que rodam no Apache, muitas pessoas o usam para que você possa misturar algo bem fácil e, além disso, é uma maneira fácil de exibir conteúdo estático. O Node é rápido, poderoso, elegante e uma ferramenta sexy com o poder bruto do V8 e uma pilha plana sem dependências embutidas.

Também quero a facilidade / flexibilidade do Apache e ainda o grunhido e a elegância do Node.JS, por que não posso ter os dois ?

Felizmente, com a diretiva ProxyPass no Apache, httpd.confnão é muito difícil canalizar todas as solicitações em uma URL específica para o aplicativo Node.JS.

ProxyPass /node http://localhost:8000

Além disso, verifique se as seguintes linhas NÃO estão comentadas para obter o proxy e o submódulo corretos para redirecionar as solicitações http:

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

Em seguida, execute o aplicativo Node na 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');

Em seguida, você pode acessar toda a lógica do Node.JS usando o /node/caminho no seu URL, o restante do site pode ser deixado para o Apache para hospedar suas páginas PHP existentes:

insira a descrição da imagem aqui

Agora, a única coisa que resta é convencer a sua empresa de hospedagem a correr com essa configuração !!!


6
Esta foi uma ótima resposta, só queria adicionar um link com um pouco mais de informações sobre o passe de proxy que eu costumava fazer com que isso funcionasse. Verifique os comentários também. boriskuzmanovic.wordpress.com/2006/10/20/...
Alex Muro

11
Eu testei colocando "ProxyPass / 127.0.0.1:8000 " dentro de um contêiner de host virtual e consegui redirecionar com êxito um grupo de domínio inteiro para uma instância de nó. Também testei com o "time wget ..." para comparar a velocidade do nó de acesso diretamente com o Apache. Em 30 pares de ensaios, a diferença média foi de cerca de 0,56 ms. O tempo de carregamento mais baixo foi de 120 ms, tanto direto quanto via Apache. O tempo de carregamento mais alto foi de 154ms para direto e 164 via Apache. Não é uma diferença significativa. Se eu tive o luxo de dois IPs eu não iria rota através Apache, mas por enquanto vou ficar com ProxyPass
kaan_a

5
Esse proxy não solicita do Apache para o Node, enquanto tira os benefícios da natureza não-bloqueante do Node?
Rastreio

2
Oi @Basj, Eu não tenho experiência em instalar suporte para websockets eu mesmo. Dito isto, o Apache 2.4.6 parece ter suporte para proxy de tráfego de soquetes da web com o uso mod_proxy_wstunnel. Vejo que já encontraram sua resposta, para os outros com o mesmo problema, por favor consulte: serverfault.com/questions/616370/...
Steven de Salas

4
Onde eu adiciono isso em distribuições baseadas em debian? Não há arquivo httpd.conf.
santi

63

Esta questão pertence mais à falha do servidor, mas o FWIW diria que executar o Apache na frente do Node.js não é uma boa abordagem na maioria dos casos.

O ProxyPass do Apache é incrível para muitas coisas (como expor serviços baseados no Tomcat como parte de um site) e se o seu aplicativo Node.js. está apenas desempenhando uma função pequena e específica ou é uma ferramenta interna com probabilidade de ter um número limitado de usuários pode ser mais fácil usá-lo para que você possa trabalhar e seguir em frente, mas isso não parece o caso aqui.

Se você quiser tirar proveito do desempenho e da escala, poderá usar o Node.js. - e especialmente se quiser usar algo que envolva a manutenção de uma conexão persistente como soquetes da Web - é melhor executar o Apache e o seu Nó. js em outras portas (por exemplo, Apache no localhost: 8080, Node.js no localhost: 3000) e, em seguida, execute algo como nginx, Varnish ou HA proxy na frente - e direcione o tráfego dessa maneira.

Com algo como verniz ou nginx, você pode rotear o tráfego com base no caminho e / ou host. Ambos usam muito menos recursos do sistema e são muito mais escaláveis ​​do que usar o Apache para fazer a mesma coisa.


13
essa resposta deve ter mais votos positivos. definitivamente é uma abordagem muito melhor usar o proxy nginx do que o apache.
rerich

Ya, mas é intensivo em recursos
O Oracle

11
Você tem alguns números para fazer backup de sua declaração de que o nginx consumiria menos recursos que o httpd?
RedShift

Eu não acho que seja dramático. Embora eu tente não vincular as respostas, pois os links são frágeis, mas você pode encontrar algumas discussões e exemplos no Google - por exemplo, help.dreamhost.com/hc/en-us/articles/…… O Apache é um ótimo software, mas normalmente não é um ótima abordagem em um contexto como este.
Iain Collins

Essa resposta parece boa, mas como acessar o Node.js através do httpS, como já foi utilizado pelo Apache?
Pierre

34


Instruções para executar node serverjunto apache2(v2.4.xx) server:

Para tubo de todos os pedidos em uma determinada URL para o aplicativo Node.js criar CUSTOM.confarquivo dentro /etc/apache2/conf-availabledo diretório, e adicione o seguinte linha ao arquivo criado:

ProxyPass /node http://localhost:8000/

Altere 8000 para o número da porta preferida para node server.
Ative configurações personalizadas com o seguinte comando:

$> sudo a2enconf CUSTOM

PERSONALIZADO é o seu nome de arquivo recém-criado, sem extensão, e ative proxy_httpcom o comando:

$> sudo a2enmod proxy_http

deve ativar ambos proxye proxy_httpmódulos. Você pode verificar se o módulo está ativado ou não com:

$> sudo a2query -m MODULE_NAME

Após a configuração e os módulos ativados, você precisará reiniciar o servidor apache:

$> sudo service apache2 restart

Agora você pode executar o servidor do nó. Todas as solicitações para o URL/nodeserão tratadas pelo servidor do nó.


Funciona como um encanto! :)
Kees Koenen

15

A execução do Node e do Apache em um servidor é trivial, pois não conflita. O NodeJS é apenas uma maneira de executar o servidor JavaScript. O verdadeiro dilema é acessar o Node e o Apache de fora. A meu ver, você tem duas opções:

  1. Configure o Apache para fazer proxy de todas as solicitações correspondentes para o NodeJS, que fará o upload do arquivo e qualquer outra coisa no nó.

  2. Tenha o Apache e o Nó em diferentes combinações de portas IP: (se o servidor tiver dois IPs, um poderá ser vinculado ao ouvinte do nó e o outro ao Apache).

Também estou começando a suspeitar que isso pode não ser o que você está realmente procurando. Se o seu objetivo final é escrever a lógica do aplicativo no Nodejs e parte da "manipulação de arquivos" que você descarrega para um contratado, então é realmente uma escolha de idioma, não um servidor da web.


9

Você pode usar uma abordagem diferente, como escrever um servidor proxy reverso com o nodejs para fazer o proxy do apache e de todos os outros aplicativos do nodejs.

Primeiro, você precisa executar o apache em uma porta diferente da porta 80. ex: porta 8080

Em seguida, você pode escrever um script proxy reverso com nodejs como:

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

O artigo a seguir descreve todo o processo para fazer isso.

EXECUTAR APACHE COM NODE JS REVERSE PROXY - USANDO REDBIRD


2
ProxyPass /node http://localhost:8000/     
  • isso funcionou para mim quando fiz a entrada acima no httpd-vhosts.conf em vez do httpd.conf
  • Eu tenho o XAMPP instalado no meu ambiente e estava procurando atingir todo o tráfego no apache na porta 80 com o aplicativo NodeJS em execução na porta 8080, ou seja, http: // localhost / [name_of_the_node_application]

1

Combinei a resposta acima com o certbot SSL cert e o CORS access-control-allow-headers e o fiz funcionar, então pensei em compartilhar os resultados.

Apache httpd.conf adicionado à parte inferior do arquivo:

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

Configurações do Apache VirtualHost (a raiz do documento para PHP está em Apache e SSL com Certbot, enquanto o site node.js / socket.io é executado na porta 3000 - e usa o certificado SSL do Apache) Observe também que o site node.js usa o proxy para a pasta / nodejs, socket.io e 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>

Em seguida, meu aplicativo 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});

Eu forço um ouvinte de ip4, mas isso é opcional - você pode substituir:

http.listen(3000);

O código do aplicativo node.js (app.js) continua com:

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

finalmente, no lado do cliente (criado como 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'
});

Neste exemplo, quando o JS carregar, ele emitirá para o soquete um "evento nomeado" enviando os dados em JSON para o servidor node.js / socket.io.

Usando o io e o soquete no servidor em path / nodejs (conectado pelo cliente), recebe os dados e os reenvia como uma transmissão. Quaisquer outros usuários no soquete receberiam os dados com seu ouvinte "named-event-broadcast". Observe que o remetente não recebe sua própria transmissão.


0

Recentemente, me deparei com esse tipo de problema, em que preciso me comunicar entre cliente e servidor usando o websocket em um projeto codeigniter baseado em PHP.

Resolvi esse problema adicionando minha porta (aplicativo de nó em execução) nas listas Allow incoming TCP ports& Allow outgoing TCP ports.

Você pode encontrar essas configurações no Firewall Configurationspainel WHM do seu servidor.


-1

Eu estava procurando a mesma informação. Finalmente encontrei a resposta no link da resposta acima por @Straseus

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

Aqui está a solução final para executar o site apache na porta 80, o serviço js do nó na porta 8080 e usar .htaccess RewriteRule

No DocumentRoot do site apache, adicione o seguinte:

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]

Para o redirecionamento no nível do diretório, o link acima sugeriu a regra (. +), Que requer um ou mais caracteres após o 'nó /'. Eu tive que convertê-lo para (. *), Que é zero ou mais para minhas coisas funcionarem.

Muito obrigado pelo link @Straseus


3
Observe que a flag [P] requer que o Apache mod_proxyesteja ativado.
Simon Médio

Isso é ineficiente. Por que chamar o mecanismo Rewrite de uma maneira simples ProxyPass?
Michael Irigoyen

-2

Suponho que você esteja criando um aplicativo Web porque se refere ao Apache e Node. Resposta rápida - É possível - SIM. É recomendado - NÃO. O nó agrupa seu próprio servidor da Web e a maioria dos sites é executada na porta 80. Também estou assumindo que atualmente não existe um plugin Apache suportado pelo Nodejs e não tenho certeza se a criação de um host virtual é a melhor maneira de implementar isso. Essas são as perguntas que devem ser respondidas pelos desenvolvedores que mantêm o Nodejs como o pessoal da Joyent.

Em vez de portas, seria melhor avaliar a pilha de tecnologia do Node, que é completamente diferente da maioria das outras e é por isso que eu a amo, mas também envolve alguns compromissos que você deve conhecer com antecedência.

Seu exemplo é semelhante a um CMS ou um aplicativo da Web de compartilhamento e existem centenas de aplicativos prontos para uso que serão executados perfeitamente no Apache. Mesmo que você não goste de nenhuma solução pronta, você pode escrever um aplicativo da Web em PHP / Java / Python ou combiná-lo com alguns aplicativos prontos e todos eles são projetados e suportados para rodar atrás de uma única instância do Apache.

É hora de fazer uma pausa e pensar no que acabei de dizer.

Agora você está pronto para decidir em qual pilha tecnológica você usará. Se o seu site nunca usar nenhum dos milhares de aplicativos prontos que requerem Apache, vá para o Node, caso contrário, você deve primeiro eliminar as suposições que afirmei anteriormente.

No final, sua escolha do techstack é muito mais importante do que qualquer componente individual.

Concordo plenamente com o @Straseus que é relativamente trivial usar a API do sistema de arquivos node.js. para manipular carregamentos e downloads, mas pense mais sobre o que você deseja do seu site a longo prazo e escolha seu pacote técnico.

Aprender a estrutura do Nó é mais fácil do que aprender outras estruturas, mas não é uma panacéia. Com um pouco mais de esforço (que pode ser um esforço que vale a pena), você também pode aprender qualquer outra estrutura. Todos aprendemos uns com os outros e você será mais produtivo se estiver trabalhando como uma equipe pequena do que se estiver trabalhando sozinho e suas habilidades técnicas de back-end também se desenvolverão mais rapidamente. Portanto, não descarte as habilidades de outros membros de sua equipe de maneira tão barata.

Este post tem cerca de um ano e é provável que você já tenha decidido, mas espero que meu discurso retórico ajude a próxima pessoa que está passando por uma decisão semelhante.

Obrigado pela leitura.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.