问题现象
有个生成pdf的接口,到处pdf为空;docker环境必现,但是本地环境无法复现
1、代码增加各处错误判断,发现docker环境调用接口出现
Loading pages (1/6)
[> ] 0%
[======> ] 10%
[======================> ] 37%
[========================> ] 41%
[==============================> ] 50%
[====================================> ] 61%
[======================================================> ] 90%
signal: killed
2、查看docker系统日志
dmesg|grep "kill"
发现oom
查看资料后显示wkhtmltopdf创建pdf会造成高内存分配
优化pdf参数,问题得到解决
// Configure PDF generator with memory-saving options
pdfg, err := wkhtmltopdf.NewPDFGenerator()
if err != nil {
return nil, fmt.Errorf("PDF generator initialization failed: %w", err)
}
pdfg.PageSize.Set(wkhtmltopdf.PageSizeA4)
pdfg.Dpi.Set(96) // 1、设置dpi,降低内存使用
pdfg.NoCollate.Set(true) // Disable collation to reduce memory
pdfg.Grayscale.Set(false)
// Configure page with memory optimization settings
page := wkhtmltopdf.NewPageReader(r)
page.LoadErrorHandling.Set("ignore")
page.JavascriptDelay.Set(2000) // Allow time for JS to execute
pdfg.AddPage(page)
// Set environment variables for memory constraints
os.Setenv("QTWEBKIT_SETTINGS", "MaximumPages=1") //2、限制同时处理的页数,避免内存峰值
os.Setenv("QTWEBKIT_MAX_MEMORY", "256M") // Limit WebKit memory usage
// Create PDF with timeout
// 3、增加超时判断
pdfCtx, pdfCancel := context.WithTimeout(context.Background(), 5*time.Minute)
defer pdfCancel()
errChan := make(chan error, 1)
go func() {
defer close(errChan)
errChan <- pdfg.Create()
}()
select {
case err := <-errChan:
if err != nil {
return nil, fmt.Errorf("PDF generation failed: %w", err)
}
case <-pdfCtx.Done():
return nil, fmt.Errorf("PDF generation timed out")
}
// Return the generated PDF
return pdfg.Bytes(), nil