利用可能なファイル ハンドルをすべて使い果たした https 経由の nginx サーバー (更新: 無限ループ?)

利用可能なファイル ハンドルをすべて使い果たした https 経由の nginx サーバー (更新: 無限ループ?)

Sinatra を使って https で動作する nginx サーバーがあります。Mongrel と http (s なし) で問題なく動作する構成で jnlp ファイルをダウンロードしようとすると、nginx サーバーは 504 エラーでファイルを提供できません。その後のログの確認では、このエラーは使用可能なファイル ハンドルの数のオーバーフロー、つまり「24: 開いているファイルが多すぎます」が原因であることがわかります。

sudo lsof -p <nginx worker pid>

次のような膨大なファイルリストが表示されます:

nginx   1771 nobody   11u     IPv4           10867997         0t0      TCP localhost:44704->localhost:https (ESTABLISHED)
nginx   1771 nobody   12u     IPv4           10868113         0t0      TCP localhost:https->localhost:44704 (ESTABLISHED)
nginx   1771 nobody   13u     IPv4           10868114         0t0      TCP localhost:44705->localhost:https (ESTABLISHED)
nginx   1771 nobody   14u     IPv4           10868191         0t0      TCP localhost:https->localhost:44705 (ESTABLISHED)
nginx   1771 nobody   15u     IPv4           10868192         0t0      TCP localhost:44706->localhost:https (ESTABLISHED)
nginx   1771 nobody   16u     IPv4           10868255         0t0      TCP localhost:https->localhost:44706 (ESTABLISHED)
nginx   1771 nobody   17u     IPv4           10868256         0t0      TCP localhost:44707->localhost:https (ESTABLISHED)
nginx   1771 nobody   18u     IPv4           10868330         0t0      TCP localhost:https->localhost:44707 (ESTABLISHED)
nginx   1771 nobody   19u     IPv4           10868331         0t0      TCP localhost:44708->localhost:https (ESTABLISHED)
nginx   1771 nobody   20u     IPv4           10868434         0t0      TCP localhost:https->localhost:44708 (ESTABLISHED)

開くことができるファイルの数を増やしても、nginx がその制限をすぐに超えてしまうため、役に立ちません。利用可能なすべてのファイルを取得するために、何らかのループが発生しているように見えるのも不思議ではありません。

何が起こっているのか、またそれをどう修正すればよいのか、何かご存知ですか?

編集:nginx 0.7.63、Ubuntu Linux、Sinatra 1.0

編集2:問題となっているコードは次のとおりです。これは Sinatra が JNLP を提供しているもので、ようやく判明しました。

get '/uploader' do
  #read in the launch.jnlp file                                                               
  theJNLP = ""
  File.open("/launch.jnlp", "r+") do |file|
    while theTemp = file.gets
      theJNLP = theJNLP + theTemp
    end
  end                                                                    
  content_type :jnlp
  theJNLP
end

これを Mongrel と http 経由で Sinatra で提供すると、すべて正常に動作します。これを https 経由で Sinatra と nginx で提供すると、上記のエラーが発生します。Web サイトのその他の部分はすべて同等のようです。

編集:それ以来、passenger 2.2.14、ruby 1.9.1、nginx 0.8.40、openssl 1.0.0a にアップグレードしましたが、変化はありません。

編集:原因は、SSL の使用による無限リダイレクトのようです。サーバーのルート ディレクトリに jnlp ファイルをホストする以外に、これを修正する方法はわかりません (一度に 1 つの jnlp ベースのアプリケーションに制限されるため、これは避けたいです)。

nginx.conf からの関連行:

# HTTPS server                                                                            
#                                                                                         
server {                                                       
    listen       443;                                                
    server_name   MyServer.org
    root         /My/Root/Dir;
    passenger_enabled on;
    expires           1d;

    proxy_set_header X-FORWARDED_PROTO https;
    proxy_set_header X_FORWARDED_PROTO https;#the almighty google is not clear on which to use   


   location /upload {
      proxy_pass https://127.0.0.1:443;
   }
}   

これに関して面白いのは、まず、jnlp を 'upload' ではなく 'uploader' というディレクトリに置いていたのですが、それでも proxy_pass ディレクティブがログに表示されたので、問題を引き起こしているように見えたことです。次に、jnlp をルートに移動すると、ssl によるプロキシがまったくなかったため、問題は回避されました。

では、nginx で無限 proxy_pass ループを回避するにはどうすればよいでしょうか?

答え1

nginx はポート 443 でリッスンしています。 へのリクエストを受け取ると/uploader、ポート 443 にプロキシします。これが nginx です。別のポートでリッスンしている sinatra アプリにプロキシする必要があるようです。 nginx についてはよくわかりませんが、正しくないようです。

関連情報