发布的尼尔·布鲁克斯2019年6月27日

编译wkhtmltopdf以便在AWS Lambda函数中使用Bref比您想象的要简单

在MyBuilder,我们最近有机会参与一个新项目,这当然意味着我们可以玩所有闪亮的新玩具,我们一直渴望尝试一段时间。

我们需要从已经在另一个项目中完成的一些工作中提取一个独立的PDF生成服务。它是AWS Lambda内部运行的完美候选程序,因此也最终做出了贡献Bref生产中的一次尝试。

以前的项目用过时髦的基于模板化HTML输出生成报告,我们有更多的项目也将使用相同的解决方案。

因为我们知道我们无法预测在任何给定的时间内服务的流量(尽管晚上很可能看不到流量),我们知道它需要能够快速地向上和向下扩展。为了保持东西的整洁和独立,我们也想避免将这个服务放在我们常规的web服务器上。

法斯/ Serverless

法斯/ serverless是这类服务的一个很好的候选者(亚马逊的FaaS服务是被称为λ).使用FaaS,您将代码推入云端,等待某种事件的到来(这可能是一个HTTP请求,或事件,如添加到队列的项,或AWS允许您对的任何数量的事情)。当您等待的事件发生时,FaaS提供程序将为您调用代码并返回响应。

关键在于,当您的代码等待事件发生时,您不会为此收取费用。您只需为代码使用的资源付费当它实际运行时.此外,调用的成本是.FaaS提供程序还可以方便地为您处理伸缩问题。

考虑到整个网站倾向于闲置在服务器上等待下一个web请求,使用这种方法意味着你可以有效地关闭所有的web服务器,在很大程度上减少你的托管成本。然而,对于这个用例,我们只需要对发生的事件做出反应亚马逊SNS

Serverless PHP

Bref是一个开源项目,旨在帮助PHP开发人员让他们的应用程序在Lambda上运行。在Lambda上运行PHP利用了2018年底引入的系统AWS,称为

一开始,层系统听起来让人困惑,但关键的一点是,一层就像一个程序或二进制文件,你可以把它作为依赖“安装”到你的Lambda函数中,只要把它包含在你的FaaS配置中就可以了。您可以在Lambda函数中包含多个层(最多5层)。

对于本文的其余部分,我将假设您对Lambda和层有基本的熟悉或知识。如果你觉得很难理解这些概念我强烈建议你尝试一下使用Bref部署一个示例应用程序首先帮助您理解这些东西是如何一起发挥作用的。

滚动自己的图层

如上所述,我们在PHP应用程序中使用Snappy将HTML转换为PDF。然而,Snappy依赖于拥有wkhtmltopdf安装在运行PHP应用程序的服务器上的二进制文件。

Bref提供了基本的PHP层它允许我们运行应用程序代码,但它不提供wkhtmltopdf二进制文件,我们需要做实际的html到pdf转换。

当我们检查wkhtmltopdf下载页面我们看到没有亚马逊Linux本地版本。因此,我们有几个选择,它们是:

  1. 在互联网上找到一个预编译的兼容lambda的二进制文件,并将其包含在我们的应用程序代码中
  2. 在互联网上找到一个预编译的Lambda兼容二进制文件,并从中创建我们自己的Lambda层
  3. 编译wkhtmltopdf将自己二进制化并从中创建一个层

我们对在互联网上找到预编译的二进制文件感到紧张,包括那些在我们的代码中,有以下几个原因:

  1. 我们无法百分百确定二进制文件的创造者是否完全值得信任
  2. 我们发现的与lambda兼容的预编译二进制文件都至少有一个小版本过期

您可能已经从本文的标题中猜到了,我们选择了选项3。我对此感到兴奋,因为尽管我已经为Bref做了一段时间的贡献,但我自己还没有编译任何层(尽管这是最常被问到的问题之一Bref松弛社区).我要提醒你的是,我们第一次做这件事花了好几个小时,有几次我们走错了路。然而,我们最终还是让它工作了。这就是我们实现目标的方式。

开始的旅程

wkhtmltopdf有一个建立和包装二进制的单独回购,并附上说明。因为我们知道我们的目标是什么AmazonLinux,我们需要确保我们已经安装和运行Docker(按wkhtmltopdf指令)。

我们还需要确保我们有python-yaml安装(pip安装pyyaml如果你用的是Mac的话)git而且p7zip

构建过程要求您在主机上同时拥有打包存储库和源存储库,因此首先创建一个wkhtmltopdf-build目录把所有东西都放在一起。

mkdirwkhtmltopdf-build& &cdwkhtmltopdf-build

接下来,将两个存储库克隆到wkhtmltopdf-build父目录。

git克隆git@github.com: wkhtmltopdf / packaging.git
git克隆git@github.com: wkhtmltopdf / wkhtmltopdf.git

这将导致以下目录结构:

wkhtmltopdf-build/ |-打包|- wkhtmltopdf

确保它是独立的

我们需要创建一个静态构建,这意味着所有的依赖wkhtmltopdf在二进制文件本身中是自包含的(基本上,我们不能依赖AmazonLinuxOS为我们提供任何东西)。这些是由wkhtmltopdf作为“链接”Git存储库(子模块)。安装它们,cdwkhtmltopdf目录并运行:

git子模块更新

这把qt库导入到项目中。

令人信服的wkhtmltopdf /包装识别亚马逊Linux

到目前为止,创建这整个东西最困难的部分是弄清楚如何使用/构建。脚本来构建我们自己的二进制文件。一旦我们找到了规则,我们便能够将其归结为几个简单的步骤:

从现在起我们所做的一切都将在包装目录,我们直接进入这里:

cd包装

现在我们需要编辑build.yaml加上我们自己的AmazonLinux配置。我知道AmazonLinux是基于RedHat / CentOS的,幸运的是已经有一个centos64配置文件,所以我应该只是能够复制和修改那。

首先,我要创建一个名为AmazonLinux64.我可以离开指令与centos64,因为包应该是兼容的。

然而,我需要改变容器的一个版本AmazonLinux操作系统。的提供了Lambda Docker映像,所以我们可以只包括这些。

amazonLinux64码头工人/ Dockerfile.centos64arg游戏lambci /λ:构建

其他的都可以保持原样,所以我的最后amazonLinux64配置应该如下:

amazonLinux64码头工人/ Dockerfile.centos64arg游戏lambci /λ:构建输出rpmx86_64依赖>ca证书fontconfigfreetype的glibclibjpeglibpnglibstdc + +libX11libXextlibXrenderopensslxorg - x11 -字体- 75 dpixorg-x11-fonts-Type1zlib

启动引擎

接下来我们需要创建Docker容器,它将实际编译wkthmltopdf二进制,构建脚本为我们提供:

。/构建docker-images amazonLinux64

开始构建

现在我们准备好做二进制了。的构建脚本为我们提供了一个compile-docker选项,该选项接受源代码并在我们的AmazonLinux容器。注意有一个package-docker命令,该命令将创建rpm程序为我们归档(或. deb如果它是Debian / Ubuntu系统),但我们想要的是实际的二进制文件,而不是安装程序。

它请求构建目标的名称(amazonLinux64),源代码的相对路径(. . / wkhtmltopdf),以及您想要放置二进制文件的位置。我选择称之为wkhtmltopdf-bin

./编译编译-docker amazonLinux64 ../ wkhtmltopdf wkhtmltopdf-bin

接下来,Docker启动一个实例,安装所有依赖项,并运行编译器。这可能需要一些时间,所以在你吃午饭或睡觉前开始是一个好主意。

从二进制文件创建一个层

一旦wkhtmltopdf二进制文件已经生成(您应该可以在wkhtmltopdf-bin / wkthtmltox / bin /),您需要将它打包到一个层中,以便包含在Lambda中。我们不关心wkhtmltoimage它还生成了二进制文件,让我们把PDF二进制文件压缩一下。

邮政编码- rwkhtmltopdf.zip wkhtmltopdf

现在我们需要将zip文件上传到AWS,以便包含在Lambda函数中。如果您喜欢可视化界面,您可以使用Lambda控制台,但考虑到我们已经通过命令行完成了其他所有事情,我们不妨使用AWS CLI

awsλpublish-layer-version——图层名称mybuilder-wkhtmltopdf——描述“独立wkhtmltopdf二进制”——压缩文件wkhtmltopdf.zip

该命令将向您发回响应JSON.需要注意的是LayerVersionArn

“LayerVersionArn”“攻击:aws:λ:一来:<编辑>:层:mybuilder-wkhtmltopdf: 1”

(注意还有一个LayerArn,但我们需要LayerVersionArn因为它指向实际版本我们创建的图层)

现在,在我的template.yaml文件,我可以包括我们刚刚发布的层在我配置和Bref提供的基本PHP层:

资源PdfService类型AWS: Serverless:函数属性#……-攻击:aws:λ:一来:> <修订:层:mybuilder-wkhtmltopdf: 1-攻击:aws:λ:eu-west-1:209497400698:层:php-73:7”

如何调用二进制

AWS使您的层的内容在/ opt.所以我们需要告诉斯内普去哪找二进制文件通过将它指向我们自己编译的版本:

<?php使用Knp \时髦\ Pdf时髦的美元Pdf' / opt / wkhtmltopdf ');

在PDF生成之后,您对它所做的就是最新的。一种方法可能是将它推到S3桶中,以便稍后下载,或者可以从Lambda服务中直接将它通过电子邮件发送给客户端(AWS SES也许会派上用场)。

完成了

在这里,我们首次尝试编译一个专门用于AmazonLinux然后为那个包创建一个层,我们可以在Lambda函数中包含和使用它。封装该层远没有编译它复杂。

我们发现这是一个真的有助于理解如何为Lambda创建层,以及如何在基于Bref的无服务器PHP应用程序中使用它们。这个用例非常复杂,当然我省略了实现细节,比如我们如何接收想要转换为PDF的HTML,以及如何解码事件。这些方面在一般的无服务器文章和AWS的文档

显然,对于这个项目,我们需要包括wkhtmltopdf程序,但很多额外层的用例不需要任何额外的软件,它们可能只需要更改PHP调用方式的运行时配置。这些情况比我们在这里讨论的要简单得多,因为您可以跳过整个编译步骤,只需压缩您自己的运行时配置(我们将在后续的另一篇文章中对此进行讨论!)

向前走,PDF-ify。

工作MyBuilder

我们需要一个有经验的软件工程师,他热爱他们的手艺,并愿意分享他们来之不易的知识。

查看职位空缺
评论的Disqus
Baidu
map