{id: intro}
{id: serverless}
-
Function as a Service - FaaS
-
0 cost for deployment
-
$ for usage
-
No root access, just a simple function (or application)
-
No server maintenance costs.
{id: what-is-it-good-for}
- For short batch processes (5 min limit)
- ETL
- Real time data stream collection and manipulation
- Scheduled jobs (cron-jobs)
- REST API web endpoints
- Bots
{id: aws-lambda-limits}
-
5 minutes execution
-
disk capacity 500 MG
-
1024 threads
-
3Gb memory
-
50 MB deployment zip
{id: development}
- In the Lambda console using Cloud9
- Local environment
- Local environment using SAM
{id: how-faas-fork}
Trigger (Event Source) -> Function -> Resources (output)
{id: event-sources}
- Supported Event Sources
- Amazon API Gateway
- Scheduled Events
- Amazon S3
- Amazon DynamoDB
- Amazon Simple Email Service
- ...
{id: function}
- Python 2.7 and 3.6
- Node.JS 6.10 and 8.10
- Java 8
- C# .NET Core
- Go 1.x
{id: resources-for-output}
- See IAM - Identity and Access Management for more resources
- S3
- Amazon DynamoDB
- SES - Simple Email Service
- SNS - Simple Notification Service (Sending SMS)
- Redshift (Data warehouse)
- ElastiCache clusters
- RDS - Relational Database Service
- ...
- External services
{id: create-account}
- Create Free Account
- You will have to supply a credit card, but AWS provides a Free tier.
- You will need to supply a phone number and they will call you.
{id: aws-lambda}
-
Log in
-
Pick a region: e.g. N. Virginia us-east-1
{id: task-1}
- Create script in Python that can be accessesed via curl.
{id: hello-world}
-
Press "Create function"
-
Name: "hello"
-
Runtime: Python 3.6
-
Role: Create new role from template(s)
-
Role name: "myrole"
-
Policy templates: Basic Edge Lambda Permission
-
Press "Create function"
The default code will look like this:
- Test it (click on "Test")
- First it will make you create a new test-case.
{id: api-gateway}
-
"Add triggers" - select API Gateway
-
Configure Required
-
Create a new API
-
API name: demo
-
Deployment stage: v0
-
Security: Open
-
Once we "save" it, we'll be able to see the "Invoke URL"
-
https://s94rb025f9.execute-api.us-east-1.amazonaws.com/v0/hello
-
curl ...
ERROR 502 Bad Gateway
or
{"message": "Internal server error"}
{id: add-header}
- The function needs to return a dictionary with the status code and the headers.
- At least the Content-type.
- curl ...
{id: send-json}
- curl ...
{"message": "Hello World!"}
{id: event-details}
- curl ...
{id: exercise-1}
- Create your own hello function.
{id: task-2}
- Accept parameter in the GET request and echo it back
{id: accept-parameters}
- Save and Click "Test"
- Observe the error
{
"errorMessage": "'queryStringParameters'",
"errorType": "KeyError",
"stackTrace": [
[
"/var/task/lambda_function.py",
4,
"lambda_handler",
"name = event['queryStringParameters']['name']"
]
]
}
- Our Python code is not safe enough, we assume a field "name" to be passed in.
{id: error-via-the-api}
-
Before we fix the code, let's see what happens if we access the URL using
curl
? -
curl ...
{"message": "Internal server error"}
-
To see the error log, visit:
-
Monitoring
-
Invocation errors
-
Jump to logs
{id: test-event-for-api-gateway}
- Before we fix the code, we can fix the test:
{
"queryStringParameters" : {
"name": "Foo Bar"
}
}
- Try this using the "Test" button.
Also, try it from the console using curl
or in your browser (use your own URL).
{"message": "Hello Foo Bar!"}
{id: exercise-2}
-
Fix the Python code so even if the user does not supply the "name" field it still won't crash.
-
Instead make it return a JSON structure with status "400 Bad Request"
-
Use
curl -I
orcurl -D err.txt
to check the headers as well. -
Create another function that will accept 2 numbers (parameters a and b) and add them together returning a JSON that looks like this:
{
'a' : 23,
'b' : 19,
'op' : '+'
'result' : 42
}
{id: solution-2-echo}
{id: solution-2-add}
{id: task-3}
- Create an application that has more than one files.
{id: multi-file-application-json}
- Create a file called a.json with some JSON content in it.
- Change the code to read the file and return it
{id: multi-file-application-module}
{id: local-development}
mkdir project
cd project
vim lambda_function.py
zip ../project.zip *
- Upload a .ZIP file.
- Save.
- Try it using
curl
.
{id: exercise-3}
-
Create a 'calculator' application that accepts two numbers 'a' and 'b' and an 'operation' that can be either 'add' or 'multiply'.
-
Return the appropirate result.
-
Create it on you computer in two files. A main web serving file and a module with two functions 'add' and 'multiply'
-
On your local computer create a directory for a project.
-
In the directory create a file called 'lambda_function.py' this will hold the main function.
-
Create also a file called 'mymodule.py'.
-
Upload the whole thing using zip.
{id: solution-3-calc}
{id: task-4}
{id: development-machine}
- Levenshtein distance
- Using pylev which is pure Python.
mkdir app_pylev
cd app_pylev
pip install pylev -t pypi
zip -r ../project.zip *
curl 'https://qspmdah6oj.execute-api.us-east-1.amazonaws.com/v0/hello?a=abd&b=acx'
{id: must-supply-either-home-or-prefix-exec-prefix-not-both}
On OSX you might get the above error. Create the 'setup.cfg' file.
{id: third-party-not-pure-python}
- editdistance is a Levenshtein distance module written in C++ and Cython
- See
- Needs a linux box either locally or on Amazon AWS.
{id: docker-to-build}
docker build -t aws .
- In the project directory:
rm -rf pypi
docker run -v $(pwd):/opt --rm aws pip install -r requirements.txt -t pypi
zip -r ../project.zip *
- Upload the zip file.
{id: exercise-4}
-
Web Client: A function that uses 'requests' to fetch a URL and return the text of the page.
-
A function that will accept the name of two cities.
-
Call the API of Open Weather Map and return the temprature difference in the two places.
{id: web-client}
pip install -r requirements.txt -t pypi
zip -r ../project.zip *
curl 'https://qspmdah6oj.execute-api.us-east-1.amazonaws.com/v0/hello?url=https://httpbin.org/get'
{id: s3-storage}
-
Buckets - (all the users share a single name-space for buckets, so a lot of them are already taken)
-
Create a bucket in s3 (eg. your-name)
-
Add permission to the role Attach policy AmazonS3FullAccess
{id: list-s3-bucket}
{id: s3-write-object-from-lambda}
{id: read-s3-object}
{id: trigger-lambda-by-s3}
Trigger by using:
aws s3 cp data.json s3://szabgab/new/data.json
Download the resulting file using
aws s3 cp s3://szabgab/out.json .
{id: handl-s3-event-in-lambda}
{id: exercise-5}
-
Create a function that can be triggered by a URL request passing in parameters like this: ?name="Foo Bar"
-
Create an object in S3 called something like "in/time.json" (with the current time)
-
Create another function that will be triggered by a newaobject with a perfix "in/"
-
Load that object and creare a new object called "out/time.json" using the same object name, but adding 3 new fields to it called
new_time: the time portion of the name of the object
end_time: the time when we read the object in the second function.
elapsed: the difference.
{id: aws-resources}
{id: resources}