Serverless
The pros and cons of building a company
without infrastructureย
Luciano Mammino
1 June 2017, Split
Who is LUCIANO
NeBK20FUA
-20% eBook
ย
NpBK15FUA
-15% Print
ย
fancy a coupon? ๐
</ shameless-self-promotion >
Agenda
What is Serverless
History & definition
Advantages & costs
How it Works
Example: AWS Lambda
Example: Serverless Framework
Serverless at Planet 9
Architecture
Security
Quality
Monitoring / Logging
Step Functions
PART 1
What is Serverless
1996 - Let's order few more servers for this rack...
2006 - Let's move the infrastructure in "the cloud"...
2013 - I can "ship" the new API to any VPS as a "container"
TODAY - I ain't got no infrastructure, just code "in the cloud" baby!
The essence of the serverlessย trend is the absence of the server concept during software development.
ย
โ Auth0
Serverless & Serverless.com Framework
๐จโ๐ป ย Focus on business logic, not on infrastructure
๐ ย Virtually โinfiniteโ auto-scaling
๐ฐ ย Pay for invocation / processingย time
Advantages of serverless
Is it cheaper to go serverless?
... It depends
Car analogy
Cars are parked 95% of the time (loige.link/car-parked-95)
How much do you use the car?
Own a car
(Bare metal servers)
Rent a car
(VPS)
City car-sharing
(Serverless)
Less than $0.40/day
for 1 execution/second
What can we build?
๐ฑ ย Mobile Backends
๐ ย APIs & Microservices
๐ฆ ย Data Processing pipelines
โก๏ธ ย Webhooks
๐คย Bots and integrations
โ๏ธ ย IoT Backends
๐ป ย Single page web applications
The paradigm
Event โ ๐
IF ________________________________ THEN ________________________________
"IF this THEN that" model
A new CSV file is saved in the object storage
Process it and save it in the DB
HTTP request: GET /products
Retrieve products from DB and return a JSON
It's 2 AM
Scrape weather forecast for next days
Cloud providers
IBM
OpenWhisk
AWS
Lambda
Azure
Functions
Cloud Functions
Auth0
Webtask
Serverless and JavaScript
Frontend
๐ Serverless Web hosting is static, but you can build SPAs
(React, Angular, Vue, etc.)
ย
Backend
๐ Node.js is supported by every provider
โก๏ธ Fast startup (as opposed to Java)
๐ฆ Use all the modules on NPM
๐ค Support other languages/dialects
(TypeScript, ClojureScript, ESNext...)
exports.myLambda = function (
event,
context,
callback
) {
// get input from event and context
// use callback to return output or errors
}
Anatomy of a Node.js lambda on AWS
Let's build a "useful"
Hello World API
// write code here
'use strict'
exports.helloWorldHandler = (event, context, callback) => {
const name =
(event.queryStringParameters && event.queryStringParameters.name) ?
event.queryStringParameters.name : 'Split';
const response = {
statusCode: 200,
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({message: `Hello ${name}`})
};
callback(null, response);
};
๐ค
API Gateway config has been generated for us...
Recap
-
Login to AWS Dashboard
-
Create new Lambda from blueprint
-
Configure API Gateway trigger
-
Configure Lambda and Security
-
Write Lambda code
-
Configure Roles & Publish
โก๏ธReady!
No local testing ๐ช ... Manual process ๐ซ
Enter the...
Get serverless framework
npm install --global serverless@latest
sls --help
Create a project
mkdir helloWorldApi
cd helloWorldApi
touch handler.js serverless.yml
// handler.js
'use strict';
exports.helloWorldHandler = (event, context, callback) => {
const name =
(event.queryStringParameters && event.queryStringParameters.name) ?
event.queryStringParameters.name : 'Split';
const response = {
statusCode: 200,
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({message: `Hello ${name}`})
};
callback(null, response);
};
# serverless.yml
service: sls-helloWorldApi
provider:
name: aws
runtime: "nodejs6.10"
functions:
helloWorld:
handler: "handler.helloWorldHandler"
events:
- http:
path: /
method: get
Local test
touch event.json
{
"queryStringParameters": {
"name": "Tim Wagner"
},
"httpMethod": "GET",
"path": "/"
}
Local test
Deploy the lambda
Recap
-
Install serverless framework
-
Create handler & serverless config
-
Test locally (optional)
-
Deploy
-
Party hard! ๐ค
PART 2
Serverless at Planet 9
a Big Data company
E.g. Meter readings per customer/year
2 ร 24 ร 365
Half Hours
ร 25
~ meter reading points
ร 24
~ data versions
= ๐ฉloadโข
of data
๐ฉโ๐ Limited number of โFull stackโ engineers
โก๏ธ Write & deploy quality code fast
๐ป Experiment different approaches over different features
๐ Adopt hot and relevant technologies
ย
Limited number of servers = LIMITED CALLS AT 2 AM!
Why Serverless
Current infrastructure
Serverless land
Web
API & Jobs
Messaging
Serverless
Frontend & Backend
Cloufront & S3
API Gateway & Lambda
planet9energy.io
api.planet9energy.io
Access-Control-Allow-Origin: https://planet9energy.io
CORS HTTP HEADER
ย Custom error page
index.html
Serverless Web Hosting
Serverless APIs
Security: Authentication
"Who is the current user?"
JWT Tokens
Custom
Authorizer Lambda
JWT Token
Authorizer
Login
user: "Podge" pass: "Unicorns<3"
Users DB
Check
Credentials
JWT token
Validate token & extract userId
API request
API 1
API 2
API 3
Security: Authorization
"Can ย ย Podge ย ย trade ย ย for ย ย Account17 ?"
User
Action
Resource
User |
Action |
Resource |
---|---|---|
Podge |
trade |
Account17 |
Podge |
changeSettings |
Account17 |
Luciano |
delete |
* |
... |
... |
... |
import { can } from '@planet9/acl';
export const tradingHandler =
async (event, context, callback) => {
const user = event.requestContext.userId;
const account = event.pathParameters.accountId;
const isAuthorized = await can(user, 'trade', account);
if (!isAuthorized) {
return callback(new Error('Not Authorized'));
}
// ... business logic
}
Security: Sensitive Data
export const handler = (event, context, callback) => {
const CONN_STRING = process.env.CONN_STRING;
// ...
}
# serverless.yml
functions:
myLambda:
handler: handler.myHandler
environment:
CONN_STRING: ${env:CONN_STRING}
Serverless environment variables
Split business logic into small testable modules
Use dependency injection for external resources
(DB, Filesystem, etc.)-
Mock stuff with Jest
Aim for 100% coverage
Nyan Cat test runners! ๐ผ
Quality: Unit Tests
Use child_process.exec to launch "sls invoke local"
Make assertions on the JSON output
Test environment simulated with Docker (Postgres, Cassandra, etc.)
Some services are hard to test locally (SNS, SQS, S3)
Quality: Functional Tests
๐จ Git-Flow
Feature branches
-
Pushย code
GitHub -> CI
Quality: Continuous integration
๐ค CircleCI
-
Lint code (ESlint)
-
Unit tests
-
Build project
-
Functional tests
-
if commit on "master": create deployable artifact
Development / Test / Deployment
Debugging
... How do we debug then
-
console.log... ๐
-
Using the debug module
-
Enable detailed logs only when needed
(e.g. export DEBUG=tradingCalculations)
Step Functions
Coordinate components of distributed applications
Orchestrate different AWS Lambdas
Visual flows
Different execution patterns (sequential, branching, parallel)
Some lessons learned...
๐ Think serverless as microservicesย "microfunctions"
โ๏ธ Cold starts!
๐ซ Be aware of soft limits
๐ There is still some infrastructure: use proper tools
(Cloudformation, Terraform, ...)
๐ PROs
๐
Agility
๐
Focus on delivering
Business Value
๐
Auto-scalability
๐
Managed service
No calls at 2 am...
๐
Smooth
Learning Curve
๐
Pay as you go!
๐ CONs
๐
No live debugging
๐
Local development & testing
๐
Service/Functions
Orchestration
๐
Servers are still there
๐
lacking
Tooling / Best practices
Should I switch to
SERVERLESS ? ๐ฑ
Thanks
(special thanks to @katavic_d, @Podgeypoos79, @quasi_modal & @augeva)