Slide 1

Slide 1 text

Proprietary + Confidential Serverless and Web API workshop on Google Cloud Guillaume Laforge — @glaforge Developer Advocate, Google Cloud April 2021

Slide 2

Slide 2 text

Proprietary + Confidential Agenda In this workshop, we’ll introduce the definition of “Serverless” and discover the serverless compute options available on Google Cloud Platform. Then, we’ll move on to discuss best practices in the design of Web APIs, and how you can take advantage of serverless products. Finally, we’ll put everything in action, through hands-on codelabs. Introduction to Serverless on Google Cloud 1 Web API best practices 2 Hands-on codelabs 3 Q&A 4 Conclusion 5

Slide 3

Slide 3 text

Proprietary + Confidential Serverless spectrum and compute options on Google Cloud

Slide 4

Slide 4 text

Proprietary + Confidential FaaS App platform Container Virtual machine The serverless spectrum Dedicated server Physical hardware Virtual hardware Operation system Application runtime Application Function Virtual hardware Operation system Application runtime Application Function Operation system Application runtime Application Function Application Function Function Serverless Zone

Slide 5

Slide 5 text

Proprietary + Confidential The serverless models and characteristics Operational Model Programming Model No Infra Management Managed Security Pay only for usage Service-based Event-driven Stateless

Slide 6

Slide 6 text

Proprietary + Confidential Cloud Functions Serverless functions App Engine Web applications and APIs Cloud Run Containerized HTTP workloads Serverless compute options on Google Cloud Source-based deployments of event-driven functions Source and compiled deployments of web apps and web API backends Containerized applications serving HTTP requests, fully managed or on GKE clusters

Slide 7

Slide 7 text

Proprietary + Confidential Cloud Functions

Slide 8

Slide 8 text

Proprietary + Confidential Cloud Functions Cloud services “glue” Backend code that reacts to events ● Background events ● HTTP events Use cases ● Integrating with 3rd-party services & APIs ● IoT backends ● Lightweight real-time data processing ● Virtual assistants & chatbots Available runtimes ● Node.JS ● Python ● Go ● Java ● .Net ● Ruby

Slide 9

Slide 9 text

Proprietary + Confidential The cloud “glue” — Functions event sources Cloud Storage Cloud Pub/Sub HTTPS Firebase Cloud Scheduler Cloud Tasks

Slide 10

Slide 10 text

Proprietary + Confidential ✅ Good fit? — ❌ Constraints? ✅ Good fit ● Easy to deploy bits of code ● React to Pub/Sub & Storage events ● Nice for webhooks handlers or other asynchronous operations ● Don’t want to think about runtime env. ● Lightweight data transformation (ETL) ● Cloud-based HTTP glue & webhooks ❌ Constraints ● Limited set of runtime languages ● Function granularity might be too small ● Must interact via events ● No custom domain (not out of the box) ● Concurrency level of 1 (more cold starts) ● Not for user-facing APIs or web fronts

Slide 11

Slide 11 text

Proprietary + Confidential Demo — Cloud Functions

Slide 12

Slide 12 text

Proprietary + Confidential App Engine

Slide 13

Slide 13 text

Proprietary + Confidential App Engine Standard Available language runtimes: ● Python 2.7 / 3.7 / 3.8 / 3.9 ● Java 8 / 11 ● Node.js 10 / 12 / 14 ● PHP 5.5 / 7.2 / 7.3 / 7.4 ● Ruby 2.5 / 2.6 / 2.7 ● Go 1.11 / 1.12 / 1.13 / 1.14 / 1.15 Features: ● Multiple services, multiple versions ● Traffic splitting (A/B testing, blue/green, canary deploym.) ● Concurrency (80 concurrent requests) ● Custom domains ● Built-in CDN for static asset serving ● Batteries included (Memcache, Datastore…)

Slide 14

Slide 14 text

Proprietary + Confidential ✅ Good fit? — ❌ Constraints? ✅ Good fit ● For stateless applications ● For HTTP request/response workloads ● Scaling high traffic, down to zero (good enough for Snapchat!) ● Built-in CDN static asset serving ● Traffic splitting (across services & versions) ❌ Constraints ● Must use one of the available runtimes ● No support for Web Sockets, gRPC streaming, or Server-Sent Events

Slide 15

Slide 15 text

Proprietary + Confidential Demo — App Engine

Slide 16

Slide 16 text

Proprietary + Confidential Cloud Run

Slide 17

Slide 17 text

Proprietary + Confidential Containers Any language Rich ecosystem Any library of base images Any binary .js .rb .go .py .sh … 0 1 0 1 0 0 1 1 1 Containers Flexibility Serverless Velocity

Slide 18

Slide 18 text

Proprietary + Confidential Serverless containers with Knative and Cloud Run Cloud Run Fully managed, deploy your workloads and don’t see the cluster. Cloud Run on Anthos Deploy into Anthos, run serverless side-by-side with your existing workloads. Knative everywhere Use the same APIs and tooling anywhere you run Kubernetes with Knative.

Slide 19

Slide 19 text

Proprietary + Confidential Container contract & resources ● Listen on 0.0.0.0 on port $PORT (default 8080) ● HTTP server must start < 4 min (timeout → 504) ● Request time < 15 min (default → 5 min, up to 60 min) ● Stateless (in-memory file system) ● Computation only within request (No background activity) ● 1 vCPU per container instance (configurable to 4 vCPU) ● 256 MiB of memory up to a max of 8 GiB (configurable, soon 16 GiB) ● 80 concurrent requests per container (configurable 1-80, soon 250) ● 100 max containers by default (configurable 1-1000, support overridable) ● Access to a Metadata Server ● Sandboxed by gVisor

Slide 20

Slide 20 text

Proprietary + Confidential Pay per use CPU / Memory / Requests 100ms

Slide 21

Slide 21 text

Proprietary + Confidential Billable time Instance Billable Time Request 1 Start Request 1 End Request 2 Start Request 2 End Instance Time Billable Non-billable

Slide 22

Slide 22 text

Proprietary + Confidential Concurrency model concurrency = 1 concurrency = 80

Slide 23

Slide 23 text

Proprietary + Confidential ✅ Good fit? — ❌ Constraints? ✅ Good fit ● For stateless workloads ● For HTTP request / response ● Supports Web Sockets, gRPC, Server-Sent events ● Scale up quickly, and down to zero ● Specific runtime needs (language, dependencies, binary…) ● Custom domains ❌ Constraints ● Must use containers, adds complexity ● Decide on build process (Cloud Build, Cloud Native Buildpacks…) ● No built-in CDN, or Memcache

Slide 24

Slide 24 text

Proprietary + Confidential Demo — Cloud Run

Slide 25

Slide 25 text

Proprietary + Confidential Hosting Web APIs on Serverless products on Google Cloud

Slide 26

Slide 26 text

Proprietary + Confidential Cloud Functions Good for simple single URL endpoints, for asynchronous calculations, or for webhooks callbacks Not for full blown Web APIs, synchronous calls (user waiting for cold start) No custom domain for nice Web API URLs Several hosting options, where to host my Web APIs? App Engine Great for deploying Web APIs, using one of the available language runtime Built-in static assets handy for serving API media files Services & versioning is useful for API versioning Custom domain useful for nice Web API URLs Cloud Run Any Web API framework and runtime in a container Support gRPC APIs, as well as Web Sockets and Server-Sent Events Services & revision can be used for API versioning Custom domain useful for nice Web API URLs

Slide 27

Slide 27 text

Proprietary + Confidential An API gateway to rule them all! Provide a consistent and well-defined API contract (Open API) over existing Web APIs made of several services implemented in various languages, deployed on different serverless platforms Features ● Decouple API contract & usage from underlying implementation ● Regroup several deployed services under a common REST API ● Manage API keys, JWT tokens, user authentication ● Define rate limitations ● Serverless gateway (scale to zero)

Slide 28

Slide 28 text

Proprietary + Confidential Web API design and best practices

Slide 29

Slide 29 text

Proprietary + Confidential REST — Principled design of the modern Web architecture Representational State Transfer, invented by Roy Field Architectural properties ● Performance ● Scalability ● Simplicity ● Modifiability ● Visibility ● Portability ● Reliability Architectural constraints ● Client-server ● Stateless ● Cacheable ● Layered system ● Code on demand (optional) ● Uniform interface

Slide 30

Slide 30 text

Proprietary + Confidential REST — Uniform interface Identification of resources Manipulation of resources through representations Self-descriptive messages HATEOAS (Hypermedia As The Engine of Application State) Resource as URIs: http://api.co/cars/123 JSON, XML, YAML, HTML… (and other media types) HTTP GET, POST, PUT, DELETE, PATCH Hypermedia: HAL, JSON-LD, Siren

Slide 31

Slide 31 text

Proprietary + Confidential HTTP methods & URIs for collections / items Item http://api.co/v2/cars/1234 Collection http://api.co/v2/cars GET Retrieve a specific car List all the cars POST Create a new car if allowed to specify its ID or key, or an ERROR Create a new car PUT Update a specific car Replace the entire collection with a whole news list of cars PATCH Update some details of a specific car Update a batch of the cars in the list, or an ERROR DELETE Delete a specific car Delete all the cars Priority operations

Slide 32

Slide 32 text

Proprietary + Confidential Nouns refer to resources Resources are handled with HTTP verbs: ● GET /cars/123, not /getCar/123 ● POST /cars, not /createCar ● DELETE /cars/1, not POST /deleteCar/1 Prefer nouns over verbs! Verbs can be used for actions or calculations: ● /login, /logout ● /convert — convert temp. °C ⇆ °F ● /transcode — a video into another format ● /promote — a release, and employee...

Slide 33

Slide 33 text

Proprietary + Confidential Naming conventions → Singular or plural resources? Prefer plural forms: /tickets/123 not /ticket/123 Avoid confusing odd singular vs plural forms ● /person vs /people, or /goose vs /geese Easier for URL routing: same prefix for regular expressions Think of it as: “this is the 123th item of the tickets collection”

Slide 34

Slide 34 text

Proprietary + Confidential Different casing in the wild: ● UpperCamelCase or lowerCamelCase ● snake_case or dashed-snake-case Prefer lowercase and snake case (underscores seem more commonly used) Naming conventions → Different casings But chose one casting and stick with it!

Slide 35

Slide 35 text

Proprietary + Confidential Dealing with hierarchies & relationships in URIs ✅ /tickets/123/messages/4 a ticket could be a group of messages ❌ /usergroups/234/users/67 a user could belong to different user groups a user should have a URI of its own, referenced from the usergroup payload

Slide 36

Slide 36 text

Proprietary + Confidential Prefer unwrapped collections ● Unless there’s specific collection payload metadata (ex: a category, a label, a time information…) ● Pagination is better handled with HTTP headers (Un)Wrapped collections GET /tickets { data: [ { id: 1, … } ] } GET /tickets [ { id: 1, … } ]

Slide 37

Slide 37 text

Proprietary + Confidential Path — required, resource identifier /books/123 Query — optional, query collections /books/123?page=3 API parameters, a rule of thumb Body — resource specific logic Part of the payload Header — global, platform wide X-Client-ID: abc123

Slide 38

Slide 38 text

Proprietary + Confidential Time for a cat break? HTTP Status Cats!

Slide 39

Slide 39 text

No content

Slide 40

Slide 40 text

No content

Slide 41

Slide 41 text

Proprietary + Confidential HTTP status codes Use appropriate HTTP status codes when answering requests Not just 200, 300, 400, 500... ● 1xx — Hold on! ● 2xx — Here you go! ● 3xx — Go away! ● 4xx — You messed up! ● 5xx — I messed up!

Slide 42

Slide 42 text

Proprietary + Confidential HTTP status codes → Common status codes 300 Multiple Choices 301 Moved Permanently 302 Found 303 See Other 304 Not Modified 307 Temporary Redirect 308 Permanent Redirect 200 OK 201 Created 202 Accepted. 204 No Content 206 Partial Content 400 Bad Request 401 Unauthorized 403 Forbidden 404 Not Found 405 Method Not Allowed 406 Not Acceptable 409 Conflict 410 Gone 412 Precondition Failed 415 Unsupported Media Type 416 Requested range unsatisfiable 429 Too Many Requests 500 Internal Server Error 501 Not Implemented 502 Bad Gateway 503 Service Unavailable 504 Gateway Time-out 506 Variant Also Negotiates 509 Bandwidth Limit Exceeded

Slide 43

Slide 43 text

Proprietary + Confidential HTTP status codes → 2xx — 201 Created When a resource is created, return 201 Specify a Location header, pointing at the location of the newly created resource POST /cars … HTTP/1.1 201 Created Location: http://api.co/v2/cars/2543 API navigation is important to make the API more discoverable

Slide 44

Slide 44 text

Proprietary + Confidential HTTP status codes → 2xx — 202 Accepted Request accepted but might be handled asynchronously It can be a long-running operation, yielding a result later on (should return a payload representing that operation or have a Location header pointing at the operation for further status requests) POST /jobs … HTTP/1.1 202 Accepted

Slide 45

Slide 45 text

Proprietary + Confidential Response ok, but no payload is returned DELETE /tickets/234 HTTP/1.1 204 No content The resource was successfully deleted, no need for a return payload. But could return 200 with the payload representing the deleted object. HTTP status codes → 2xx — 204 No content

Slide 46

Slide 46 text

Proprietary + Confidential When the content is too big to be returned in one response: ● A resource payload that is too big ● A collection payload that is paginated GET /meteorites?page=4 HTTP/1.1 206 Partial content Link: ; rel=”first”, ; rel=”prev”, ; rel=”next”, ; rel=”last”, HTTP status codes → 2xx — 206 Partial content

Slide 47

Slide 47 text

Proprietary + Confidential With a page number — ?page=3 ● Can also specify a page size ● Might get odd results on collection insertions With a cursor — ?cursor=abc123 ● Insertion friendly With a semantic parameter — ?letter=A ● For a limited or discrete number of elements Pagination

Slide 48

Slide 48 text

Proprietary + Confidential Accept-Range header could be used (not just for bytes, but not very common) GET /users HTTP/1.1 206 Partial content Accept-Ranges: users Content-Range: users 0-9/200 Pagination with an Accept-Range header GET /users Range: users=30-39 HTTP/1.1 206 Partial content …

Slide 49

Slide 49 text

Proprietary + Confidential When HTTP caching headers are in play, the client should have a version in cache already GET /meteorites/654 HTTP/1.1 304 Not modified HTTP status codes → 3xx — 304 Not modified

Slide 50

Slide 50 text

Proprietary + Confidential Request with Modified-Since and reply with Last-Modified GET /users/123 Modified-Since: Wed, 7 Apr 2021 01:16:10 GMT HTTP/1.1 200 OK Last-Modified: Wed, 15 Apr 2021 09:16:10 GMT Caching → Last-Modified (date based)

Slide 51

Slide 51 text

Proprietary + Confidential Request with If-None-Match and reply with Etag GET /users/123 If-None-Match: e9fea8ca2fbb4e6c HTTP/1.1 200 OK Etag: 686897696a7c876b Caching → ETag (tag based) GET /users/123 If-None-Match: 686897696a7c876b HTTP/1.1 304 Not modified

Slide 52

Slide 52 text

Proprietary + Confidential Provide helpful error payloads No definitive standard yet ● HTTP problem proposal ● vnd-error mime type HTTP status codes → 4xx — Errors HTTP/1.1 403 Forbidden Content-Type: application/problem+json { "type": "https://ex.com/probs/out-of-credit", "title": "Not have enough credit.", "detail": "Current balance: 30, cost: 50.", "instance": "/account/12345/msgs/abc", "balance": 30, "accounts": ["/account/12345"] }

Slide 53

Slide 53 text

Proprietary + Confidential An unknown status code should be treated as the first one of the family ● 4xx → 400 generic client error ● 5xx → 500 generic server error HTTP status codes → 4xx / 5xx

Slide 54

Slide 54 text

Proprietary + Confidential When rate limitation is reached, send 429 Too Many Requests Otherwise, indicate common rate limitation status headers: HTTP/1.1 200 OK Date: Mon, 01 Jul 2020 17:27:06 GMT X-RateLimit-Limit: 60 X-RateLimit-Remaining: 56 X-RateLimit-Reset: 1372700873 HTTP status codes → 4xx — 429 Too Many Requests

Slide 55

Slide 55 text

Proprietary + Confidential Selecting ● Query parameters One size does not fit all! Filtering ● Include fields ● Exclude fields ● Expand fields ● Style preference Sorting ● Query parameters Searching ● Combine filtering, sorting, selecting… ● Custom query language

Slide 56

Slide 56 text

Proprietary + Confidential Selecting with query parameters: GET /restaurants?type=chinese&stars=5 Expanding referenced resources: GET /users/123?fields=address.zip Selecting

Slide 57

Slide 57 text

Proprietary + Confidential Include only fields you’re interested in GET /users/123?fields=name,age Specify excluded fields GET /users/123?exclude=biography Specify a “style” as a query parameter GET /users/123?style=compact Filtering Use the prefer header for different “styles” GET /users/123 HTTP/1.1 Content-Type: application/json Prefer: return=minimal Vary: Prefer,Accept,Accept-Encoding HTTP/1.1 200 OK Content-Type: application/json Vary: Prefer,Accept,Accept-Encoding Preference-Applied: return=minimal

Slide 58

Slide 58 text

Proprietary + Confidential SQL style GET /books?sort=title+DESC GET /books?sort=title+DESC,author+ASC Sort and asc/desc query parameters GET /books?sort=title&order=DESC GET /books?sort=title,authors&desc=title&asc=author Sorting

Slide 59

Slide 59 text

Proprietary + Confidential Combine various mechanisms: filtering fields, ordering, pagination… Other approaches like GraphQL... Searching Provide a full-blown query language ● POST a query document to a /search endpoints ● Encode a query into a query parameter

Slide 60

Slide 60 text

Proprietary + Confidential ● Most frequent, in the URL GET /v2/cars/123 ● Custom header GET /cars/123 X-API-Version: 2 Versioning: different approaches ● Less frequent, with an accept header Clients don’t have to change endpoint, but update headers GET /cars/123 Accept: application/vnd.cars.v2/json

Slide 61

Slide 61 text

Proprietary + Confidential With hypermedia controls: ● Easier discovery & navigation ● More generic API clients ● Can palliate need for versioning However: ● Heavier payloads (for limited bandwidth) ● Clients still need to understand the meaning of “links” ● Many competing hypermedia formats ○ HAL, JSON-LD, Collection+JSON, SIREN... Hypermedia — The Richardson’s API maturity model

Slide 62

Slide 62 text

Proprietary + Confidential Frameworks provide custom Web API documentation approach Also often generate Open API documentation and playground Open API 2 still dominant (also known as Swagger) But Open API 3.1 released (→ check tooling support) Other (less popular) formats exist, like: ● RAML ● API Blueprint API documentation — Open API (Swagger)

Slide 63

Slide 63 text

Proprietary + Confidential Hands-on — Let’s deploy serverless Web APIs!

Slide 64

Slide 64 text

Proprietary + Confidential You’ll find step by step instructions in this codelab: codelabs.developers.google.com/ codelabs/serverless-web-apis Codelabs instructions

Slide 65

Slide 65 text

Proprietary + Confidential You’ll find the code used in the codelabs on Github: github.com/glaforge/ serverless-web-apis Open source code

Slide 66

Slide 66 text

Proprietary + Confidential REST API design resources The never ending REST API design debate https://speakerdeck.com/glaforge/ the-never-ending-rest-api-design-debate-devoxx-france-2016 Google API design guide https://cloud.google.com/apis/design Best practices for REST API design https://stackoverflow.blog/2020/03/02/best-practices-for-rest-api-design/ API design guidance: long-running background jobs https://tyk.io/api-design-guidance-long-running-background-jobs/ Best practices for designing a pragmatic RESTful API https://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api PayPal REST API guide https://github.com/paypal/api-standards/blob/master/api-style-guide.md How to design a REST API https://blog.octo.com/en/design-a-rest-api/ HTTP API design guide (initially from Heroku) https://geemus.gitbooks.io/http-api-design/content/en/index.html On choosing a hypermedia type for your API https://sookocheff.com/post/api/on-choosing-a-hypermedia-format/ Your API versioning is wrong, by Troy Hunt https://www.troyhunt.com/your-api-versioning-is-wrong-which-is/

Slide 67

Slide 67 text

Proprietary + Confidential Thank you! Guillaume Laforge — @glaforge Developer Advocate Google cloud