{Pengenalan Serverless} {Pengenalan AWS Lambda} {Serverless PHP} {Serverless Deployment} {Serverless Demo} {Profiling Lambda Function}*
Menjalankan kode aplikasi tanpa perlu memikirkan server (autoscaling dkk).
Dalam konteks ini adalah Function as a Service (FaaS).
{Zero Administration} {Bayar per Eksekusi} {Idle = Gratis} {Auto-Scaling} {Microservice sejak awal} {Event-Driven} {Faster time to market}
Yang akan kamu kerjakan
Task | VM | Serverless |
Manage Auto-Scaling | ✓ | ⤫ |
Konfigurasi Server | ✓ | ⤫ |
Manage OS | ✓ | ⤫ |
Bayar Running Cost | ✓ | ⤫ |
Upload Kode | ✓ | ✓ |
Layanan Serverless dari AWS yang mendukung penggunaan kode NodeJS, Python, Java, Go, .NET Core, Ruby dan Custom Runtime.
Biaya dihitung per 100ms durasi waktu dan Σ eksekusi.
Gabungan dari sistem operasi, bahasa pemrograman dan pustaka-pustaka lain yang dibutuhkan untuk menjalankan kode.
def my_handler(event, context):
return {
"message": "Hello World"
}
{
"resource": "/",
"path": "/",
"httpMethod": "GET",
"requestContext": {
"resourcePath": "/",
"httpMethod": "GET",
"path": "/Prod/",
...
},
"headers": {
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"accept-encoding": "gzip, deflate, br",
"Host": "70ixmpl4fl.execute-api.us-east-2.amazonaws.com",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36",
"X-Amzn-Trace-Id": "Root=1-5e66d96f-7491f09xmpl79d18acf3d050",
...
},
"multiValueHeaders": {
"accept": [
"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
],
"accept-encoding": [
"gzip, deflate, br"
],
...
},
"queryStringParameters": null,
"multiValueQueryStringParameters": null,
"pathParameters": null,
"stageVariables": null,
"body": null,
"isBase64Encoded": false
}
Tidak ada :( #justkidding
Bref adalah Runtime PHP, Framework dan deployment tool agar PHP dapat dijalankan di AWS Lambda.
Dibuat dari amazonlinux:2018.03 Docker image
Layer | Cocok untuk |
---|---|
php-* | PHP Function (from scratch) |
php-*-fpm | Website/Framework |
console | Console (CLI) |
App | Tipe | Lambda Layer |
Terbilang | HTTP API | bref php-73 |
SQL Query Browser | Normal Web | bref php-73-fpm |
New File Notification* | S3 Event | bref php-73 |
What is My IP* | HTTP API + Normal Web | bref php-73 |
*) Hanya menggunakan Bref PHP Runtime tanpa Bref Framework
Sebuah layanan HTTP API yang akan mengubah angka "123" menjadi bentuk terbilang "seratus dua puluh tiga".
$ cat composer.json
{
"require": {
"bref/bref": "^0.5.29",
"rioastamal/terbilang": "^1.0"
}
}
$ composer install -vvv
$ ./vendor/bin/bref init
What kind of lambda do you want to create? (you will be able to add more functions later by editing `serverless.yml`) [PHP function]:
[0] PHP function
[1] HTTP application
[2] Console application
> 0
<?php declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use RioAstamal\AngkaTerbilang\Terbilang;
/**
* @param array $event
* @see https://docs.aws.amazon.com/lambda/latest/dg/services-apigateway.html for example
* @return callable
*/
return function ($event)
{
$angka = $event['queryStringParameters']['angka'] ?? '0';
$options = isset($event['queryStringParameters']['pretty']) ? JSON_PRETTY_PRINT : 0 ;
$response = [
'angka' => $angka,
'terbilang' => Terbilang::create()->t($angka)
];
return json_encode($response, $options);
};
$ serverless deploy
$ curl --get -d 'angka=1500,004,300' -d 'pretty' [END_POINT]
{
"angka": "1500,004,300",
"terbilang": "satu milyar lima ratus juta empat ribu tiga ratus"
}
Sebuah web app untuk melakukan query pada MySQL dan menampilkan hasilnya secara langsung.
$ cd terraform/
$ export AWS_PROFILE=YOUR_PROFILE AWS_DEFAULT_REGION=YOUR_REGION
$ terraform apply
Outputs:
database = {
"connect" = "mysql -u awsug -h [HOST_NAME] -p serverlessphp"
"endpoint" = "[HOST_NAME]:3306"
"engine" = "mysql 5.7.26"
}
$ cat composer.json
{
"require": {
"bref/bref": "^0.5.29",
}
}
$ composer install -vvv
$ ./vendor/bin/bref init
What kind of lambda do you want to create? (you will be able to add more functions later by editing `serverless.yml`) [PHP function]:
[0] PHP function
[1] HTTP application
[2] Console application
> 1
<?php
$dsn = $_POST['dsn'] ?? '';
$username = $_POST['username'] ?? 'root';
$password = $_POST['password'] ?? '';
$query = $_POST['query'] ?? '';
$pdo = null;
function exec_query($pdo, $query)
{
if (empty($query)) {
return '// Result will be shown here';
}
$counter = 0;
try {
echo '<table>';
foreach ($pdo->query($query, PDO::FETCH_ASSOC) as $row) {
// --- HEADING --- //
if ($counter === 0) {
echo '<thead><tr>';
foreach ($row as $key => $val) {
printf('<td>%s</td>', $key);
}
echo '</tr></thead><tbody>';
}
// --- /HEADING --- //
echo '<tr>';
foreach ($row as $val) {
printf('<td>%s</td>', $val);
}
echo '</tr>';
$counter++;
}
echo '</tbody></table>';
} catch (PDOException $e) {
printf('<pre>Error: %s</pre>', $e->getMessage());
}
}
if ($dsn) {
try {
$pdo = new PDO($dsn, $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
}
?><!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Query Browser on AWS Lambda</title>
<style type="text/css">
label {
display: block;
}
div.label-wrapper {
width: 300px;
}
table {
border-collapse: collapse;
width: 100%;
}
thead td {
background-color: #f1f1f1;
font-weight: bold;
}
tr td {
border: 1px solid #ccc;
padding: 4px 8px;
}
</style>
</head>
<body>
<h2>Query Browser on AWS Lambda</h2>
<form method="post">
<label>MySQL DSN</label>
<input type="text" name="dsn" placeholder="mysql:dbname=testdb;host=127.0.0.1" style="width: 300px;" value="<?= $dsn ?>">
<label>Username / Password</label>
<input type="text" name="username" placeholder="MySQL Username" value="<?= $username; ?>">
<input type="password" name="password" placeholder="MySQL Password" value="<?= $password; ?>">
<br><br>
<label>SQL Query</label>
<textarea style="width: 99%;height: 200px; font-size: 24px; color: blue;" name="query"><?= htmlentities($query) ?></textarea>
<input type="submit" value="RUN">
</form>
<hr>
<?php exec_query($pdo, $query) ?>
</body>
</html>
$ serverless deploy
Sebuah fungsi Lambda yang akan mengirimkan notifikasi ke email jika ada file baru pada bucket tertentu.
$ bash build.sh
> Creating zip file into build/function.zip ...
Generating autoload files
Generated autoload files
< Lambda function has been zipped.
$ bash deploy.sh
...
Outputs:
demo = {
"mailhog" = {
"ec2_ip" = "18.139.0.199"
"mailhog_auth" = "user = teknocerdas | password = orang.cerdas"
"ssh_access" = "ssh -i ~/.ssh/teknocerdas.key -o LogLevel=quiet -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null [email protected]"
"url" = "https://mailhog.teknocerdas.com"
}
"s3_bucket" = {
"butcket_name" = "awsug06-sub-demo"
"create_example" = "aws s3 cp ./YOUR_FILE.ext s3://awsug06-sub-demo/"
}
}
#!/bin/sh
# Main entry point for Lambda execution
# Fail on error
set -e
# Outer main loop for execution.
# So if there's next event it will get execute it immediately
while true
do
# All errors to STDOUT so it can be captured to CloudWatch
/opt/bin/php "$_HANDLER" 2>&1
done
$ aws s3 cp /some/file.ext s3://[BUCKET_NAME]/