Posted on Sep 15, 2012 at 19:10
※あまりテキトーな事書くのもどうかと思いますが動いたのでメモしておきます。
【概要】
WebSocketを使ったサービスが作りたくなり、どうせなら前から気になってたnode.jsを使おうと思い立ったわけですが、既存のホスティング環境(さくらのVPS)にはApacheが走っているため、そのまま使おうとすると「http://example.com:8124」とかポート番号直打ちになるため、ちょっとカッコ悪いという問題が発生。(80番ではApacheが走ってるのでnodeが動かせない。)
そのため、なんか方法は無いものかと調べたら以下の素敵なスライドを発見。
Node.js勉強会@関西 第0回 Node.jsでつくるリバースプロキシ
node製の「node-http-proxy」というこれまた素敵なものがあるらしく、これを使えばリバースプロキシが簡単に作れるらしい。
ただ既存の環境ではApacheにバーチャルホストを設定してるので、そのままやっちゃっていいものなのか、いまいち良く分からない。
そのため、さらに検索したところ、なにやら凄く分かり易いサンプルを発見。
Reverse HTTP Proxy (Apache + nodejs)
正にこれだ!ということで早速、実装に取りかかる事に。
【目的】
現在、ポート80番で動いているApacheを「8080番」で動作するように変更し、node-http-proxyを使ったリバースプロキシを「80番」動作させて、各ドメインごとにApacheで処理するか、nodeで処理するかを自動的に振り分けるようにします。
【やった事メモ】
※以下、既にnode.jsはインストール済みという前提で進めます。環境はCentOS6.2です。
-
何はともあれnode-http-proxyのインストールを行います。
npm install -g http-proxy
npm link http-proxy
-
サーバの適当な場所に上記の参考先を元にしてリバースプロキシのjsファイルを作成。
[proxy.js]
var httpProxy = require('/path/to/node_modules/http-proxy');
//※本当はフルパスで読み込まなくてもいいはずです
var options = {
hostnameOnly: true,
router: {
'example1.com': '127.0.0.1:8080',
'example2.com':'127.0.0.1:8080'
}
};
var proxyServer = httpProxy.createServer(options);
proxyServer.listen(80);
console.log('It Works!');
※http-proxyの呼び出しがフルパスなのは -g を付けてインストールしたにも関わらず、私の環境ではNODE_PATHが通ってないらしく、良く分からなかったのでフルパスで書きました。通常はフルパスの必要はありません。
-
Apacheのポートをこれまでの「80番」から「8080番」に変更。当然、そのままではサイトに繋がらなくなるので、既にApacheで何か動かしてる人は注意して下さい。
以下、設定例。
[/etc/httpd/conf/httpd.conf]
Listen 8080
NameVirtualHost *:8080
<VirtualHost *:8080>
DocumentRoot /path/
ServerName www.example1.com
ServerAlias example1.com *.example1.com
</VirtualHost>
<VirtualHost *:8080>
DocumentRoot /path/
ServerName www.example2.com
ServerAlias example2.com *.example2.com
</VirtualHost>
コンフィグの修正が完了したら構文確認後、Apacheを再起動、またはコンフィグをリロードします。
/usr/sbin/apachectl -t
/etc/init.d/httpd restart
この時点で一旦、80番で繋がらなくなります。
-
先ほど作ったリバースプロキシ(proxy.js)を動かします。
node proxy.js
動いた!・・・と思いきやエラーが発生。
Error: listen EACCES
どうやら80番で動かすにはsudoでやらないといけないらしい。再度実行すると今度は無事に動いた。
sudo node proxy.js
上手くいっていれば、この状態でバーチャルホストに設定されたドメインにアクセスするとこれまで通りちゃんとレスポンスが帰ってきます。上手くいかない場合はリバースプロキシの設定とApacheの設定をもう一度見直して下さい。
-
さて、動いたのは良いのですが、このままの状態だとコンソールに「It Works!」と表示されたままで他の作業が出来なくなります。Macのターミナルなら標準でタブが付いてるので大した問題でもないのかもしれませんが、素人に毛が生えた程度の私くらいのレベルだともはやこの世の終わりに近い状態です。
というかnode.jsには「forever」というnode.jsで作成したプログラムを永続化し、デーモンとして管理できるパッケージがあるのでそれを使えば話は早いのですが、今回のリバースプロキシは「80番」という特権ポートで動かしているためか、どうやらforeverでデーモンにする事ができないらしい???
じゃあどうするのかというとコマンドの最後に「&」を付けてコントロールを奪われないようにします。
sudo node proxy.js &
こうするとバックグラウンドでプロセスが動き続けるので、リバースプロキシを動作させた後もコンソールのコントロールを奪われる事無く、色々と作業を継続出来ます。ただ、この方法は色々と突っ込みどころが多そうなので、詳しい人はデーモンにする詳しい方法とか教えてもらえると助かります。
参考リンク:
nodeのアプリをport80で動かす
ログアウトした後もコマンドを実行し続ける方法
-
これで一通りの目的は達成出来たため、後はnode.jsでガリガリとアプリを開発して適当なポートで動作させ、proxy.jsに動作しているnode製アプリの記述を加えてやれば、特定のドメインでアクセスした時にnodeのアプリが動くようになります。
ただ、proxy.jsは最低限の記述となっているので以下のコードを参考にもう少しまともなリバースプロキシにした方が良さそうです。今だとhttpsとかで接続しても繋がらないんじゃないかと思います。
参考:
node-http-proxyを使ったいわゆるバーチャルホスト対応Webサーバー
以上。