読者です 読者をやめる 読者になる 読者になる

うまいぼうぶろぐ

linuxとhttpdとperlのメモ

nginxでngx_http_upstream_hash_moduleを有効にする

  • ngx_http_upstream_hash_module

upstreamディレクティブでbackendのサーバに振り分ける際に、特定の変数(のハッシュ値)パーシステンスできるモジュール。デフォルトではremote addr(ソースIP)でパーシステンスするip_hashがある。

使用できる変数はここ。

パーシステンス

  • デフォルトのip_hashの設定
upstream backend {
  ip_hash;
  server 192.168.0.1;
  server 192.168.1.1;
} 
  • ngx_http_upstream_hash_module

リクエストURIで振り分け先を指定する場合。

upstream backend {
  hash $request_uri;
  server 192.168.0.1;
  server 192.168.1.1;
} 

install

patchの適用
20100505追記

2010/05/05 時点のnginx-0.7.65 と nginx_upstream_hash-0.3.1 だと、そのままpatch適用できたので↓の内容は不要。

src/http/ngx_http_upstream.hにpatchを当てる必要があるらしい。が、用意されているのはnginx 0.7.11用なので、最新版にはpatch適用できなかった。patchの中身を見てみた。

$ cat nginx.patch
diff -Naur src/http/ngx_http_upstream.h src-hash/http/ngx_http_upstream.h
--- src/http/ngx_http_upstream.h        2008-03-03 12:04:06.000000000 -0800
+++ src-hash/http/ngx_http_upstream.h   2008-06-07 13:01:37.000000000 -0700
@@ -90,6 +90,10 @@

     ngx_array_t                    *servers;   /* ngx_http_upstream_server_t */

+    ngx_array_t                    *values;
+    ngx_array_t                    *lengths;
+    ngx_uint_t                      retries;
+
     ngx_uint_t                      flags;
     ngx_str_t                       host;
     u_char                         *file_name;

ngx_http_upstream_srv_conf_s構造体に

ngx_array_t                    *values;
ngx_array_t                    *lengths;
ngx_uint_t                      retries;

の3行を追加しているだけのようだ。てーことは最新版用のパッチはこうなるのかな。

$ diff -u src/http/ngx_http_upstream.h.org src/http/ngx_http_upstream.h
--- src/http/ngx_http_upstream.h.org    2009-06-08 16:44:47.000000000 +0900
+++ src/http/ngx_http_upstream.h        2009-06-08 16:45:36.000000000 +0900
@@ -104,6 +104,9 @@

     ngx_array_t                     *servers;  /* ngx_http_upstream_server_t */

+    ngx_array_t                     *values;
+    ngx_array_t                     *lengths;
+    ngx_uint_t                       retries;
     ngx_uint_t                       flags;
     ngx_str_t                        host;
     u_char                          *file_name;
patch適用
# cd nginx-0.7.59
# patch -p0 < ../path/to/nginx.patch
moduleを足してコンパイル
# ./configure --add-module=path/to/upstream/hash/directory
# make && make install

実験

  • nginx.conf
  upstream backend {
    hash $request_uri;
    server 192.168.0.1:8080;
    server 192.168.0.2:8080;
  }
nginx configtest
  • patch適用前

hashディレクティブなんかないよ、と怒られる。

# /etc/init.d/nginx configtest
[emerg]: unknown directive "hash" in /usr/local/nginx/conf/nginx.conf:24
configuration file /usr/local/nginx/conf/nginx.conf test failed
  • patch適用後
# /etc/init.d/nginx configtest
the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
configuration file /usr/local/nginx/conf/nginx.conf test is successful
アクセスしてみる
  • nginx.conf
  upstream backend {
    hash $request_uri;
    server 192.168.0.1:8080;
    server 192.168.0.2:8080;
  }

  location / {
      proxy_pass      http://backend;
  }
  • backend server

とりあえず自分のIPアドレスを出すcgiを用意。

$ curl http://192.168.0.1:8080/test.cgi
192.168.0.1
$ curl http://192.168.0.2:8080/test.cgi
192.168.0.2


PATHINFOを色々かえてnginxにアクセス。

$ echo {0..1000} | sed -e 's/ /\n/g' | xargs -i curl http://nginx.example.com/test.cgi/{} 2>/dev/null
192.168.0.1
192.168.0.2
192.168.0.1
192.168.0.2
192.168.0.2
192.168.0.1
192.168.0.2
192.168.0.1
192.168.0.2
192.168.0.1
192.168.0.2

request_uriでハッシュしているので、特定のbackendに偏らずにばらばらに出てくれば成功。ip_hashだとソースIPでパーシステンスなので、どちらか1つのbackendにしかいかない。