Ruby on Rails 6.0部署Heroku时PDF生成性能问题及优化方案问询
Heroku Ruby on Rails 6.0 站点PDF生成性能优化方案
疑问解答
- 后台任务相关:后台任务可以解决Heroku路由默认30秒的请求超时问题,避免用户侧触发请求直接失败,但确实无法缩短PDF本身的生成耗时,可搭配站内信、邮件通知的方式告知用户生成结果,优化使用体验。
- 增加worker相关:该方案合理,但仅能提升并发处理能力,无法优化单任务的生成速度。按你当前每分钟10次的请求量,若单任务耗时优化到10秒内,2个worker即可稳定承载所有请求,无需过度扩容。
- 替代方案相关:可优先选用纯Ruby实现的
prawn库,无需依赖wkhtmltopdf、puppeteer等大型二进制依赖,slug体积可减少200MB以上,针对图片相册这类结构简单的PDF,生成速度比wkhtmltopdf快3~5倍,内存占用仅为原有方案的1/3。也可将PDF生成逻辑抽离到无服务层部署,不占用Heroku dyno资源,也不会增大本地slug体积。 - 缓存相关:虽然无法做永久存储,但可设置10~15分钟的短期缓存,同一用户短时间内重复请求相同内容时可直接返回缓存结果,避免重复生成,能大幅降低无效性能开销。
现有wicked_pdf代码优化方案
你当前的代码可做以下调整,预计可将生成耗时降低60%以上,内存占用减少一半:
def book_pdf # 此处新增:预处理所有图片,先将外部图片下载到本地临时目录,压缩到适配A4横向的分辨率(最大2480px宽)后再传入模板,不要直接在模板里加载外部高清图 # code to generate the picture list and title of the gallery # respond_to do |format| format.html format.pdf do render pdf: @model_name.parameterize, orientation: "Landscape", page_size: 'A4', show_as_html: false, disposition: 'attachment', # 替换HTML模板头/脚为静态参数,减少额外webkit渲染开销 header: { right: '[page]/[topage]', font_size: 9, spacing: 5 }, footer: { center: '相册生成时间:' + Time.now.strftime("%Y-%m-%d"), font_size: 8 }, quality: 50, # 新增以下两个参数,关闭不需要的渲染逻辑 disable_smart_shrinking: true, javascript: false, # 移除zoom参数,关闭智能收缩后不需要额外缩放适配 layout: "pdf.html" end end end WickedPdf.config = { layout: 'pdf.html.erb', print_media_type: true, page_size: 'A4', encoding: 'utf-8', # 新增配置,禁止加载不必要的外部资源 no_stop_slow_scripts: true }
重度使用场景替换方案
若优化后仍无法满足性能要求,建议切换为prawn库实现,核心逻辑示例如下:
# Gemfile添加 gem 'prawn' def book_pdf pdf = Prawn::Document.new(page_size: 'A4', orientation: :landscape) # 遍历图片列表,每页放2张 @picture_list.each_with_index do |pic, idx| pdf.start_new_page if idx > 0 && idx % 2 == 0 # 下载压缩后的图片到临时文件 temp_pic = Down.download(pic.url) pdf.image temp_pic.path, fit: [pdf.bounds.width, pdf.bounds.height/2 - 10] temp_pic.unlink end send_data pdf.render, filename: "#{@model_name.parameterize}.pdf", type: 'application/pdf', disposition: 'attachment' end
内容的提问来源于stack exchange,提问作者Roberto Boldi
相关产品推荐
相关产品推荐

