Loading

Building a Serverless company with Node.js, React and the Serverless Framework - JS Day 2017

Luciano Mammino

This is a live streamed presentation. You will automatically follow the presenter and see the slide they're currently on.

BUILDING A SERVERLESS COMPANY WITH NODE, REACT AND THE SERVERLESS FRAMEWORK

Luciano Mammino

MAY 10TH 2017, Verona

Who is LUCIANO

NeBK20JV

-20% eBook

 

NpBK15JV

-15% Print

 

fancy a coupon? 😇

Agenda

What is Serverless

  • History & definition

  • Advantages & costs

  • How it Works

  • Example on AWS Lambda

  • Example with 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 (cheap!)

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

Google

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

🤙

API Gateway config has been generated for us...

Recap

  1. Login to AWS Dashboard
  2. Create new Lambda from blueprint
  3. Configure API Gateway trigger
  4. Configure Lambda and Security
  5. Write Lambda code
  6. 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 : 'Verona';
    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

  1. Install serverless framework
  2. Create handler & serverless config
  3. Test locally (optional)
  4. Deploy
  5. 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 *
... ... ...
  • Custom ACL module used by every lambda
  • Built on node-acl & knex.js
  • Persistence in Postgres
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}
  • 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, ...)

  • Serverless architectures are COOL! 😎

    • Infinite scalability at low cost

    • Managed service

    • Still, has some limitations

  • Managing a project might be hard but:

    • Technology progress and open source (e.g. Serverless.com) will make things easier

Recap

Thanks

(special thanks to @Podgeypoos79, @quasi_modal & @augeva)