【发布时间】:2020-03-16 20:54:39
【问题描述】:
我正在构建一个 Sinatra 应用程序来使用 Ghostscript 处理 PDF,但是当我将它推送到 Heroku 时,它会超时,因为 Ghostscript 处理 PDF 的时间超过 30 秒。
我需要一种方法来在后台运行 Ghostscript 命令并显示加载指示器直到它完成,否则我需要不断地 ping 服务器直到处理完成。我搜索了几个星期如何完成此操作,但没有任何效果。
这是我的 POST 操作:
post '/process_pdf' do
unless params[:file] && params[:file][:tempfile] && params[:file][:filename]
return erb :form
end
@filename = params[:file][:filename].gsub!(/[^0-9A-Za-z.]/, '')
@output_file_name = "#{Time.now.strftime('%b_%d_%I_%M')}_#{@filename}"
@file = params[:file][:tempfile]
File.open("#{settings.root}/tmp/#{@filename}", 'wb') do |file|
file.write(@file.read)
file.close
end
# @pdf = GS.run("#{settings.root}/tmp/#{@filename}") do |command|
# command.option(GS::PDFA)
# command.option(GS::BATCH)
# command.option(GS::NO_PAUSE)
# command.option(GS::PROCESS_COLOR_MODEL, 'DeviceCMYK')
# command.option(GS::DEVICE, 'pdfwrite')
# command.option(GS::PDFA_COMPATIBILITY_POLICY, '1')
# command.option('CompatibilityLevel', '1.4')
# command.option('PDFSETTINGS', 'prepress')
# command.option(GS::OUTPUT_FILE,
# "#{settings.root}/tmp/#{@output_file_name}")
# end
# until @pdf.success?
# puts 'loading...'
# sleep 1
# end
Kernel.system 'gs -dPDFA -dBATCH -dNOPAUSE'\
' -sProcessColorModel=DeviceCMYK'\
' -sDEVICE=pdfwrite -sPDFACompatibilityPolicy=1'\
' -dCompatibilityLevel=1.4 -dPDFSETTINGS=/prepress'\
" -sOutputFile=#{settings.root}/tmp/#{@output_file_name}"\
" #{settings.root}/tmp/#{@filename}"
erb :process_pdf
end
并在处理完成后显示:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="<%= url("/style.css")%>">
<title>Processing PDF</title>
</head>
<body>
<%= send_file "#{settings.root}/tmp/#{@output_file_name}" %>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
</body>
</html>
在我的 POST 操作中,我尝试了多种使用 Ghostscript 处理 PDF 的方法,但在 Heroku 上的 30 秒超时内没有任何方法可以加快它的速度。我什至尝试检查 Process::Status 的 success?(这是 gs-ruby gem 提供的),但是当它甚至到达那个块时,它已经处理并且已经太晚了。
这在本地运行良好,直到它在 Heroku 上才失败,因为处理时间太长。
【问题讨论】:
-
能否提供超时错误。超时可以指很多事情。比如处理时间太长,网页没有及时回复,...
-
嘿@TinNguyen,感谢您的回复! papertrail 上的错误代码是
at=error code=H12 desc="Request timeout" method=POST path="/process_pdf" status=503 -
devcenter.heroku.com/articles/request-timeout "超时值不可配置。如果您的服务器需要超过 30 秒才能完成给定的请求,我们建议将该工作转移到后台任务或工作人员以定期 ping 您的服务器到看看处理请求是否已经完成。这种模式可以让您的 Web 进程腾出时间来做更多的工作,并减少整体应用程序响应时间。您的 PDF 处理是一个阻塞调用,因为在完成之前没有计算任何其他内容。您需要创建后台任务或单独的工作人员。
-
我知道,这就是我问这个问题的原因。使用 sinatra,添加后台任务并不像在 rails 上安装 sidekiq gem 那样容易。我还没有找到在 sinatra 中创建后台任务的好解决方案,我希望有人能推荐一下
-
虽然 Sinatra 是一个出色的服务器环境,但它的功能也不如其他环境那样全面,因此它可能无法满足您的需求。 Padrino 是我的经验的下一步,然后你进入 Rails。