2020年10月20日火曜日

nginx の server_names_hash_bucket_size の挙動を確認してみる

概要

server_names_hash_bucket_size ディレクティブは nginx で VirtualHost を使う場合に影響するディレクティブになります
VirtualHost として指定する server_name が長い場合などにエラーが発生することがあります
今回は server_names_hash_bucket_size の適切なサイズを見極めるために挙動を確認してみました

環境

  • macOS 10.15.7
  • nginx 1.19.3

まずは確認用のアプリを作成する

何でも OK です
今回は nginx 単体で動作確認します

nginx.conf

2 つの server ディレクティブを定義します
下が動作確認用で上は Host ヘッダが設定されていない場合のデフォルトで表示する server になります
server_names_hash_bucket_size はデフォルトの 32 で設定しています

  • vim /usr/local/etc/nginx/nginx.conf
worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile      on;
    keepalive_timeout  65;
    server_names_hash_bucket_size  32;

    server {
        listen       80;
        server_name  localhost;

        location / {
            root   html;
            index  index.html;
        }
    }

    server {
        listen       80;
        server_name  test-server.dev;

        location / {
            root   html;
            index  index2.html;
        }
    }
}

確認用 html

どちらが表示されているか確認できるないようであれば何でも OK です

  • vim /usr/local/var/www/index.html
<html>
<head>
</head>
<body>
index
</body>
</html>
  • vim /usr/local/var/www/index2.html
<html>
<head>
</head>
<body>
index2
</body>
</html>

テストしてみる

  • brew services start nginx

で起動し curl で Host ヘッダを設定し異なるコンテンツが返ってくるか確認しましょう

  • curl localhost

=> index

  • curl -H 'Host: test-server.dev' localhost

=> index2

が返ってくることを確認します

server_name を長くしてエラーが発生するか確認する

まずは could not build server_names_hash, you should increase server_names_hash_bucket_size: 64 というエラーが発生するか確認します
想定では server_name を長くすれば発生するはずです
例えば以下のように長くしてみましょう

  • vim /usr/local/etc/nginx/nginx.conf
server_name  test-server.aaaaaaaaaabbbbbbbbbbccccccccccaaaaaaaaaabbbbbbbbbbcccccccccc.dev;

76 文字あります
これで nginx を再起動してみるとうまく起動していないことが確認できます

  • brew services restart nginx

またログを見ると該当のログが表示されているのも確認できると思います

  • less /usr/local/var/log/nginx/error.log
2020/10/20 14:37:05 [emerg] 22865#0: could not build server_names_hash, you should increase server_names_hash_bucket_size: 64

ちなみにこの指示通りに server_names_hash_bucket_size: 64 に変更してもなぜかエラーは止まりませんでした
更に上の 128 を指定したところ上記の設定でも動作するを確認しています
なぜ 64 ではダメで 128 で動作するのかは謎です

ギリギリのラインを確認する

先程は 76 文字の適当な server_name を設定しました
今度はエラーになるギリギリの文字数を見つけてみます

  • vim /usr/local/etc/nginx/nginx.conf
server_name  test-server.aaaaaaaaaabbbbbbbbbbcccccccccc.dev;

上記のように 46 文字を指定したところでエラーが止まりました
これならば server_names_hash_bucket_size: 32 でも動作します
しかし一文字増やすだけで 64 でなく 128 が必要になります

別の server ディレクティブの影響を受けるのか確認する

server_name の情報をマッピングするハッシュを生成している可能性があるので別の server ディレクティブを追加してみます
まずは以下のようにしましょう

  • vim /usr/local/etc/nginx/nginx.conf
worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile      on;
    keepalive_timeout  65;
    server_names_hash_bucket_size 32;

    server {
        listen       80;
        server_name  localhost;

        location / {
            root   html;
            index  index.html;
        }
    }

    server {
        listen       80;
        server_name  test-server.aaaaaaaaaabbbbbbbbbbcccccccccc.dev;

        location / {
            root   html;
            index  index2.html;
        }
    }

    server {
        listen       80;
        server_name  new.test-server.dev;

        location / {
            root   html;
            index  index3.html;
        }
    }
}

これは server_names_hash_bucket_size: 32 でも動作しました
これだけ見ると server ディレクティブの数には影響しないように見えます
一応更に動作確認として new2, new3, new4 まで作りましたが特に問題なく動作しました

ただドキュメントを見ると server_name を大量に定義した場合は server_names_hash_max_size ディレクティブのチューニングが必要とあったのでもしかすると 50 とか 100 ほど server ディレクティブを定義すればエラーが発生するかもしれません

結論

結論としては数字と server_name の相関関係ははっきりとわかりませんでした
nginx のコードを読めばハッシュの生成方法がわかると思いますがそこまでは追っていません
なので現状は自分もとりあえずエラーが発生したら値を増やせという雑な対応しかできないところです
使用している CPU のラインキャッシュが影響するようなのでマシンによっては大きな値は設定できないという可能性もでてきそうです

参考サイト

0 件のコメント:

コメントを投稿