AWS Lambda上的无服务器PHP

大家好 周一,第一堂课将在“ Backend PHP Developer”课程的新小组中举行。 在这方面,我们继续就该主题发表有用的材料。 让我们开始吧。



Simon Wordley一样,我认为无服务器计算是一个非常有趣的领域,这主要是由于精细的支付系统(仅在执行代码时才付款),并且您无需担心服务和准备服务器和容器的问题。 如此之多,以至于我可以使用Apache OpenWhisk的开放PHP运行时 ,该运行时的商业版本可以作为IBM Cloud的功能之一使用。

还有其他无服务器提供程序, AWS Lambda仍然是市场领导者,但是直到最近,对PHP的支持仍然非常繁琐和朴实。 随着新的Lambda 运行时API层支持,这种情况在2018年底发生了变化。

让我们看看使用Serverless Framework在Lambda上的服务器PHP的实际方面。

TL; DR


一个简单的Hello World的源代码位于我在Github上的lambda-php存储库中。 转到“ 注释”部分,我们可以继续。

PHP运行时


运行时API允许您将任何运行时与Lambda一起使用。 在某种程度上,这与OpenWhisk相似,因为无服务器平台和运行时之间存在HTTP API。 与Lambda的一大不同之处在于,运行时向平台发送请求以接收调用数据,而OpenWhisk调用运行时应提供的端点。 有关更多信息,请参阅Michael Moussa的AWS博客文章 ,这启发了我去做这一工作。

首先,我们需要Lambda的PHP运行时。 根据平台的要求,它将包括一个PHP可执行文件,调用无服务器功能的PHP代码以及一个bootstrap文件。 从这三件事中,我们收集了一层。 可以在不同的帐户中重复使用图层,因此令我惊讶的是,AWS没有为我们提供PHP帐户。 不可思议,但事实是,它们不使用PHP 7.3,因此我们将必须构建自己的PHP。
我们放在项目中的layer/php目录中的所有文件。

构建一个PHP可执行文件


我们需要一个可在Lambda容器中运行的PHP可执行文件。 最简单的方法是在与Lambda相同的平台上进行编译,因此我们将使用EC2。 Michael的文章解释了如何做到这一点,我将这些命令包装在compile_php.sh脚本中,然后将其复制到EC2实例,运行并将可执行文件复制回我的计算机:

 $ export AWS_IP=ec2-user@{ipaddress} $ export SSH_KEY_FILE=~/.ssh/aws-key.rsa $ scp -i $SSH_KEY_FILE compile_php.sh $AWS_IP:doc/compile_php.sh $ ssh -i $SSH_KEY_FILE -t $AWS_IP "chmod a+x compile_php.sh && ./compile_php.sh 7.3.0" $ scp -i $SSH_KEY_FILE $AWS_IP:php-7-bin/bin/php layer/php/php 


这种方法将使其重现性很好,并希望它将仅升级到新版本的PHP。

自举


由于我们使用运行时API,因此我们需要一个bootstrap文件。 Lambda本身需要这样的名称来指定文件;它通过循环调用API来响应与图像匹配的函数调用。

本质上,我们需要处于一个循环中并调用端点/next以了解下一步要调用什么,然后调用它,然后将答案发送给端点/response
AWS 使用curl在BASH中提供了一个示例:

 while true do HEADERS="$(mktemp)" # Get an event EVENT_DATA=$(curl -sS -LD "$HEADERS" -X GET "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next") REQUEST_ID=$(grep -Fi Lambda-Runtime-Aws-Request-Id "$HEADERS" | tr -d '[:space:]' | cut -d: -f2) # Execute the handler function from the script RESPONSE=$($(echo "$_HANDLER" | cut -d. -f2) "$EVENT_DATA") # Send the response curl -X POST "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/$REQUEST_ID/response" -d "$RESPONSE" done 


我们想在PHP中做同样的事情,尽管我可以自己写,但Pariksit Agnihotri在PHP-Lambda-Runtime / runtime.php中已经领先于我,因此我们只需将其复制到layer/php/runtime.php 。 在我的版本中,我进行了一些更改,添加了json_encoding并改进了错误处理程序。
文件layer/php/bootstrap非常简单,只需执行此文件即可运行PHP可执行文件:

 #!/bin/sh cd $LAMBDA_TASK_ROOT /opt/php /opt/runtime.php 


仅此而已。 现在,在layer / php中有三个文件:

  • php - php可执行文件;
  • runtime.php运行时API工作文件;
  • bootstrap是必需的Lambda文件。


结果,所有这些将成为Lambda应用程序中的PHP层(层)。

配置无服务器框架


无服务器框架提供了无服务器应用程序的可重复配置和部署。 我是这个概念的拥护者,并且我想使用更多这样的工具。 我们将对我们的PHP Hello World使用无服务器框架。
由于在无服务器框架中没有方便的PHP应用程序模板,因此我们只需在项目目录中创建serverless.yml文件即可。
对于初学者来说,最基本的是:

 service: php-hello-world provider: name: aws runtime: provided region: eu-west-2 memorySize: 128 


我们将调用应用程序php-hello-world并使用AWS作为提供者。 自从我在英国以来,我已经建立了伦敦地区 。 我们不需要大量的内存,因此128 MB就足够了。
运行时通常是您希望函数执行的语言。 要使用bootstrap文件将执行的runtime API ,请将此字段设置为provider
您将需要一个.gitignore文件,其中包含:

 .serverless 


由于在git我们不需要此目录。
接下来,通过添加以下内容将我们的层添加到serverless.yml

 layers: php: path: layer/php 


这将创建一个AWS层并将其命名为PhpLambdaLayer ,我们可以在函数中引用该名称。

让我们编写Hello World函数
现在,我们可以编写无服务器的PHP函数。 这必须在handler.php文件中输入:

 <?php function hello($eventData) : array { return ["msg" => "hello from PHP " . PHP_VERSION]; } 


该函数获取有关事件的信息,并返回一个关联数组。
要向Serverless Framework告知我们功能的部署,您需要将以下内容添加到serverless.yml文件中:

 functions: hello: handler: handler.hello layers: - {Ref: PhpLambdaLayer} 


无服务器框架为一个应用程序支持多种功能。 它们每个都有一个名称(在本例中为hello ),在本例中是一个处理程序,即不带扩展名的文件名,后跟一个点,然后是此文件中的函数名。 因此, handler.hello处理程序意味着我们将在handler.php运行hello()函数。
最后,我们还向PHP层报告函数,以便它可以执行PHP代码。

在Lambda中部署


要扩展其功能,请运行以下命令:

 $ sls deploy 


如果命令的执行时间尽可能长,则将获得与此类似的输出:



履行我们的职能


部署后,我们可以使用以下命令调用该函数:

 $ sls invoke -f hello -l 




大功告成!

总结一下


有了新的层和运行时API,您现在可以轻松地在Lambda中运行PHP无服务器功能。 对于与AWS绑定的PHP开发人员而言,这是个好消息。

朋友们,等待您的评论!

Source: https://habr.com/ru/post/zh-CN453116/


All Articles