📜 ⬆️ ⬇️

Serverless PHP on AWS Lambda

Hello. Already on Monday, the first lesson in the new group “Backend Developer in PHP” course will take place. In this regard, we continue to publish useful material on the topic. Let's start.



Like Simon Wordley , I believe that serverless computing is an extremely interesting area, primarily because of the granular payment system (pay only when your code is executed), and you do not need to worry about servicing and preparing servers and containers. So much so that I work with the open PHP Runtime for Apache OpenWhisk , the commercial version of which is available as one of the IBM Cloud features.
')
There are other serverless providers, and AWS Lambda is the market leader, but until recently PHP support was extremely cumbersome and unsightly. This changed at the end of 2018 with a new Lambda runtime API and layer support .

Let's look at the practical aspects of serverless PHP on Lambda with a Serverless Framework .

TL; DR


The source code for a simple Hello World is in my lambda-php repository on Github. Go to the Notes section, and we can continue.

PHP runtime


The runtime API allows you to use any runtime with Lambda. In a sense, this is similar to the work of OpenWhisk, since there is an HTTP API between serverless platform and runtime. There is one big difference that with Lambda, runtime sends a request to the platform to receive call data, whereas OpenWhisk calls the endpoint that runtime should provide. For more information, see the Michael Moussa article on the AWS blog , which inspired me to do this work.

To get started, we need a PHP runtime for Lambda. It will consist of a PHP executable file, PHP code to call the serverless function, and a bootstrap file, as required by the platform. From these three things we collect the layer. Layers can be reused in different accounts, so I am surprised that AWS does not provide us with a PHP account. Unbelievable, but true, they do not use PHP 7.3, so we will have to build our own.
All files we put in the directory layer/php in our project.

Building a PHP Executable


We need a PHP executable file that will run inside Lambda containers. The easiest way to do this is to compile it on the same platform as Lambda, so we will use EC2. Michael's article explains how to do this, and I wrapped these commands in the compile_php.sh script, so that I could copy it into an EC2 instance, run it and copy the executable file back to my computer:

 $ 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 


This approach will make it well replicable, and hopefully it will just update to new versions of PHP.

Bootstrapping


Since we are using the runtime API, we will need the bootstrap file. This file name is required by Lambda itself, it is responsible for calling the function, corresponding to the images by calling the API in a loop.

In essence, we need to be in a loop and call the end point /next to understand what to call next, call it, and then send the answer to the end point /response .
AWS provides an example in BASH using curl :

 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 


We want to do the same in PHP, and although I could write it on my own, Parikshit Agnihotri already beat me to PHP-Lambda-Runtime / runtime.php , so we just copy it to layer/php/runtime.php . In my version, I made a few changes, added json_encoding and improved the error handler.
The layer/php/bootstrap file is very simple, and all that is required of it is to run the PHP executable file with this file:

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


That's all. Now we have three files in layer / php:



In the end, all this will become the PHP Layer (layer) in our Lambda application.

Serverless Framework Setup


Serverless Framework provides repeatable configuration and deployment of serverless applications. I am a fan of this concept and I want to use more of these tools. We will use the Serverless Framework for our PHP Hello World.
Since there is no convenient template for PHP applications in the Serverless Framework, we simply create the serverless.yml file in the directory with our project.
For a start, the most basic:

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


We will call our application php-hello-world and use AWS as the provider. Since I am in the UK, I established the region of London . We do not need a lot of memory, so 128 MB will be enough.
Runtime is usually the language in which you want your function to be executed. To use the runtime API that our bootstrap file will execute, you set this field to provided .
You will .gitignore need a .gitignore file containing:

 .serverless 


Because we don’t need this directory in git .
Next, let's add our layer to serverless.yml by adding:

 layers: php: path: layer/php 


This will create an AWS layer and give it the name PhpLambdaLayer , which we can refer to in our function.

Let's write the Hello World function
Now we can write our serverless PHP function. It is necessary to enter in the file handler.php :

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


The function takes information about the event and returns an associative array.
To inform the Serverless Framework about the deployment of our feature, add the following to the serverless.yml file:

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


Serverless Framework supports multiple functions for a single application. Each of them has a name, in this case hello , and, in our case, a handler, which is the name of the file without an extension, followed by a dot, and then the name of the function in that file. Thus, handler.hello means that we will run the hello() function in handler.php .
Finally, we also report functions about our PHP layer so that it can execute PHP code.

Deploy to Lambda


To expand our function with its layer, we run the following command:

 $ sls deploy 


If the command is continued for a long time, an output similar to this will be received:



Perform our function


After deployment, we can call the function using the command:

 $ sls invoke -f hello -l 




And everything is ready!

Let's sum up


Thanks to new layers and the runtime API, you can now easily run serverless PHP functions in Lambda. This is great news for PHP developers tied to AWS.

We are waiting for your comments, friends!

Source: https://habr.com/ru/post/453116/


All Articles