동일한 서버의 Apache 및 Node.js


352

노드가 빠르기 때문에 클라이언트를 사용하고 싶습니다. 클라이언트 측에서 사용하는 것과 동일한 언어를 사용하며 정의에 따라 차단되지 않습니다. 그러나 파일 처리 (저장, 편집, 이름 바꾸기, 다운로드, 파일 업로드 등)를 위해 프로그램을 작성하기 위해 고용 한 사람은 아파치를 사용하려고합니다. 따라서 다음을 수행해야합니다.

  1. 그를 사용하도록 설득하십시오 (그는 거의 근거를 포기하지 않았습니다)

  2. 노드에서 파일을 업로드, 다운로드, 이름 바꾸기, 저장하는 방법 등을 파악하거나

  3. 동일한 서버에 아파치와 노드를 설치해야합니다.

가장 유리한 상황은 무엇이며 어떻게 구현합니까?

답변:


704

좋은 질문입니다!

PHP에는 Apache에서 실행되는 많은 웹 사이트와 무료 웹 응용 프로그램이 있으며, 많은 사람들이이를 사용하여 매우 쉽고 정적 콘텐츠를 제공하는 가장 쉬운 방법을 만들 수 있습니다. Node는 빠르고 강력하며 우아하며 V8의 강력한 성능과 내장 된 종속성이없는 평평한 스택을 갖춘 섹시한 도구입니다.

또한 Apache의 용이성 / 유연성을 원하지만 Node.JS의 강력 함과 우아함을 원합니다. 왜 둘 다 가질 수 없습니까?

다행히도 Apache 의 ProxyPass 지시문 httpd.conf을 사용하면 특정 URL의 모든 요청을 Node.JS 애플리케이션으로 파이프하기가 어렵지 않습니다.

ProxyPass /node http://localhost:8000

또한 http 요청을 다시 라우팅 할 수있는 올바른 프록시 및 하위 모듈을 얻으려면 다음 행을 주석 처리하지 않아야합니다.

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

그런 다음 포트 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');

그런 다음 /node/URL 의 경로를 사용하여 모든 Node.JS 논리에 액세스 할 수 있으며 나머지 웹 사이트는 Apache로 남겨져 기존 PHP 페이지를 호스팅 할 수 있습니다.

여기에 이미지 설명을 입력하십시오

이제 남은 것은 호스팅 회사가이 구성으로 실행되도록 설득시키는 것입니다 !!!


6
이것은 훌륭한 답변이었습니다.이 작업을 수행하는 데 사용한 프록시 패스에 대한 정보가 조금 더있는 링크를 추가하고 싶었습니다. 의견도 확인하십시오. boriskuzmanovic.wordpress.com/2006/10/20/…
Alex Muro

11
가상 호스트 컨테이너 에 "ProxyPass / 127.0.0.1:8000 "을 넣는 것을 테스트 했으며 전체 도메인 그룹을 노드 인스턴스로 리디렉션 할 수있었습니다. 또한 "time wget ..."으로 테스트하여 노드 액세스 속도와 Apache를 통한 노드 액세스 속도를 직접 비교했습니다. 30 쌍의 시도에서 평균 차이는 약 0.56ms였습니다. 가장 낮은로드 시간은 직접 및 Apache를 통한 120ms입니다. 가장 높은로드 시간은 직접 154ms, Apache를 통한 164입니다. 큰 차이는 없습니다. 내가 두 개의 IP를 가지고 있다면 Apache를 통해 라우팅하지는 않지만 지금은 Proxypass를 사용합니다
kaan_a

5
이 프록시가 Apache에서 Node로 요청하지는 않지만 Node의 비 차단 특성의 이점을 제거합니까?
Trace

2
안녕하세요 @Basj, 웹 소켓에 대한 지원 설치 경험이 없습니다. 아파치 2.4.6은을 사용하여 웹 소켓 트래픽 프록시를 지원하는 것으로 보입니다 mod_proxy_wstunnel. : 난 당신이 지금을 참조하시기 바랍니다 같은 문제를 가진 다른 사람을 위해, 당신의 대답을 발견 볼 serverfault.com/questions/616370/...
스티븐 드 살라스

4
데비안 기반 배포판에서 이것을 어디에 추가합니까? httpd.conf 파일이 없습니다.
산티

63

이 질문은 서버 결함 에 더 속합니다 하지만 FWIW Node.js 앞에서 Apache를 실행하는 것이 대부분의 경우 좋은 접근 방법이 아니라고 말하고 싶습니다.

Apache의 ProxyPass는 (Tomcat 기반 서비스를 사이트의 일부로 노출하는 것과 같은) 많은 일에 훌륭합니다. Node.js 앱이 특정하고 작은 역할을 수행하거나 제한된 수의 사용자 만 가질 수있는 내부 도구 인 경우 그런 다음 사용하기가 더 쉬워서 작업을 계속 진행할 수 있지만 여기에서는 그렇지 않습니다.

성능과 확장 성을 활용하려면 Node.js를 사용하여 얻을 수 있습니다. 특히 웹 소켓과 같은 지속적인 연결을 유지하는 것과 관련된 것을 사용하려는 경우 Apache와 Node를 모두 실행하는 것이 좋습니다. 다른 포트의 js (예 : localhost : 8080의 Apache, localhost : 3000의 Node.js)를 nginx, Varnish 또는 HA 프록시와 같은 방식으로 실행하고 트래픽을 라우팅합니다.

니스 또는 nginx와 같은 경로를 사용하면 경로 및 / 또는 호스트를 기반으로 트래픽을 라우팅 할 수 있습니다. 둘 다 시스템 리소스를 훨씬 적게 사용하며 Apache를 사용하여 동일한 작업을 수행하는 것보다 훨씬 확장 성이 뛰어납니다.


13
이 답변에는 더 많은 투표가 있어야합니다. 아파치 하나보다 nginx 프록시를 사용하는 것이 훨씬 더 나은 방법입니다.
리치

예, 그러나 자원 집약적입니다.
Oracle

1
nginx가 httpd보다 덜 자원 집약적이라는 진술을 뒷받침 할 숫자가 있습니까?
RedShift

나는 그것이 극적이지는 않지만. 링크가 깨지기 때문에 회신에 링크하지 않으려 고하지만 Google을 통해 몇 가지 토론과 예를 찾을 수 있습니다 (예 : help.dreamhost.com/hc/en-us/articles/… ... Apache는 훌륭한 소프트웨어이지만 일반적으로 이와 같은 맥락에서 훌륭한 접근 방식.
Iain Collins

이 답변은 훌륭하게 들리지만 Apache에서 이미 가져온 httpS를 통해 Node.js에 액세스하는 방법은 무엇입니까?
Pierre

34


지침 실행 node server함께 apache2(v2.4.xx) server:

만들고, Node.js를 응용 프로그램으로 파이프하기 위해 특정 URL에 대한 모든 요청을 CUSTOM.conf내부 파일 /etc/apache2/conf-available생성 된 파일 행 다음에 디렉터리를 추가 :

ProxyPass /node http://localhost:8000/

8000을 선호하는 포트 번호로 변경하십시오 node server.
다음 명령으로 사용자 정의 구성을 활성화하십시오.

$> sudo a2enconf CUSTOM

CUSTOM은 확장명없이 새로 생성 된 파일 이름이며 다음 proxy_http명령 을 사용 하여 활성화 하십시오.

$> sudo a2enmod proxy_http

모듈 proxyproxy_http모듈을 모두 활성화해야 합니다. 다음을 통해 모듈의 활성화 여부를 확인할 수 있습니다.

$> sudo a2query -m MODULE_NAME

구성 및 모듈을 활성화 한 후에는 Apache 서버를 다시 시작해야합니다.

$> sudo service apache2 restart

이제 노드 서버를 실행할 수 있습니다. 에 대한 모든 요청 URL/node은 노드 서버에서 처리합니다.


매력처럼 작동합니다! :)
Kees Koenen 2016 년

15

하나의 서버에서 Node와 Apache를 실행하는 것은 충돌하지 않으므로 쉽지 않습니다. NodeJS는 JavaScript 서버 측을 실행하는 방법입니다. 실제 딜레마는 외부에서 노드와 아파치 모두에 액세스 할 때 발생합니다. 내가 알듯이 두 가지 선택이 있습니다.

  1. 일치하는 모든 요청을 NodeJS에 프록시하도록 Apache를 설정하십시오. 그러면 파일 업로드 및 노드의 다른 모든 작업이 수행됩니다.

  2. 다른 IP : 포트 조합에 Apache와 노드를 갖습니다 (서버에 두 개의 IP가있는 경우 하나는 노드 리스너에 바인딩하고 다른 하나는 Apache에 바인딩 할 수 있음).

나는 이것이 당신이 실제로 찾고있는 것이 아닐 수도 있다고 의심하기 시작했습니다. 최종 목표가 Nodejs에 애플리케이션 로직을 작성하고 계약자에게 오프로드하는 일부 "파일 처리"부분을 작성하는 것이면 웹 서버가 아닌 언어를 선택하는 것입니다.


9

nodejs로 리버스 프록시 서버를 작성하는 것과 같은 다른 접근법을 사용하여 아파치 및 다른 모든 nodejs 앱을 프록시 할 수 있습니다.

먼저 포트 80 이외의 다른 포트에서 아파치를 실행해야합니다. 예 : 포트 8080

그런 다음 nodejs를 사용하여 리버스 프록시 스크립트를 작성할 수 있습니다.

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

다음 기사에서는이를 만드는 전체 프로세스에 대해 설명합니다.

REDBIRD를 사용하여 노드 JS 리버스 프록시로 아파치 실행


2
ProxyPass /node http://localhost:8000/     
  • 이것은 httpd.conf 대신 httpd-vhosts.conf에 위 항목을 만들 때 나에게 효과적이었습니다.
  • 내 환경에 XAMPP가 설치되어 있고 8080 포트에서 실행되는 NodeJS 응용 프로그램이있는 포트 80의 아파치에서 모든 트래픽에 도달하려고했습니다 . http : // localhost / [name_of_the_node_application]

1

위의 답변을 certbot SSL 인증서 및 CORS 액세스 제어 허용 헤더와 결합하여 결과를 공유 할 것이라고 생각했습니다.

Apache httpd.conf가 파일의 맨 아래에 추가되었습니다.

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

Apache VirtualHost 설정 (PHP 용 문서 루트는 Certbot이있는 Apache 및 SSL에 있으며 node.js / socket.io 사이트는 포트 3000에서 실행되고 Apache의 SSL 인증서를 사용함)도 node.js 사이트에서 폴더에 프록시를 사용합니다. / nodejs, socket.io 및 ws (웹 소켓) :

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

그런 다음 내 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});

나는 ip4 리스너를 강제하지만 선택 사항입니다-당신은 대체 할 수 있습니다 :

http.listen(3000);

node.js 앱 (app.js) 코드는 다음과 같이 계속됩니다.

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

마지막으로 클라이언트 쪽에서 (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'
});

이 예제에서는 JS가로드 될 때 JSON의 데이터를 node.js / socket.io 서버로 보내는 "명명 된 이벤트"를 소켓으로 방출합니다.

클라이언트에서 연결된 / nodejs 경로 아래의 서버에서 io 및 소켓을 사용하여 데이터를 수신 한 다음 브로드 캐스트로 다시 보냅니다. 소켓의 다른 사용자는 리스너가 "named-event-broadcast"인 데이터를 수신합니다. 발신자는 자신의 브로드 캐스트를받지 않습니다.


0

최근에 PHP 기반 codeigniter 프로젝트에서 websocket을 사용하여 클라이언트와 서버간에 통신 해야하는이 일종의 문제가 발생했습니다.

내 포트 (노드 앱이 실행중인)를 Allow incoming TCP ports& 에 추가 하여이 문제를 해결했습니다.Allow outgoing TCP ports 목록 .

이러한 구성은 Firewall Configurations서버의 WHM 패널에서 찾을 수 있습니다 .


-1

나는 같은 정보를 찾고 있었다. 마지막으로 @Straseus의 위 답변에 대한 링크에서 답변을 찾았습니다.

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

다음은 포트 80에서 Apache 웹 사이트를 실행하고 포트 8080에서 노드 js 서비스를 실행하고 .htaccess RewriteRule을 사용하는 최종 솔루션입니다.

Apache 웹 사이트의 DocumentRoot에서 다음을 추가하십시오.

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]

디렉토리 레벨 경로 재 지정의 경우 위의 제안 된 (. +) 규칙은 'node /'다음에 하나 이상의 문자가 필요합니다. 내 물건이 작동하려면 0 이상으로 (. *)로 변환해야했습니다.

링크 @Straseus에 감사드립니다


3
[P] 플래그를 사용하려면 Apache mod_proxy를 활성화해야합니다.
Simon East

이것은 비효율적입니다. 왜 간단하게 다시 쓰기 엔진을 호출 ProxyPass합니까?
Michael Irigoyen

-2

Apache 및 Node를 참조하기 때문에 웹 응용 프로그램을 만들고 있다고 가정합니다. 빠른 답변-가능합니까-예. 권장합니다-아니오. 노드 번들은 자체 웹 서버이며 대부분의 웹 사이트는 포트 80에서 실행됩니다. 현재 Nodejs에서 지원하는 Apache 플러그인이 없으며 가상 호스트를 만드는 것이 이것이 최선의 방법인지 확실하지 않습니다. Joyent의 훌륭한 사람들처럼 Nodejs를 유지 관리하는 개발자가 대답해야 할 질문입니다.

포트 대신, 대부분의 다른 기술과 완전히 다른 Node의 기술 스택을 평가하는 것이 더 좋으며, 이것이 내가 좋아하는 이유이지만 미리 알고 있어야 할 몇 가지 타협도 포함됩니다.

귀하의 예는 CMS 또는 공유 웹 앱과 유사하며 Apache에서 제대로 실행될 수있는 즉시 사용 가능한 수백 가지 앱이 있습니다. 기성품 솔루션이 마음에 들지 않더라도 PHP / Java / Python으로 웹 응용 프로그램을 작성하거나 두 가지 기성품 앱과 n을 일치시킬 수 있으며 단일 Apache 인스턴스에서 실행되도록 설계되고 지원됩니다.

내가 방금 말한 것을 멈추고 생각할 때입니다.

이제 사용할 기술 스택을 결정할 준비가되었습니다. 귀하의 웹 사이트에서 Apache가 필요한 수천 개의 기성품 앱을 절대 사용하지 않으면 Node로 이동하십시오. 그렇지 않으면 먼저 앞서 언급 한 가정을 제거해야합니다.

결국, 기술 스택 선택은 개별 구성 요소보다 훨씬 중요합니다.

업로드 및 다운로드 처리에 node.js 파일 시스템 API를 사용하는 것이 비교적 쉽지만 장기적으로 웹 사이트에서 원하는 것을 더 많이 생각한 다음 기술 스택을 선택하는 것이 @Straseus에 전적으로 동의합니다.

Learning Node의 프레임 워크는 다른 프레임 워크를 배우는 것보다 쉽지만 만병 통치약은 아닙니다. 약간 더 노력하면 (자체적으로 가치있는 노력이 될 수 있음) 다른 프레임 워크도 배울 수 있습니다. 우리는 모두 서로에게서 배우며 혼자서 일하는 것보다 소규모 팀으로 일할 경우 생산성이 향상되고 백엔드 기술 능력이 더 빨리 발전합니다. 따라서 팀의 다른 구성원의 기술을 너무 싸게 할인하지 마십시오.

이 게시물은 1 년 정도되었으며 이미 결정한 것 같습니다.하지만 저의 시련이 비슷한 결정을 내리는 다음 사람을 도울 수 있기를 바랍니다.

읽어 주셔서 감사합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.