当使用 Nginx 代理时,Rails 应用程序无法提供 PDF 服务
我希望有人能够阐明这一点。我们有一个 Rails 2 应用程序,可以使用 wicked_pdf 库生成 PDF。我们正在由 nginx 代理的 unicorn 下运行该应用程序。
问题是,每当应用程序尝试提供 PDF 时,它就会超时,并且 nginx 会报告 404。我已经通过 unicorn 端口检查了该应用程序,它工作正常,所以这是 unicorn 和 nginx 之间发生的事情导致此失败。
日志文件没有报告任何有用的信息。应用程序日志仅正常报告所有内容,但不输出 Sending data
行。 nginx 日志报告*443上游在从上游客户端读取响应标头时过早关闭连接
。
unicorn 错误日志报告连接超时,worker 被终止,但 PDF 生成不需要 30 秒:
worker=2 PID:14099 timeout (31s > 30s), killing
reaped #<Process::Status: pid=14099,signaled(SIGKILL=9)> worker=2
worker=2 ready
我觉得我们在站点的 nginx 配置中遗漏了一些内容,但我不确定从哪里开始寻找。
我已经包含了下面的 nginx 配置:
server {
listen *:80;
server_name server_name.example.com;
root /var/apps/application/current/public;
try_files /system/maintenance.html $uri $uri/index.html @app;
location @app {
proxy_pass http://unix:/tmp/application.sock;
proxy_set_header Host $http_host;
}
error_page 404 400 500 502 /error.html;
location = /error.html {
root /var/www;
}
}
I'm hoping somebody might be able to shed some light on this. We have a Rails 2 app that generates PDF's using the wicked_pdf library. We're running the app under unicorn proxied by nginx.
The trouble is that whenever the app tries to serve a PDF it just times out and nginx reports a 404. I've checked the app via the unicorn port and it works fine so it's something happening between unicorn and nginx that's causing this to fail.
Log files are not reporting anything useful. The application log just reports everything normally but doesn't output the Sending data
line. The nginx log reports *443 upstream prematurely closed connection while reading response header from upstream, client
.
The unicorn error log reports that the connection is timing out and the worker is being killed, but the PDF generation does not take 30 seconds:
worker=2 PID:14099 timeout (31s > 30s), killing
reaped #<Process::Status: pid=14099,signaled(SIGKILL=9)> worker=2
worker=2 ready
I feel like we've missed something in the nginx configuration for the site, but I'm not sure where to start looking.
I've included the nginx config below:
server {
listen *:80;
server_name server_name.example.com;
root /var/apps/application/current/public;
try_files /system/maintenance.html $uri $uri/index.html @app;
location @app {
proxy_pass http://unix:/tmp/application.sock;
proxy_set_header Host $http_host;
}
error_page 404 400 500 502 /error.html;
location = /error.html {
root /var/www;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
尝试在您的环境文件中进行设置:
注意:这适用于 Nginx,不适用于 Apache。
Try setting this in you environment file:
Note: this works for Nginx, not Apache.
好吧,经过几个小时的摸索,我终于解决了这个问题。
当我将超时设置得足够大时,PDF 最终会通过,这表明它在其他地方发生了超时。最终发现我正在访问 PDF 布局文件中的 request.env['HTTP_HOST'] 来创建图像的绝对路径。这导致 wkhtmltopdf 尝试连接回错误主机名的服务器,但失败。
解决方案是将其替换为绝对文件系统路径。
Ok, after a few hours of poking around I've finally solved this one.
When I set the timeouts to be big enough the PDF would eventually come through, which pointed to it being a timeout somewhere else. It eventually turned out that I was accessing request.env['HTTP_HOST'] in the layout file for the PDF to create an absolute path for an image. This was causing wkhtmltopdf to try and connect back to the server on the wrong hostname and it was failing.
The solution was to swap it out for an absolute file system path.