Nginx のアップストリーム応答時間が時々非常に遅くなる

Nginx のアップストリーム応答時間が時々非常に遅くなる

大量のトラフィックと多数のサイトを処理する Ubuntu サーバーを所有していますが、Nginx の応答に非常に長い時間がかかることがあります (20 ~ 30 秒かかることもありますが、通常はその前にリクエストがタイムアウトします)。最初は、トラフィックの急増と Passenger の処理がうまくいっていないことが原因だと思いましたが、その後、Passenger を Puma に置き換えてトラフィックの負荷を分散しましたが、それでも同じことが起こります。

Nginx Amplify は、nginx.upstream.response.timeたとえば 14 秒のように、タイプが高すぎるというアラートを送信します。

セットアップの概要は次のとおりです。

  • サーバー #1 (時々応答が遅くなるサーバー) には、300 以上のサイト用の Nginx サーバー ブロックがあります。
  • サーバーproxy_passは、サーバー #1 上のロード バランサー サーバー ブロック (sites.myapp.com) にブロックします。
  • ロードバランサは、このサーバ#1(重み1)とサーバ#2(重み2)の間でトラフィックを分割し、2倍の量のトラフィックがサーバ#2に送られるようにします。
  • サーバー #1 と #2 の両方に、ロード バランサーからのトラフィックを受信し、proxy_passそれを Puma がアプリのインスタンスを提供するために使用する UNIX ソケットに送信する別のサーバー ブロックがあります。

これらすべてに関連する構成は以下にあります。この問題のトラブルシューティング方法はわかりませんが、プロキシ バッファリングをオフにしたり、プロキシ バッファ サイズを変更したりするなど、サーバー ブロックに改善できる構成があるかどうか疑問に思っています。

この原因は何なのか、また、問題を追跡するにはどうすればよいのか、何かご存知ですか? Nginx の応答が非常に遅くなると、トラフィックがサーバー 2 に再ルーティングされなくなります。

すべてのサイトのサーバー ブロック/SSL とロード バランサーを別のサーバーに移動して、少なくともサーバー 1 が低速応答フェーズを通過しているときにトラフィックがサーバー 2 に渡されるようにする必要があることはわかっていますが、現時点ではこれらの 2 つのサーバーしかありません。

サイト設定の例:

server {
  server_name www.somesite.com;

  location / {
    proxy_pass                      https://sites.myapp.com;
    proxy_set_header                X-Real-IP       $remote_addr;
    proxy_set_header                X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header                Cookie $http_cookie;
    proxy_set_header                WLDOMAIN www.somesite.com;
    proxy_cookie_domain             .myapp.com .somesite.com;
    proxy_pass_request_headers      on;
    rewrite ^/(.*)$ /sites/12345/$1 break;
  }
}

ロードバランサの簡略化された構成:


upstream cluster {
  ip_hash;
  server X.X.X.X:1234 weight=1; #internal ip of server #1
  server Y.Y.Y.Y:1234 weight=2; #internal ip of server #2
}

server {
  server_name sites.myapp.com;
  
  location / {
    try_files $uri @app;
  }

  location @app {
    proxy_pass http://cluster;

    proxy_next_upstream error timeout invalid_header http_429 http_500 http_502 http_503 http_504;

    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Host $http_host;

    proxy_headers_hash_max_size 512;
    proxy_headers_hash_bucket_size 128;

    proxy_redirect off;
  }
}

アップストリームの簡略化された構成:

upstream puma {
  server unix:///var/www/myapp/shared/sockets/puma.sock;
}

server {
  listen 1234;

  root /var/www/myapp/public;

  location / {
    try_files $uri @app;
  }

  location @app {
    proxy_pass http://puma;

    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Host $http_host;

    proxy_headers_hash_max_size 512;
    proxy_headers_hash_bucket_size 128;

    proxy_redirect off;
  }

}

この問題は、セットアップが、proxy_passロード バランサーを間に配置するのではなく、さまざまなサイトのサーバーがアップストリームへのトラフィックをブロックし、アプリが Puma ではなく Passenger によって提供されるだけだったときにすでに発生していたことに注意してください。

念のため言っておきますが、このアプリは Ruby on Rails です。

答え1

したがって、Nginx でデバッグ出力をオンにした後、問題はnginx-extrasPhusion Passenger のパッケージ内の Nchan モジュールにあったようです。このモジュールにはバグがあり、時々ハングしていましたが、Passenger を削除して (Puma に置き換えて) に置き換えてからは、nginx-extrasそのnginx問題は発生していません。

関連情報