同じサーバー上のApacheとNode.js


352

Nodeを使用したいのは、迅速で、クライアント側で使用しているのと同じ言語を使用しており、定義上は非ブロッキングだからです。しかし、ファイル処理(ファイルの保存、編集、名前変更、ダウンロード、アップロードなど)のためにプログラムを作成するために雇った男は、Apacheを使用したいと考えています。だから、私はしなければなりません:

  1. ノードを使用するように彼を説得します(彼はそのことについてほとんど地面をあきらめていません)

  2. ノードでファイルをアップロード、ダウンロード、名前変更、保存などする方法を理解する

  3. Apacheとノードを同じサーバーにインストールする必要があります。

最も好ましい状況はどれですか、それをどのように実装しますか?

回答:


704

すばらしい質問です。

Apacheで実行されるPHPで実装された多くのWebサイトと無料のWebアプリがあり、多くの人々がそれを使用するので、非常に簡単なだけでなく、静的コンテンツを提供する簡単な方法でマッシュアップできます。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ロジックにアクセスできます。Web サイトの残りの部分は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経由で164msでした。大きな違いはありません。2つのIPの贅沢がある場合は、Apache経由ではルーティングしませんが、ここではProxypassを使います
kaan_a

5
このプロキシは、ApacheからNodeにリクエストを送信しますが、Nodeの非ブロッキング性の利点を取り除きませんか?
2014

2
こんにちは@Basj、私は自分でWebSocketのサポートをインストールした経験がありません。そうは言っても、Apache 2.4.6はを使用したWebSocketトラフィックのプロキシをサポートしているようmod_proxy_wstunnelです。同じ問題のある他のユーザーについては、次を参照してください。serverfault.com
Steven de Salas 14

4
これをdebianベースのディストリビューションでどこに追加すればよいですか?httpd.confファイルはありません。
サンティ2015

63

この質問はサーバー障害に属していますが、FWIW私はNode.jsの前でApacheを実行することはほとんどの場合良いアプローチではないと思います。

ApacheのProxyPassは、(Tomcatベースのサービスをサイトの一部として公開するなど)多くの点で優れており、Node.jsアプリが特定の小さな役割を実行している場合や、ユーザー数が限られている可能性が高い内部ツールである場合そうすれば、それを使用して先に進むことができるので、それを使用する方が簡単かもしれませんが、ここではそうではありません。

Node.jsを使用することで得られるパフォーマンスとスケールを活用したい場合、特にWebソケットなどの永続的な接続を維持する必要がある場合は、ApacheとNodeの両方を実行したほうがよいでしょう。他のポートのjs(たとえば、localhost:8080のApache、localhost:3000のNode.js)でnginx、VarnishまたはHAプロキシなどを実行し、トラフィックをそのようにルーティングします。

ワニスやnginxなどを使用すると、パスやホストに基づいてトラフィックをルーティングできます。どちらもシステムリソースの使用量がはるかに少なく、Apacheを使用して同じことを行うよりもはるかにスケーラブルです。


13
この回答にはもっと賛成票があるはずです。nginxプロキシを使用する方法は、Apacheのものよりも明らかに優れています。
2016年

はい、ただしリソースを集中的に
使用します

1
nginxはhttpdよりもリソース集中型ではないという声明を裏付ける数値はありますか?
RedShift

それはかなり劇的ですが、私はしません。リンクは壊れやすいので返信ではリンクアウトしないようにしていますが、Google経由でいくつかのディスカッションや例を見つけることができます。たとえば、help.dreamhost.com / hc / en - us / articles / ……Apacheは素晴らしいソフトウェアですが、通常このような状況での素晴らしいアプローチ。
Iain Collins、

この回答は良さそうに聞こえますが、Apacheによってすでに採用されているため、httpSを介してNode.jsにアクセスする方法
ピエール

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

15

1つのサーバーでノードとApacheを実行しても、競合しないので簡単です。NodeJSは、JavaScriptサーバー側を実行するための単なる方法です。本当のジレンマは、外部からNodeとApacheの両方にアクセスすることから生じます。私が見ると、2つの選択肢があります。

  1. 一致するすべてのリクエストをNodeJSにプロキシするようにApacheを設定します。NodeJSはファイルのアップロードなど、ノード内の他のすべてを実行します。

  2. Apacheとノードを異なるIP:ポートの組み合わせで使用します(サーバーに2つのIPがある場合、1つをノードリスナーにバインドし、もう1つをApacheにバインドできます)。

また、これが実際に探しているものではないのではないかと疑い始めています。最終目標がNodejsでアプリケーションロジックを記述し、請負業者にオフロードするいくつかの「ファイル処理」パーツを記述することである場合、それは実際にはWebサーバーではなく言語の選択です。


9

nodejsを使用してリバースプロキシサーバーを作成し、apacheと他のすべてのnodejsアプリの両方をプロキシするなど、別のアプローチを使用できます。

まず、Apacheをポート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");

次の記事では、これを行うプロセス全体について説明します。

NODE JS REVERSE PROXYを使用してAPACHEを実行する– Redbirdを使用する


2
ProxyPass /node http://localhost:8000/     
  • これは、httpd.confではなくhttpd-vhosts.confに上記のエントリを作成したときに機能しました
  • 私の環境にはXAMPPがインストールされており、8080ポートで実行されているNodeJSアプリケーションでhttp:// localhost / [name_of_the_node_application]を使用して、ポート80のapacheですべてのトラフィックをヒットしようとしていました

1

上記の回答とcertbot SSL certおよびCORS access-control-allow-headersを組み合わせて機能させたので、結果を共有すると思いました。

ファイルの最後に追加された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(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>

次に、私の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 portsAllow outgoing TCP portsリストに追加することで、この問題を解決しました。

これらの構成はFirewall Configurations、サーバーのWHMパネルにあります。


-1

同じ情報を探していました。最後に@Straseusによる上記の回答のリンクから回答を見つけました

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

これは、ポート80でapache Webサイトを実行し、ポート8080でノードjsサービスを実行し、.htaccess RewriteRuleを使用するための最終的なソリューションです。

Apache Webサイトの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 /」の後に1つ以上の文字を必要とします。私の作品が機能するためには、それを(。*)に変換する必要がありました。

リンク@Straseusに感謝します


3
[P]フラグを使用するには、Apache mod_proxyを有効にする必要があることに注意してください。
Simon East

これは非効率的です。なぜ、単純なオーバー書き換えエンジンボークProxyPass
Michael Irigoyen、2015年

-2

ApacheとNodeを参照しているので、あなたはWebアプリを作成していると思います。簡単な答え-可能ですか-はい。それはお勧めですか-いいえ。Nodeは独自のWebサーバーをバンドルしており、ほとんどのWebサイトはポート80で実行されます。また、現在NodejsでサポートされているApacheプラグインがないと想定しています。仮想ホストの作成がこれを実装する最善の方法かどうかはわかりません。これらは、Joyentの優秀な人々のようにNodejsを保守する開発者が回答する必要がある質問です。

ポートの代わりに、他のほとんどのノードとは完全に異なるノードの技術スタックを評価する方が良いでしょう。そのため、私はそれを気に入っていますが、事前に知っておくべきいくつかの妥協も伴います。

あなたの例はCMSや共有Webアプリに似ており、Apache上で問題なく実行できる数百のすぐに使えるアプリがあります。既製のソリューションが気に入らない場合でも、PHP / Java / Pythonでwebappを作成するか、それをいくつかの既製のアプリと組み合わせることができます。これらはすべて、Apacheの単一インスタンスの背後で実行するように設計およびサポートされています。

一時停止して、今言ったことを考えてみましょう。

これで、使用するtechstackを決定する準備ができました。Apacheを必要とする何千もの既製のアプリのうち、あなたのウェブサイトが決して何も使用しない場合は、Nodeに進んでください。

結局のところ、techstackの選択は、個々のコンポーネントよりもはるかに重要です。

アップロードとダウンロードを処理するためにnode.jsファイルシステムAPIを使用するのは比較的簡単であるという@Straseusに完全に同意しますが、長期的にはWebサイトに何が欲しいかを考え、techstackを選択します。

Learning Nodeのフレームワークは、他のフレームワークの学習よりも簡単ですが、万能薬ではありません。もう少し努力(それ自体は価値のある努力かもしれません)で、他のフレームワークも学ぶことができます。私たちは皆、お互いから学び、一人で作業するよりも小さなチームで作業している場合の方が生産性が高くなり、バックエンドの技術スキルもより速く発達します。したがって、チームの他のメンバーのスキルをそれほど安く割引しないでください。

この投稿は約1年前のものであり、あなたがすでに決定している可能性がありますが、私の怒りが同様の決定を経験している次の人を助けることを願っています。

読んでくれてありがとう。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.