さくらのVPS設定[8]-NginxでリバースプロキシとNodeアプリ

リバースプロキシは、アクセスを代行して受け取るサーバーだ。wikipediaから引用すると、以下のような説明になる。

リバースプロキシ
リバースプロキシ(英: Reverse proxy)または逆プロキシは、特定のサーバへの要求を必ず経由するように設置されたプロキシサーバ。一般的なプロキシとは異なり不特定多数のサーバを対象としない。リバースプロキシは、不特定多数のクライアントから寄せられる要求に対して、応答を肩代わりすることにより特定のサーバの負担を軽減したり、アクセスを制限することにより特定のサーバのセキュリティを高めたりする目的に用いられる。

node.jsでアプリを作成しforeverで永続化した場合、xxx.xxx.xx:3000などと最後にポート番号がついてしまう、これがとても気になっており、nginxでリバースプロクシを入れてアプリごとサブドメイン運用をしようとしたきっかけとなった。もちろんサブディレクトリの方にも入れることができるので簡単な実験とかはそちらの方がいいのかもしれない。
またnodeには動的な物を任せ、静的な部分についてはnginxで取り扱う形のほうがパフォーマンスから見ても良いようだ。
それとリバースプロクシはwebsocketを通さないのでnginx_tcp_proxy_moduleを使用して動かす方法も書いておく。

使用しているのは、以前作ったタッチ共有アプリだ。これをさくらのVPSサーバーへ持ってきて諸処の作業を行った。

nginx_tcp_proxy_moduleでnode.jsのsocket.ioをリバースプロクシさせる

nginx_tcp_proxy_moduleのインストールは以前のエントリの通りだ。そして設定方法は次のブログ記事を参考にさせて頂いた。

nginxでsocket.ioのリバースプロキシ設定
nginx_tcp_proxy_module を入れてnode.jsのsocket.ioを動かすnginxの設定

モジュール設定はtcpブロックで行うがhttpブロックとたいして変わりがない。
そして/usr/local/nginx/conf/tcps以下にtcp設定を置きnginx.confからincludeする形にした。

user nginx;
worker_processes  2;
・・・・
events {
    worker_connections  1024;
}
# Load config files from th/usr/local/nginx/conf/tcps/ directory
include tcps/*.conf;

http {
 ・・・・
}

includeしたtcp_cotouch.confはこのような内容であり、3000ポートでnodeアプリを動かし、サイトに3001で接続するとちゃんと動くのを確認できた。

tcp {
  upstream coTouchApp {
    server 127.0.0.1:3000;
    check interval=3000 rise=2 fall=5 timeout=1000;
  }

  server {
    listen 3001;
    server_name cotouch.omusuhi.info;

    proxy_read_timeout 200000;
    proxy_send_timeout 200000;
    proxy_pass coTouchApp;
  }
}

ところで、ソケット通信は、こちらの説明でも書いてある通り、IPアドレスとPort番号を一組とした通信手段となる。
ソケット【socket】 

「ソケット」というのはIPアドレスとPort番号を一組にしたものに結び付けられた仮想メモリ空間なのです。 相手にデータを送るときは、このメモリ空間に通信するためのデータを書き込むことによって 「Socket」ライブラリの中の「socket」プログラムが相手アプリケーションとデータの通信を行ってくれるのです。

なので、[[Portが一つ占有されることになる]]はずだと思いながら、tcpとhttpで同じポート番号を指定すると、動いてしまった。しかしながら、別々のポートを指定していた時とは違い引っかかりがある。どういうことなのだろうと思いnginxを停めてinit.dで再起動しようとするとポートが使われていて動かせないと出てくる。

sudo /etc/init.d/nginx restart

前の時は、設定ファイルのリロードだったのを思い出し、nginx.confでtcpとhttpのポート指定を書き換えた上でnginxを機動、tcpとhttpのポート指定を同じにした上で下記のコマンドで設定リロードする。

sudo nginx -s reload

そうすると同じポートで動いてしまった。ここで、エラーログを確認しようとした。

sudo vi /usr/local/nginx/logs/error.log

すると重くて開くのにとんでもなく時間が掛かる。
やはり、ソケットとhttpの接続とで混乱が起きていた模様で大量のエラーが発生していた。これで同じポート指定はやはり出来ないことが分かった。
そして念の為にtcpブロックで同じポート指定で2つ動かそうとしてみたら、先に書かれていたものが優先され、default_serverの指定が後のサーバにあった場合、既に使われているというエラーが出る。
このため、やはりtcpのserverブロックは1ポート専有というのを再確認することができた。

nodeアプリをhttpブロックでリバースプロキシ

soket.ioでの接続は現段階ではリバースプロキシしてもあまり意味が無いので、これまでのようにポート指定で行うことにして、ソケットとは関係のないnodeアプリ本体の部分にリバースプロキシを使いURLにポート番号が出ないようにすることにした。
soket.ioと本体のポート番号を変えるのは下記の記事を参考にさせていただいている。
Socket.io Chat on Dreamhost: Hiding the URL

nodeアプリでは、このように本体を3001、ソケットを3002として指定しなおしている。

var sys = require('util'),
		express = require('express'),
		app = express.createServer();

app.configure(function(){
	app.use(express.static(__dirname+'/views'));
});
app.listen(3001);
//var io = require('socket.io').listen(app);appではなくポート番号指定と変えている。
var io = require('socket.io').listen(3002);

io.sockets.on('connection', function(socket){
・・・・

html部分だと、index.htmlでsocket.io.jsを指定する部分をポート番号付きに変更する。

<!--<script src="/socket.io/socket.io.js"></script> -->
<script src="http://www.omusuhi.info:3002/socket.io/socket.io.js"></script>

socketを使うクライアント側jsファイルの方でもsocket.io側のポート指定へと変える。

function initSocket(){
  var socket = io.connect('http://www.omusuhi.info:3002/');
  socket.on('message', function(t){
    console.log('mes; '+t);
  });
・・・・
}

Nodeアプリの変更点は以上となる。次にnginxでリバースプロキシの設定を行った。
参考にさせていただいたのは、主にこちらのサイトだ。
Virtualmin, Apache, and Nginx Reverse Proxy
さくらVPS を設定してみる:Nginx + リバースプロキシで WordPress を動かしてみた♪
apache のかわりにnginxを使ってみる(10) nginx をリバースプロキシとして使ってみた
nginxでリバースプロキシ。

プロキシ共有設定ファイルを上記サイトを見つつ、このような感じで書き、
projects/proxy.confへと保存した。

proxy_cache_path        /var/cache/nginx/ levels=1:2 keys_zone=czone:10m max_size=100m inactive=120m;
proxy_temp_path         /var/cache/nginx;
proxy_redirect          off;
proxy_set_header        Host            $host;
proxy_set_header        X-Real-IP       $remote_addr;
proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size    10m;
client_body_buffer_size 128k;
proxy_connect_timeout   90;
proxy_send_timeout      90;
proxy_read_timeout      90;
proxy_buffers           32 4k;
proxy_cache_valid       200 302 10m;
proxy_cache_valid       301 1h;                                                           
proxy_cache_valid       any 1m;

また、今回のアプリのプロキシ設定を下記のように書き、
projects/cotouch.confへと保存してある。

upstream cotouch {
    ip_hash;
    server 127.0.0.1:3001;
}

server {
    listen   80;
    server_name cotouch.omusuhi.info;
    location / {
        proxy_pass http://cotouch/;
    }
}

前回のエントリで、projectsディレクトリにあるものは読みこむようにしてあったので、proxy.confもcotouch.confもnginx起動時に自動的に読み込まれることになる。

・・・・
http {
・・・・
 # Load config files from th/usr/local/nginx/conf/projects/ directory
 include /usr/local/nginx/conf/projects/*.conf;
}

ここまで変更してから、nginxの再起動を行う。

sudo /etc/init.d/nginx restart

すると、ちゃんとサブドメインでアプリが動き、さらに2枚同時に立ち上げると同期しているのも確認できた。
cotouch.omusuhi.info

これで、複数のNodeアプリがあってもnginx側で管理できるようになった。
次はphp-fpmでphpを動かしてみたい。
余裕ができたらwordpressもnginxでどれだけパフォーマンスが良くなるのか試してみたいと考えている。

Submit a Comment

Spam Protection by WP-SpamFree