Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Practical Serverless & Edge Computing

Practical Serverless & Edge Computing

Video: https://youtu.be/kKfW9LLL7Rc?t=196

While serverless is way beyond its hype point, it is still an underestimated technology that could open up new approaches in how we build our apps. In this talk I'm going to give an overview of practical applications of serverless JS. We're going to cover serverless frontend microservices, authorization methods, Smart CDNs, caching (including stale-while-revalidate) with Vercel and Cloudflare Workers. I'll illustrate these methods with practical examples from the tools we build internally at resume.io OG image generation, PDF/DOCX rendering, automatic Critical CSS injection and more.

Alexey Taktarov

October 16, 2020
Tweet

More Decks by Alexey Taktarov

Other Decks in Programming

Transcript

  1. 2 alexey taktarov / @mlfrg λ. co-founded resume.io, 8.5M+ resumes

    online λ. I write code (JS / Ruby) occasionally these days… λ. I love designing backends!
  2. 3 wouter: a tiny 1.3KB React router github.com/molefrog/wouter react-colorful: a

    1.8KB color picker github.com/omgovich/react-colorful an amateur OSS contributor react-colorful — a micro color picker component for React
  3. 5 fundamental problems in networking increasing throughput horizontal scaling, network

    configuration reducing latency caching, geo-distribution
  4. λ http reqs λ. ∞-scalable λ. no ops needed λ.

    pay for the compute you need (down to 100ms) 8
  5. λ http reqs λ. ∞-scalable λ. no ops needed λ.

    pay for the compute you need (down to 100ms) λ λ λ λ λ λ λ λ λ λ λ λ λ λ λ λ λ λ λ λ 8
  6. 9 general-purpose FaaS providers AWS Lambda, Google Cloud, Azure, IBM,

    Yandex … → https://fauna.com/blog/comparison-faas-providers deployment platforms + SmartCDNs Vercel (formerly Zeit / Now), Netlify better DX, less configurable built on internally
  7. 9 general-purpose FaaS providers AWS Lambda, Google Cloud, Azure, IBM,

    Yandex … → https://fauna.com/blog/comparison-faas-providers deployment platforms + SmartCDNs Vercel (formerly Zeit / Now), Netlify better DX, less configurable built on internally edge computing Cloudflare Workers AWS Lambda@Edge EdgeEngine
  8. 10 Vercel and Cloudflare λ. CDN-based λ. great developer experience*

    * Serverless Framework is another great tech worth looking at
  9. import fetch from 'node-fetch' export default async (req, res) "=>

    { const name = req.query.name "|| 'wouter' const response = await fetch(githubRepo(name)) const repo = await response.json() res.json({ stars: `${repo.stargazers_count} stars!` }) } api/stars.js 12
  10. 1. NPM deps are bundled import fetch from 'node-fetch' export

    default async (req, res) "=> { const name = req.query.name "|| 'wouter' const response = await fetch(githubRepo(name)) const repo = await response.json() res.json({ stars: `${repo.stargazers_count} stars!` }) } 1 api/stars.js 12
  11. 1. NPM deps are bundled import fetch from 'node-fetch' export

    default async (req, res) "=> { const name = req.query.name "|| 'wouter' const response = await fetch(githubRepo(name)) const repo = await response.json() res.json({ stars: `${repo.stargazers_count} stars!` }) } 1 2. async/await is supported 2 api/stars.js 12
  12. 1. NPM deps are bundled import fetch from 'node-fetch' export

    default async (req, res) "=> { const name = req.query.name "|| 'wouter' const response = await fetch(githubRepo(name)) const repo = await response.json() res.json({ stars: `${repo.stargazers_count} stars!` }) } 1 2. async/await is supported 3. req and res provide convenient helper methods 3 2 api/stars.js 12
  13. 15

  14. 15

  15. 16 λ. the preview must update in the real-time λ.

    react-pdf renders preview in a WebWorker λ. IE isn’t supported → need an SSR fallback
  16. 19 authorisation decoupled JSON Web Tokens signed with asymmetric ciphers

    (RSA/ECD) → https://vercel.com/docs/solutions/authentication
  17. 23 backend issues JWT signs with the secret key browser

    passes JWT to the lambda Authorization header lambda user info token authenticity token lifetime (iat)
  18. 25 export default async (req, res) "=> { const db

    = await connectToDB() const user = await db.getUserById(req.query.id) }
  19. 25 export default async (req, res) "=> { const db

    = await connectToDB() const user = await db.getUserById(req.query.id) } ← latency!
  20. 26 reusing resources between calls λ. one lambda can only

    process 1 request at a time λ. a lambda could be reused between requests λ λ λ λ λ λ lambda instance #1 lambda instance #2 λ
  21. 27 let dbPool = null const connectToDB = async ()

    "=> { if (!dbPool) { dbPool = createConnectionPool() } return await dbPool.acquire() } ← could be reused between requests
  22. 29 const useAuthMiddleware = fn "=> (req, res, ""...args) "=>

    { if (!jwtValid) { const errorMessage = "Not Authorized!" return res.status(402).json({ errorMessage }) } return fn(req, res, ""...args) } export default useAuthMiddleware(lambda) Remember: lambdas are just plain functions!
  23. 30 PDF rendering lambda performance λ. responds within 400ms–1.6s (depending

    on a document size) λ. no downtime since March, 2019 λ. processes ~300GB/m worth of requests λ. conversion rate increased by 0.2%
  24. 33 λ : (id) "-> jpeg could take up to

    2s to render the image…
  25. 35 Now Vercel is a CDN that is also capable

    of executing code. Guillermo Rauch, Vercel
  26. 36 response.setHeader('Cache-Control', 's-maxage=86400') Vercel will cache the image in 70+

    locations around the world for 24 hours → https://vercel.com/docs/edge-network/caching
  27. 40 λ. a Vercel lambda builds SVGs from the set

    of pre-made parts: heads, eyes, hairs λ. the result is cached forever in SmartCDN λ. PRNG is initialized with the name as a seed https:"//headsome.resume.tools/alex.svg
  28. 40 λ. a Vercel lambda builds SVGs from the set

    of pre-made parts: heads, eyes, hairs λ. the result is cached forever in SmartCDN λ. PRNG is initialized with the name as a seed https:"//headsome.resume.tools/alex.svg
  29. A B B B B 42 → https://vercel.com/docs/edge-network/caching#stale-while-revalidate Cache-Control: ’s-maxage=60,

    stale-while-revalidate=600' serve cached version, but revalidate in the background A 1 min ← revalidates without blocking the request 10 min A A C D E 0 min
  30. λ. request time is critical λ. the content changes infrequently

    λ. does not have to be always fresh when to use stale-while-revalidate OG image preview rarely changes, but has to be fast!
  31. origin SFO edge FRA client Cloudflare has 200+ edge locations

    around the globe → https://www.cloudflare.com/network/
  32. 46 running JS on the edge λ. V8 Isolate: cold

    starts in 5ms λ. can modify origin request / response λ. no filesystem, no Node modules λ. only pure JS packages λ. Web APIs: Crypto, fetch, URL etc. → https://developers.cloudflare.com/workers/
  33. 48 λ. CSS files are render-blocking λ. «Above-the-Fold» CSS could

    be inlined to speed up the page load λ. higher PageSpeed → better SEO → https://web.dev/defer-non-critical-css/
  34. 50 <style type="text/css"> .hero{background-color: #ADD8E6;color: #444;cursor: pointer;""... "</style> <link rel="preload"

    href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'"> «Critical» CSS of the above-the-fold content
  35. 52 async function handleRequest(req) { const originResponse = await fetch(req)

    return new HTMLRewriter() .on("div", new MyDivHandler()) .transform(originResponse) } addEventListener("fetch", event "=> { event.respondWith(handleRequest(event.request)) })
  36. 1. inspired by ServiceWorkers 1 52 async function handleRequest(req) {

    const originResponse = await fetch(req) return new HTMLRewriter() .on("div", new MyDivHandler()) .transform(originResponse) } addEventListener("fetch", event "=> { event.respondWith(handleRequest(event.request)) })
  37. 1. inspired by ServiceWorkers 1 2. fetches the response from

    the origin 52 async function handleRequest(req) { const originResponse = await fetch(req) return new HTMLRewriter() .on("div", new MyDivHandler()) .transform(originResponse) } addEventListener("fetch", event "=> { event.respondWith(handleRequest(event.request)) }) 2
  38. 1. inspired by ServiceWorkers 1 2. fetches the response from

    the origin 52 async function handleRequest(req) { const originResponse = await fetch(req) return new HTMLRewriter() .on("div", new MyDivHandler()) .transform(originResponse) } addEventListener("fetch", event "=> { event.respondWith(handleRequest(event.request)) }) 2 3 2. rewriter allows to modify individual elements using a «visitor» pattern
  39. 53 request fetch origin → critical CSS → → rewrite

    HTML → https://github.com/addyosmani/critical
  40. 53 request fetch origin → critical CSS → → rewrite

    HTML response → → https://github.com/addyosmani/critical
  41. 53 request fetch origin → critical CSS → → rewrite

    HTML response → → https://github.com/addyosmani/critical headless-chrome? not supported by workers… →
  42. 53 request fetch origin → critical CSS → → rewrite

    HTML response → → https://github.com/addyosmani/critical headless-chrome? not supported by workers… → Vercel lambda running headless-chrome! λ
  43. «Critic» performance λ. CPU time ~5.3ms (99 pct) λ. processes

    3M+ reqs/m λ. SEO clicks doubled Core Web Vitals report, green shows the number of webpages that are considered “good” → https://search.google.com/ worker
  44. 57 Cloudflare Workers λ. SSR, APIs, websites λ. fine-grained app

    proxies Vercel, Netlify and alternatives λ. server-side rendering λ. APIs λ. dynamic websites with infrequent updates: blogs, SEO pages λ. things that use canvas, headless chrome, native packages etc. λ. low-latency / HA APIs λ. real-time apps w/ WebSockets* * https://blog.cloudflare.com/introducing-workers-durable-objects/
  45. 58 For the longest time, CDNs have been treating the

    "origin" as an opaque black box. It's now possible to push content directly to the network and design frameworks that optimize for this capability. Guillermo Rauch, Vercel
  46. 59 λ. deno.land website built w/ Vercel & CF Workers

    λ. Using node-canvas with Vercel λ. chrome-aws-lambda package additional resources appendix font Inter · icons Radix Icons Alexey Taktarov · molefrog.com · github.com/molefrog · @mlfrg