AWS Lambda functions

What do they do? Do they do things? Let's find out!


A talk by Vladimir Šetka
The Software Engineering Department of billigflieger.de

What is AWS Lambda? How does it work? Why should you care to know more?

Lambda is a new type of compute abstraction, a building block of serverless architecture

Lambda

10 to 20 minutes later...

Under the hood

  • Containerized: spun up on-demand
    • Linux VMs
    • Specialized containers
    • Isolated runtimes (Node.js, Java, Python)
    • Sandboxed (cgroups, seccomp)
  • Stateless, no persistence
    • Instances Hibernate/freeze and thaw
    • Memory state preservation not guaranteed

Why should you care about serverless?

$

AWS Lambda overview

  • Containerized: spun up on-demand
  • Stateless, no persistence
  • No control over the environment
  • Language support: JavaScript (Node), Java, Python
  • Suited for short, stateless operations
  • Work best if traffic is not too spiky

Case study: Ranking thousands of data rows in realtime

Problem

  • Ranking flight optimality
  • Dozen search requests, 20 providers, 200-2000 results per provider
  • Backend in Node.js (single thread)

Solution 1

  • VMs in multiple zones
  • Clusters of workers
  • Messaging over RabbitMQ

Solution 2

  • Worker as a Lambda function
  • Direct invocation

5.364.000 invocations per month (estimated)

Lambda

~1 s duration per invocation on average

Lambda

The good stuff

  • Function as a deployment and scaling unit
  • Not dealing with machines, VMs or containers, simplified deployment
  • Reduced operational cost (16% of VM solution)
  • Reduced deployment complexity (provisioning)
  • Automatic horizontal scaling with quick reaction to traffic spikes
  • Forces more pure functional architecture
  • First million invokes are free

The bad stuff

  • Possible multi-tenancy issues (security, robustness)
  • Configuration must be externalized
  • Ecosystem lock-in
  • Vague restrictions, behaviour, documentation
  • Monitoring and debugging options limited
  • Startup costs
  • Random timeouts (corrupted instances) ~1%

Creating a Lambda function

Function example


'use strict';
console.log('Loading function');

exports.handler = (event, context, callback) => {
    // event is our payload
    console.log('first param', event.param1);
    console.log('second param', event.param2);

    // context provides extra information
    console.log('', context);

    // after we're done, we call the callback
    callback(null, event.key1);
};

Packaging

  • Zip files (with dependencies)
  • Upload (S3, aws-cli, Web GUI, Jenkins plugin...)
  • Native dependencies are fine, statically and dynamically linked (and executing binaries)
  • Available seconds after deploy / upload
filename.js
package.json
node_modules/async
node_modules/async/lib
node_modules/async/lib/async.js
node_modules/async/package.json

Deployment - Create

  • Define region and name the function
  • IAM Execution role ensures proper permission context
  • Specify hander (filename + function name)
  • Specify runtime
aws lambda create-function \
--region eu-central-1 \
--function-name my-function \
--zip-file fileb://my-function.zip \
--role arn:aws:iam::472899049124:role/my-lambda-execution-role \
--handler filename.handler \
--runtime nodejs4.3

Deployment - Update

  • Specify function to be updated
  • Support for versioning and version aliasing (green / blue deployment)
aws lambda update-function-code \
--function-name bas-ranking-lambda \
--zip-file fileb://bas-ranking-lambda.zip \
--publish

Green-Blue Deployment Switch

Lambda

Execution

  • Triggered by an event source: S3, Kinesis, DynamoDB, Cloudtrail, SNS
  • Invoked directly through AWS SDK
  • Invoke via HTTP Gateway (can throttle individual users or requests, protects against DDoS, provides a caching layer)
  • Scheduled

Best practices

Most important points

  • Write pure functions, remain stateless
  • Extract logic to a lib, code in handler minimal
  • Avoid variables outside the scope of the handler
  • Ensure +rx permissions on your files
  • Minimize the use of startup code
  • Use CloudWatch monitoring to view and optimize request latencies
  • Delete old Lambda functions that are no longer used

Minimal handler

exports.handler = (event, context, callback) => {
  let lib = require('myLib');

  lib.do(event.params)
    .then((res) => callback(null, res));
};

Lambda Client wrapper

let aws = require('aws-sdk');

module.exports.do = (data) => {
  aws.lambda(data);
};

Client execution

let client;

if (config.rpc) {
  client = require('./rpc.js');
} else if (config.lambda) {
  client = require('./lambda.js');
}

client.do({ some: 'data' });

Where to go from here?

Interesting use cases

Articles

Check out the alternatives

  • OpenWhisk - Available on IBM's Bluemix cloud
  • Google Cloud Functions
  • Azure Functions

Thank you