TKC Works

ギジュツ的なメモ、読書感想文など

NginxによるWebSocketの負荷分散

Node.js、Socket.IOを使ってリアルタイムなWebアプリなんかを作っていて、分散構成はどうすればいいのか試行錯誤しているメモ。

Nginxは1.3.13からWebSocketのプロキシに対応したので以下を参考にサクッとやってみる。 http://nginx.org/en/docs/http/websocket.html

upstream chatserver {
    server xxx.xxx.xxx.xxx:3000;
    server yyy.yyy.yyy.yyy:3000;
}

server {
    listen       3000;
    server_name  localhost;

    location / {
        proxy_pass http://chatserver;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

この設定でも確かにプロキシされたし、分散もされた。
しかし、接続先のサーバーが頻繁に変わってしまうようで、アプリの挙動がおかしくなった。

なのでセッションごとに同じサーバーに接続する仕組みが必要。
ip_hashだとなんとなくサーバーが偏りそうな気がしたのでstickyを試す。

http://nginx.org/en/docs/http/ngx_http_upstream_module.html
ここを見ているとstickyが標準で入っているっぽいが、実際には入っていないのでNginxをビルドし直してサードパーティモジュールとして組み込む。
(Nginx Plusなら入ってるのかな?)

stickyのダウンロード先、ビルド方法は以下を参照。
https://bitbucket.org/nginx-goodies/nginx-sticky-module-ng

設定はほとんど変わらず、stickyを追記するだけ。

upstream chatserver {
    sticky;
    server xxx.xxx.xxx.xxx:3000;
    server yyy.yyy.yyy.yyy:3000;
}

今のところこれでいけそう。
ちなみに各バージョンは

Nginx : 1.6.0
Node.js : v0.10.28
Socket.IO : 0.9.17

Nodeを分散するとNodeプロセス間でのデータの共有が必要で、それにはRedisのPub/Subがよいらしい。

http://www.cyberagent.co.jp/recruit/techreport/report/id=8858#id-2013-09%E6%8F%90%E5%87%BA%E5%88%86%EF%BC%8F%E5%85%AC%E9%96%8B%E7%94%A8%EF%BC%8F%E3%82%AA%E3%83%B3%E3%83%A9%E3%82%A4%E3%83%B3%E9%80%9A%E7%9F%A5%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0-homing-%EF%BC%88%E5%8F%A4%E8%B0%B7%E8%96%AB%EF%BC%89-2-4.Redis%E3%82%B5%E3%83%BC%E3%83%90%EF%BC%88Socket.IO%E7%94%A8%EF%BC%89

以上、アリーヴェデルチ