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

Serverless for mere mortals

Serverless for mere mortals

Ee8543e8f5554aaeabb6d140fa07b919?s=128

Nikolay Sverchkov

April 22, 2019
Tweet

Transcript

  1. SERVERLESS FOR MERE MORTALS NIKOLAY SVERCHKOV @ssnickolay

  2. None
  3. evilmartians.com

  4. None
  5. SERVERLESS FOR MERE MORTALS

  6. OR

  7. HOW I REDUCED COSTS BY 250 TIMES USING SERVERLESS

  8. PAST

  9. IN-HOUSE SERVER A LONG TIME AGO

  10. A LONG TIME AGO MAINTAINABILITY IN-HOUSE SERVER

  11. DEDICATED SERVER NOT SO LONG AGO ovh.com

  12. DEDICATED SERVER NOT SO LONG AGO SCALABILITY

  13. CLOUDS NOT SO LONG AGO

  14. CLOUDS NOT SO LONG AGO

  15. CLOUDS NOT SO LONG AGO

  16. CLOUDS NOT SO LONG AGO ? CPU ? RAM ?

    DISK
  17. http://bit.ly/2X9qnp5

  18. None
  19. ?

  20. KANYE WEST

  21. None
  22. ~66.500 RUB

  23. LOAD 0 25 50 75 100 0 1 2 3

    4 5 6 7
  24. LOAD 0 25 50 75 100 0 1 2 3

    4 5 6 7
  25. CAPACITY PLANNING

  26. None
  27. CLOUDS NOT SO LONG AGO CAPACITY PLANNING

  28. MORE ABSTRACTION! move away from server assessment models

  29. None
  30. 2014

  31. HOW IT WORKS

  32. ; ; ; AWS Lambda 1. SLEEP SOURCE_CODE.ZIP S3

  33. AWS Lambda 1. SLEEP 2. EVENT

  34. AWS Lambda 1. SLEEP 2. EVENT 3. HANDLE

  35. function(event, context) { console.log(event.key1); return “Success”; }

  36. AWS Lambda 1. SLEEP 2. EVENT 3. HANDLE 4. RESPONSE

  37. ; ; ; AWS Lambda 1. SLEEP 2. EVENT 3.

    HANDLE 4. RESPONSE 5. -> 1
  38. HTTP ❤ EVENT

  39. BLOG + STATIC PAGES RAILS 3; DO; NGINX ASSETS PIPELINE

  40. User Lambda Markdown -> HTML

  41. User S3 Lambda Assets Markdown -> HTML CloudFront

  42. User S3 Lambda Assets Markdown -> HTML + CloudFront

  43. NOTE 1: THE RIGHT SOLUTION (JAMstack) +

  44. NOTE 2: CAUTION OPEN FLAME

  45. NOTE 2: CAUTION OPEN FLAME

  46. CAUTION OPEN FLAME

  47. ⏱ DEC 2018 % +

  48. DEC 2018 MARCH 2019 % +

  49. VS http://bit.ly/2Dd7R7X

  50. SERVERLESS

  51. SERVERLESS $ serverless create !--template aws-go !!==> serverless.yml

  52. SERVERLESS $ serverless deploy $ serverless rollback !--timestamp timestamp $

    serverless invoke -f functionName $ serverless logs -f functionName $ serverless create !--template aws-go !!==> serverless.yml
  53. SERVERLESS $ serverless deploy $ serverless rollback !--timestamp timestamp $

    serverless invoke -f functionName $ serverless logs -f functionName $ serverless ???? $ serverless create !--template aws-go !!==> serverless.yml
  54. SAM(-CLI) https://github.com/lambci/docker-lambda Docker images and test runners that replicate the

    live AWS Lambda environment
  55. TEMPLATES https://github.com/serverless/examples

  56. serverless.yml functions: post: !<<: *default handler: bin/post events: - http:

    path: blog/{slug} method: get
  57. post.go package main import ( "github.com/aws/aws-lambda-go/events" "github.com/aws/aws-lambda-go/lambda" ) func Handler(ctx

    context.Context, request Request) (events.APIGatewayProxyResponse, error) { !// put code here } func main() { lambda.Start(Handler) }
  58. post.go func Handler(_, request Request) (_, _) { var buf

    bytes.Buffer var slug = request.PathParameters["slug"] … }
  59. post.go func Handler(_, request Request) (_, _) { var buf

    bytes.Buffer var slug = request.PathParameters["slug"] post !:= lib.NewPost(slug, lambdaF.Config) if err !:= post.Render(&buf, lambdaF.Renderer); err !!= nil { return events.APIGatewayProxyResponse{StatusCode: 404}, err } … }
  60. post.go func Handler(_, request Request) (_, _) { var buf

    bytes.Buffer var slug = request.PathParameters["slug"] post !:= lib.NewPost(slug, lambdaF.Config) if err !:= post.Render(&buf, lambdaF.Renderer); err !!= nil { return events.APIGatewayProxyResponse{StatusCode: 404}, err } return lambdaF.Render(&buf) }
  61. REDUCED x250 0.02$ vs 5$

  62. +VAT = 6$!!! REDUCED x300

  63. SERVERLESS UNDER THE MICROSCOPE

  64. LOG $ serverless invoke -f index -l

  65. LOG $ serverless invoke -f index -l START RequestId: <UUID>

    Version: $LATEST END RequestId: <UUID> REPORT RequestId: <UUID> Duration: 1.48 ms Billed Duration: 100 ms Memory Size: 1024 MB Max Memory Used: 31 MB
  66. LOG $ serverless invoke -f index -l START RequestId: <UUID>

    Version: $LATEST END RequestId: <UUID> REPORT RequestId: <UUID> Duration: 1.48 ms Billed Duration: 100 ms Memory Size: 1024 MB Max Memory Used: 31 MB
  67. LOG $ serverless invoke -f index -l START RequestId: <UUID>

    Version: $LATEST END RequestId: <UUID> REPORT RequestId: <UUID> Duration: 1.48 ms Billed Duration: 100 ms Memory Size: 1024 MB Max Memory Used: 31 MB
  68. WHAT ABOUT CPU?

  69. AWS Lambda allocates CPU power proportional to the memory… (с)

    Amazon Docs
  70. AWS Lambda allocates CPU power proportional to the memory… For

    example, if you allocate 256 MB memory, your Lambda function will receive twice the CPU share than if you allocated only 128 MB. (с) Amazon Docs
  71. https://aws.amazon.com/lambda/pricing/

  72. 6$ / PRICE(100ms) = 28.8M!

  73. MEMORY / CST http://bit.ly/2UZ7xDL Completely Fair Scheduler (CFS)

  74. FREE!

  75. CST https://amzn.to/2Ix2t2O

  76. COST !!<=> LANGUAGE

  77. $ wrk -t10 -c400 -d20s -R40000 http://endpoint.url http://github.com/ssnickolay/dump2019

  78. $ wrk -t10 -c400 -d20s -R40000 $ curl http://endpoint.url/[ruby/go] !=>

    {“success”: true} http://github.com/ssnickolay/dump2019
  79. 0 250 500 750 1000 0 1 2 4 5

    MAX AVG AVG ~80ms BATTLE (128 MB)
  80. 0 250 500 750 1000 0 1 2 4 5

    MAX AVG AVG ~80ms 31712 requests in 20.01s Requests/sec: 1584.83 BATTLE (128 MB)
  81. 0 250 500 750 1000 0 1 2 4 5

    0 250 500 750 1000 0 1 2 4 5 MAX AVG AVG ~1.8ms AVG ~80ms 31712 requests in 20.01s Requests/sec: 1584.83 50347 requests in 20.00s Requests/sec: 2517.30 BATTLE (128 MB)
  82. 0 250 500 750 1000 0 1 2 4 5

    0 250 500 750 1000 0 1 2 4 5 MAX AVG AVG ~1.8ms AVG ~80ms 31712 requests in 20.01s Requests/sec: 1584.83 50347 requests in 20.00s Requests/sec: 2517.30 W IN BATTLE (128 MB)
  83. 0 250 500 750 1000 0 1 2 4 5

    0 250 500 750 1000 0 1 2 4 5 MAX AVG AVG ~1.8ms AVG ~80ms 31712 requests in 20.01s Requests/sec: 1584.83 50347 requests in 20.00s Requests/sec: 2517.30 W IN + BATTLE (128 MB)
  84. 0 250 500 750 1000 0 1 2 4 5

    0 250 500 750 1000 0 1 2 4 5 MAX AVG AVG ~1.8ms AVG ~80ms 31712 requests in 20.01s Requests/sec: 1584.83 50347 requests in 20.00s Requests/sec: 2517.30 BATTLE (128 MB)
  85. BATTLE (128 MB) AVG ~1.8ms AVG ~80ms “Billed Duration: 100

    ms” (c) Lambda Log
  86. COST !!<=> PACKAGE SIZE

  87. 5.4MB 140KB COST !!<=> PACKAGE SIZE MIN SIZE

  88. Go + WRK2 Milliseconds (AVG) 1,7 1,775 1,85 1,925 2

    Megabytes 6 25 150 220
  89. 5.4MB 140KB COST !!<=> PACKAGE SIZE

  90. http://rubyonjets.com/

  91. COST !!<=> DEPENDENCIES

  92. MINIMIZE THE COMPLEXITY OF YOUR DEPENDENCIES

  93. MINIMIZE THE COMPLEXITY OF YOUR DEPENDENCIES

  94. MINIMIZE THE COMPLEXITY OF YOUR DEPENDENCIES

  95. WAIT A MINUTE

  96. https://stackoverflow.com/q/54110697

  97. When you write your Lambda function code, do not assume

    that AWS Lambda automatically reuses the execution context for subsequent function invocations…. (c) AWS Docs AWS LAMBDA EXECUTION CONTEXT
  98. func Fibonacci(n uint) uint { if n !<= 1 {

    return n } return Fibonacci(n-1) + Fibonacci(n-2) } OPTION 1
  99. func Fibonacci(n uint) uint { if n !<= 1 {

    return n } return Fibonacci(n-1) + Fibonacci(n-2) } func main() { lambda.Start(Handler) } OPTION 1
  100. func Fibonacci(n uint) uint { if n !<= 1 {

    return n } return Fibonacci(n-1) + Fibonacci(n-2) } !// Handler is our lambda handler invoked by !// the `lambda.Start` function call func Handler(ctx context.Context) (Response, error) { Fib !:= Fibonacci(33) !// noise here resp !:= Response{ Body: Fib } … } func main() { lambda.Start(Handler) } OPTION 1
  101. Milliseconds (AVG) 0 250 500 750 1000 1 2 3

    4 Golang (128MB + Fib) ~ 400ms Option1
  102. var Fib uint func Fibonacci(n uint) uint {…} func Handler(ctx

    context.Context) (Response, error) { … } func init() { Fib = Fibonacci(33) !// noise here } func main() {…} OPTION 2
  103. Milliseconds (AVG) 0 250 500 750 1000 1 2 3

    4 Golang (128MB + Fib) ~ 400ms Option1 Option2
  104. COST SPEED ⏫

  105. 0 15000 30000 45000 60000 0 1 2 4 5

    50347 requests in 20.00s Requests/sec: 2517.30 LOAD !!<=> $$$
  106. 0 15000 30000 45000 60000 0 1 2 4 5

    50347 requests in 20.00s Requests/sec: 2517.30 PROTECTION 1: X-API-KEY
  107. 0 15000 30000 45000 60000 0 1 2 4 5

    PROTECTION 2: AWS SHIELD 50347 requests in 20.00s Requests/sec: 2517.30
  108. 0 15000 30000 45000 60000 0 1 2 4 5

    50347 requests in 20.00s Requests/sec: 2517.30 62808 requests in 20.01s Non-2xx or 3xx responses: 62127 1 1000 CONCURRENCY PROTECTION 3: THROTTLING
  109. PREDICTABLY

  110. PREDICTABLY

  111. PREDICTABLY

  112. RECIPE

  113. 1. TAKE SERVERLESS

  114. 1. TAKE SERVERLESS 2. FOLLOW RULES

  115. 1. TAKE SERVERLESS 2. FOLLOW RULES 3. ????

  116. 1. TAKE SERVERLESS 2. FOLLOW RULES 3. ???? 4. PROFIT

  117. WHAT ABOUT PRODUCTION?

  118. WHAT ABOUT PRODUCTION? Tung Nguyen

  119. @ssnickolay Nikolay Sverchkov @ssnickolay THANK YOU! @evilmartians http://evl.ms/blog http://evl.ms/telegram