因此,我有一个使用 Sinatra 通过 https 工作的 nginx 服务器。当我尝试下载 jnlp 文件时,其配置在 Mongrel 和 http(无 s)上工作正常,但 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 来提供此服务,则会出现上述错误。网站的所有其他部分似乎都相同。
编辑:此后,我已升级到 Passenger 2.2.14、ruby 1.9.1、nginx 0.8.40、openssl 1.0.0a,但没有任何变化。
编辑:罪魁祸首似乎是由于使用 SSL 而导致的无限重定向。我不知道如何解决这个问题,除了将 jnlp 文件托管在服务器的根目录中(我不想这样做,因为它限制我一次只能使用一个基于 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 放入名为“uploader”而不是“upload”的目录中,但这似乎仍然会触发问题,因为该 proxy_pass 指令出现在日志中。其次,再次将 jnlp 移到根目录中可以避免此问题,因为由于 ssl 而不存在任何此类代理。
那么,如何避免 nginx 中的无限 proxy_pass 循环?
答案1
nginx 正在监听端口 443。当您收到请求时/uploader
,您会代理到...端口 443。这就是 nginx。似乎您应该代理到您的 sinatra 应用程序,而该应用程序正在监听其他端口?我不太了解 nginx,但看起来不对劲。