2026年9月7日

2026年9月7日

Nginxのupstreamでweightを設定してサーバーごとの振り分け比率を変える方法

Nginxで複数のバックエンドサーバーに負荷分散するとき、upstream ブロックの server に weight を付けると、サーバーごとにリクエストを振り分ける比率を変えられます。性能の違うサーバーを混ぜて使う場合や、新しいサーバーに少しずつリクエストを流したい場合に使います。

この記事の設定と振り分けの結果は、2026年10月時点のNginx 1.30.6(Docker公式イメージ nginx:stable)で確かめています。負荷分散の基本設定はNginxで負荷分散を設定する方法を参照してください。

weightの基本

weight は server の後ろに書きます。書かなければ1です。

upstream backend {
    server 192.168.1.101;            # weight=1(既定値)
    server 192.168.1.102 weight=3;
}

server {
    listen 80;
    server_name example.com;

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

既定の振り分け方式(重み付きラウンドロビン)では、各サーバーが受け取るリクエストの割合は「そのサーバーのweight ÷ 全サーバーのweightの合計」になります。この例では合計が4なので、192.168.1.101 が4分の1(25%)、192.168.1.102 が4分の3(75%)です。

upstream ブロックは http ブロックの中(Debian/Ubuntuなら /etc/nginx/conf.d/ や sites-available の設定ファイル)に、server ブロックの外に書きます。

比率の計算例

4台のサーバーに次のweightを付けた場合の割合です。

upstream backend {
    server 192.168.1.101;            # weight=1
    server 192.168.1.102 weight=3;
    server 192.168.1.103 weight=2;
    server 192.168.1.104 weight=2;
}
サーバー weight 割合
192.168.1.101 1 1/8(12.5%)
192.168.1.102 3 3/8(37.5%)
192.168.1.103 2 2/8(25%)
192.168.1.104 2 2/8(25%)

weightは比率だけが意味を持つので、weight=2 と weight=4 の組み合わせは weight=1 と weight=2 と同じ割合になります。

実際の振り分け順

重み付きラウンドロビンは、weightの大きいサーバーに連続して送るのではなく、なるべく間を空けて混ぜながら振り分けます。

検証では、3台のバックエンド(A、B、C)がそれぞれ自分の名前を返すようにし、ワーカープロセス1つで14回リクエストを送りました。

upstream backend3 {
    server 127.0.0.1:8081 weight=5;   # A
    server 127.0.0.1:8082;            # B
    server 127.0.0.1:8083;            # C
}

結果は A A B A C A A の7回が2周し、7回ごとにAが5回、BとCが1回ずつでした。前の節の1対3の例では、B A B B B A B ... のように4回に1回がweight=1のサーバーでした。

ワーカープロセスが複数ある場合

upstream に zone を書いていない場合、振り分けの状態は各ワーカープロセスが別々に持ちます。ワーカープロセスが複数あると、少ない回数で試したときに比率どおりに並ばないことがありますが、リクエスト数が増えれば全体としては設定した比率に近づきます。ワーカープロセス間で状態を共有したい場合は、upstream ブロックに zone を書きます。

upstream backend {
    zone backend 64k;
    server 192.168.1.101;
    server 192.168.1.102 weight=3;
}

振り分けの確かめ方

検証用に、バックエンドとして自分の名前を返すだけのサーバーを用意すると、振り分けを目で確かめられます。

server { listen 8081; return 200 "A\n"; }
server { listen 8082; return 200 "B\n"; }
server { listen 8083; return 200 "C\n"; }
for i in $(seq 1 20); do curl -s http://127.0.0.1/; done | sort | uniq -c

本番のバックエンドで確かめる場合は、アクセスログに振り分け先を記録します。$upstream_addr に、実際に転送したサーバーのアドレスが入ります。

log_format upstream_log '$remote_addr [$time_local] "$request" $status '
                        'upstream=$upstream_addr rt=$upstream_response_time';
access_log /var/log/nginx/upstream.log upstream_log;
grep -o 'upstream=[^ ]*' /var/log/nginx/upstream.log | sort | uniq -c

log_format は http ブロックに、access_log は server ブロックに書きます。ログの書式はNginxのログ書式をカスタマイズする方法も参照してください。

weightと組み合わせて使う設定

least_conn

least_conn を書くと、接続数がもっとも少ないサーバーに送ります。このときもweightが考慮されます。

upstream backend {
    least_conn;
    server 192.168.1.101;
    server 192.168.1.102 weight=3;
}

ip_hash もバージョン1.3.1/1.2.2以降はweightを指定できます。振り分け方式の違いはNginxの負荷分散アルゴリズムの種類を参照してください。

down:一時的に外す

メンテナンスなどでサーバーを振り分けから外すときは、weightを0にするのではなく down を付けます。weight=0 は書けず、nginx -t で次のエラーになります。

nginx: [emerg] invalid parameter "weight=0" in /etc/nginx/conf.d/default.conf:2
upstream backend {
    server 192.168.1.101 weight=2;
    server 192.168.1.102 down;
}

backup:ほかが使えないときだけ使う

backup を付けたサーバーには、ほかのサーバーがすべて使えないときだけリクエストが送られます。検証でも、通常のサーバーが動いている間はbackupのサーバーに1回も送られませんでした。

upstream backend {
    server 192.168.1.101 weight=2;
    server 192.168.1.102;
    server 192.168.1.103 backup;
}

backup は hash、ip_hash、random の方式とは一緒に使えません。ip_hash と組み合わせると、次のエラーになります。

nginx: [emerg] balancing method does not support parameter "backup" in /etc/nginx/conf.d/default.conf:3

max_failsとfail_timeout:応答しないサーバーを一時的に外す

オープンソース版のNginxは、実際のリクエストが失敗したことでサーバーの異常を判断します(定期的にバックエンドを確かめるアクティブなヘルスチェックは、有償のNGINX Plusの機能です)。fail_timeout の時間内に max_fails 回失敗すると、そのサーバーは fail_timeout の間、振り分けから外れます。既定値は max_fails=1、fail_timeout=10s です。

upstream backend {
    server 192.168.1.101 weight=2 max_fails=3 fail_timeout=30s;
    server 192.168.1.102          max_fails=3 fail_timeout=30s;
}

設定を反映する

sudo nginx -t
sudo systemctl reload nginx

nginx -t で syntax is ok と test is successful が表示されてから reload します。reloadは処理中の接続を切らずに新しい設定に切り替えるので、weightの変更に再起動(restart)は不要です。

うまくいかないとき

症状 確かめること
比率どおりに振り分けられない ワーカープロセスが複数あり zone が無いか。試した回数が少なすぎないか。ip_hash や hash を使っていると、同じクライアントは同じサーバーに送られる
特定のサーバーにまったく送られない down や backup が付いていないか。max_fails によって外れていないか(エラーログに upstream のエラーが出ていないか)
nginx -t がエラーになる weight=0 や負の値を書いていないか。backup を hash/ip_hash/random と一緒に使っていないか

エラーログは /var/log/nginx/error.log に出ます。

まとめ

weight は upstream の server に付ける振り分け比率で、既定値は1、割合は「weight ÷ 合計」です。重み付きラウンドロビンでは比率どおりに混ぜながら振り分けられ、least_conn でもweightが考慮されます。サーバーを外すときは weight=0 ではなく down を使い、予備のサーバーには backup を付けます。変更後は nginx -t で確かめてから systemctl reload nginx で反映し、$upstream_addr をログに出して実際の振り分けを確かめます。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲