nginx mirror module の罠?の話
注意
- nginx v1.24.0で確認しています。
- ソースコードを呼んだとかではないので、利用する際には十分検証を行ってください。
内容
Nginx には、ミラーモジュール ( ngx_http_mirror_module ) というモジュールがあり、
server { listen :80; location /mirror { internal; proxy_pass http://origin2; } location / { mirror /mirror proxy_pass http://origin1; } }
このような ForwardProxy の設定を行うことで
[Client] -> [nginx] -+-------------------> [origin1] `- - -(mirror)- - -> [origin2]
このように origin1
にリクエストを行いつつ、同様のリクエストを origin2
にも行い、origin2
のレスポンスは無視することができるというものです。
しかし、実際に使ってみると罠?と思われる挙動が合ったので、ここにメモしておきます。
🪤1:ミラー側が遅延するとレスポンスが遅延する
以下のように origin1 と origin2 のレイテンシが異なる場合、遅い方に引きずられます。
[Client] -> [nginx] <---+--(100ms)--> [origin1] +--(300ms)--------------> [origin2]
負荷試験など、遅いレイテンシに引きずられたくない場合は、以下のように、mirror側にタイムアウト設定を実施すると回避できます。
server { listen :80; location /mirror { internal; proxy_pass http://origin2; proxy_connect_timeout 100ms; proxy_read_timeout 100ms; proxy_send_timeout 100ms; } location / { mirror /mirror proxy_pass http://origin1; } }
🪤2:ミラー側のKeepAliveが有効にならない
以下のように、origin1 / origin2ともにKeepAliveの設定を設定しているにも関わらず、
server { listen :80; location /mirror { internal; proxy_http_version 1.1; proxy_set_header Connection ""; proxy_pass http://origin2; } location / { mirror /mirror proxy_http_version 1.1; proxy_set_header Connection ""; proxy_pass http://origin1; } }
以下のように、mirror側のKeepAliveが有効にならず都度接続増えてしまう場合、
[Client] ---> [nginx] <-+--(KeepAlive有効)----> [origin1] +--(KeepAlive無効)----> [origin2]
mirrorの中ではKeepAliveが有効にならないようなので、別サーバとしてKeepAliveを有効にして、proxy_passの先に指定することで回避することが可能です。
upstream nginx_proxy_socket { unix:/var/run/nginx-proxy.sock } server { listen unix:/var/run/nginx-proxy.sock location / { internal; proxy_http_version 1.1; proxy_set_header Connection ""; proxy_pass http://origin2; } } server { listen :80; location /mirror { internal; proxy_http_version 1.1; proxy_set_header Connection ""; proxy_pass http://nginx_proxy_socket$request_uri; } location / { mirror /mirror proxy_http_version 1.1; proxy_set_header Connection ""; proxy_pass http://origin1; } }