我有一个Play Framework应用程序(Play 2.8,Scala 2.13和Java 8),该应用程序使用Apache PDFBox 2从上载的PDF文件创建JPG缩略图。缩略图是根据请求创建的,然后缓存在文件系统上。但是,当一个用户尝试显示包含许多未缓存缩略图的PDF的图库时,会同时创建一堆缩略图,并且服务器因OutMemoryError崩溃而崩溃(似乎同时执行5或6个任务就足够了)。服务器会自动重新启动,并在几十秒后再次可用,但是正在创建的缩略图已损坏,我不得不面对许多不可用的地方。
PDFBox配置为使用临时文件,但是在渲染缩略图时会发生内存不足。
该服务器只有2 GB的可用RAM。上载的PDFS每个约为1 MB,生成的缩略图约为100 KB(72 DPI;大小约为500×1000 px)。我可以在不增加堆大小的情况下解决此问题吗?理想情况下,Play应该能够自动将这些占用大量内存的请求放入队列,但是我可以通过某种方式手动限制同时发生的占用大量内存的任务的数量来实现生活……
最简单的方法可能是将专用的ExecutionContext
与基本的固定大小线程池一起使用来生成缩略图。
import java.nio.file.Path
import java.util.concurrent.Executors
import scala.concurrent.{ ExecutionContext, Future }
object RenderPDF {
implicit val ec : ExecutionContext = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(3 /* adjust */))
def thumbnail(pdf: Path) : Future[Path] = Future {
... // call PDFbox
}
}
您可以在动作处理程序中使用它来减轻缩略图的生成。
如果您要处理上传的PDF,最好预先渲染缩略图,因为这样可以避免用户打开图库时突然不得不渲染数十个PDF的问题。