You need to enable JavaScript to run this app. Ruby on Rails 6.0部署Heroku时PDF生成性能问题及优化方案问询
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.18 23:24:01