Know How Guide and Hands on Guide for AWS
Guide AWS Lambda Custom Runtime for PHP
Launch a EC2 instance supported by AWS Lambda runtimes: amzn-ami-hvm-2018.03.0.20181129-x86_64-gp2 https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html
Build Php runtime
# Update packages and install needed compilation dependencies
sudo yum update -y
sudo yum -y install autoconf bison gcc gcc-c++ libcurl-devel libxml2-devel
# Compile OpenSSL v1.0.1 from source, as Amazon Linux uses a newer version than the Lambda Execution Environment, which
# would otherwise produce an incompatible binary.
wget http://www.openssl.org/source/openssl-1.0.1k.tar.gz
tar -zxf openssl-1.0.1k.tar.gz
cd openssl-1.0.1k
./config && make && sudo make install
cd ~
# Download the PHP 7.3.0 source
mkdir ~/php-7-bin
wget https://github.com/php/php-src/archive/php-7.3.0.tar.gz
tar -zxf php-7.3.0.tar.gz
cd php-src-php-7.3.0
# Compile PHP 7.3.0 with OpenSSL 1.0.1 support, and install to /home/ec2-user/php-7-bin
./buildconf --force
./configure --prefix=/home/ec2-user/php-7-bin/ --with-openssl=/usr/local/ssl --with-curl --with-zlib
make install
# Verify all went well
/home/ec2-user/php-7-bin/bin/php -v
# PHP 7.3.0 (cli) (built: Jun 15 2020 14:26:43) ( NTS )
# Copyright (c) 1997-2018 The PHP Group
# Zend Engine v3.3.0-dev, Copyright (c) 1998-2018 Zend Technologies
mkdir -p ~/php-example/{bin,src}/
cd ~/php-example
touch ./src/{hello,goodbye}.php
touch ./bootstrap && chmod +x ./bootstrap
cp ~/php-7-bin/bin/php ./bin
tree /home/ec2-user/php-example/
# /home/ec2-user/php-example/
# ├── bin
# │ └── php
# ├── bootstrap
# └── src
# ├── goodbye.php
# └── hello.php
# 2 directories, 4 files
Since the Lambda environment’s responsibility will be limited to simply starting and shutting down our custom runtime API, it’s up to us to define what is actually going to happen in the Lambda environment once that runtime API starts up. The bootstrap script will be what handles these Init and Invoke phases.
curl -sS https://getcomposer.org/installer | ./bin/php
./bin/php composer.phar require guzzlehttp/guzzle
composer fund
command to find out more!
2. Build the bootstrap
Lambda will place the files from our various layers under /opt, so our /home/ec2-user/php-example/bin/php file will ultimately end up being /opt/bin/php
`bootstrap` script
```php
#!/opt/bin/php
<?php
// This invokes Composer's autoloader so that we'll be able to use Guzzle and any other 3rd party libraries we need.
require __DIR__ . '/vendor/autoload.php';
// Making a GET request to the runtime API to obtain the next Lambda invocation that needs to be serviced.
function getNextRequest()
{
$client = new \GuzzleHttp\Client();
$response = $client->get('http://' . $_ENV['AWS_LAMBDA_RUNTIME_API'] . '/2018-06-01/runtime/invocation/next');
return [
'invocationId' => $response->getHeader('Lambda-Runtime-Aws-Request-Id')[0],
'payload' => json_decode((string) $response->getBody(), true)
];
}
// Grab the request payload to supply request parameters to our functions. We’ll retrieve those and return a simple associative array to make these values available to the caller.
function sendResponse($invocationId, $response)
{
$client = new \GuzzleHttp\Client();
$client->post(
'http://' . $_ENV['AWS_LAMBDA_RUNTIME_API'] . '/2018-06-01/runtime/invocation/' . $invocationId . '/response',
['body' => $response]
);
}
// This is the request processing loop. Barring unrecoverable failure, this loop runs until the environment shuts down.
do {
// Ask the runtime API for a request to handle.
$request = getNextRequest();
// Obtain the function name from the _HANDLER environment variable and ensure the function's code is available.
$handlerFunction = array_slice(explode('.', $_ENV['_HANDLER']), -1)[0];
require_once $_ENV['LAMBDA_TASK_ROOT'] . '/src/' . $handlerFunction . '.php';
// Execute the desired function and obtain the response.
$response = $handlerFunction($request['payload']);
// Submit the response back to the runtime API.
sendResponse($request['invocationId'], $response);
} while (true);
?>
src/hello.php:
<?php
function hello($data)
{
return "Hello, {$data['name']}!";
}
?>
src/goodbye.php:
<?php
function goodbye($data)
{
return "Goodbye, {$data['name']}!";
}
?>
2. Create IAM Role
/tmp/trust-policy.json:
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
aws iam create-role \
--role-name LambdaPhpExampleRole \
--path "/service-role/" \
--assume-role-policy-document file:///tmp/trust-policy.json \
--region us-west-2
LambdaPhpExampleRole=
php_example_runtime_arn=
aws lambda publish-layer-version
–layer-name php-example-vendor
–zip-file fileb://vendor.zip
–region us-west-2
php_example_vendor_arn=
4. Deploy sample function
```bash
aws lambda create-function \
--function-name php-example-hello \
--handler hello \
--zip-file fileb://./hello.zip \
--runtime provided \
--role $LambdaPhpExampleRole \
--layers $php_example_runtime_arn $php_example_vendor_arn \
--region us-west-2
aws lambda create-function \
--function-name php-example-goodbye \
--handler goodbye \
--zip-file fileb://./goodbye.zip \
--runtime provided \
--role $LambdaPhpExampleRole \
--layers $php_example_runtime_arn $php_example_vendor_arn \
--region us-west-2
aws lambda invoke
–function-name php-example-goodbye
–region us-west-2
–log-type Tail
–query ‘LogResult’
–output text
–payload ‘{“name”: “World”}’ goodbye-output.txt | base64 –decode
cat hello-output.txt #Hello, World!
cat goodbye-output.txt #Goodbye, World!
aws lambda invoke
–function-name php-example-hello
–region us-west-2
–log-type Tail
–query ‘LogResult’
–output text
–payload ‘{“name”: “SecondCall”}’ hello-output.txt | base64 –decode
aws lambda invoke
–function-name php-example-goodbye
–region us-west-2
–log-type Tail
–query ‘LogResult’
–output text
–payload ‘{“name”: “SecondCall”}’ goodbye-output.txt | base64 –decode
## Cleanup
```bash
aws lambda delete-function --function-name php-example-goodbye
aws lambda delete-function --function-name php-example-hello
aws lambda delete-layer-version --layer-name php-example-runtime --version-number 1
aws lambda delete-layer-version --layer-name php-example-vendor --version-number 1
Terminate the EC2 instance