Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

We All Live in a Yellow (Serverless) Submarine

56 views

Published on

The term “serverless” is finding it’s way into everyday development, but is it more than just a buzzword? In this talk, Luke will go over the idea of serverless, and how it can be useful to modern day web developers with real examples of where REDspace has managed to be successful with it.

Luke will also give some code examples, talk about some “serverless” libraries and review some of the pitfalls of going serverless, and where we might see it going in the future.

Objective
To understand what the serverless web is all about, and how it can be useful.

Target Audience
Developers who are interested in the serverless revolution.

Assumed Audience Knowledge
Basic JavaScript

Level
Beginner

Five Things Audience Members Will Learn
What is serverless?
The benefits of going serverless
How to deploy a serverless function to AWS
When not to go serverless
Options for migrating apps to serverless

Published in: Internet
  • Be the first to comment

  • Be the first to like this

We All Live in a Yellow (Serverless) Submarine

  1. 1. WeAllLiveInAYellow (Serverless)Submarine
  2. 2. Welcome.
  3. 3. LukeDeWitt WEB TEAM LEAD / DAD / SMOKER OF VARIOUS MEATS / SAD BLUE JAYS FAN ThisisYourCaptainSpeaking
  4. 4. LukeDeWitt WEB TEAM LEAD / DAD / SMOKER OF VARIOUS MEATS / SAD BLUE JAYS FAN ThisisYourCaptainSpeaking ARRRRR!!
  5. 5. Serverless
  6. 6. Serverless
  7. 7. Serverless Server-Less=
  8. 8. Serverless A cloud computing model where-by a server dynamically allocates machine resources to execute code on-demand.
  9. 9. Serverless
  10. 10. Serverless • Also referred to FaaS (Functions as a Service) • Originator: Zimki - 2006 • Introduced by Amazon in 2014 (AWS Lambda)
  11. 11. Serverless
  12. 12. Serverless
  13. 13. Why?
  14. 14. WhyServerless? • No need to deal with f*%&ing servers
  15. 15. WhyServerless? • Let’s you concentrate on what’s important to your clients and users
  16. 16. WhyServerless? • Cheap • 128MB • $0.000000208 / 100ms • 1024MB • $0.000001667 / 100ms • Function at 1024MB, runs 1000X at 80ms / exec • $0.1667 = 17 cents
  17. 17. WhyServerless? • Auto-Scaling
  18. 18. WhyServerless? • Less complex development
  19. 19. WhyServerless? • Prototyping
  20. 20. WhyServerless? • Get sh*t done faster
  21. 21. When?
  22. 22. WhenServerless? • Websites / APIs
  23. 23. WhenServerless? • Event Streaming w/ Pub/Sub
  24. 24. WhenServerless? • IOT
  25. 25. WhenServerless? • Continuous Integration
  26. 26. WhenServerless? • Image / Video Manipulation NOT A HOTDOG
  27. 27. Why?
  28. 28. WhyNot?
  29. 29. WhyNotServerless? • Kind of a pain in the ass getting started • All of the providers are different
  30. 30. WhyNotServerless? • No server = No control • Difficult to test • Logging and Error Handling
  31. 31. WhyNotServerless? • Cost model may not make sense • Your language may not be supported • Execution time limits
  32. 32. WhyNotServerless? • Cold start
  33. 33. Serverless
  34. 34. Andthen...?
  35. 35. What’sNext? • Serverless Databases • Containers
  36. 36. Talkischeap...
  37. 37. Demotime!
  38. 38. ServerlessDemo • React App • User Uploads a Photo to S3 • Triggers Lambda Function • Image Modified, Saved to S3 • Share to Social Media • Meme Generator
  39. 39. ServerlessDemo
  40. 40. ServerlessDemo
  41. 41. ReactApp NOT A REACT TALK
  42. 42. UploadtoS3 Amplify.configure({ Auth: { identityPoolId: process.env.IDENTITY_POOL_ID, region: process.env.AWS_REGION }, Storage: { bucket: process.env.UPLOAD_BUCKET, region: process.env.AWS_REGION } }); let filename = shortid.generate(); this.setState({ photoUrl: `//www.thatsweb.ca/uploads/${filename}.png` }); Amplify.Storage.put( `${filename}.png`, this.dataURItoBlob(this.photo.current.src), { contentType: "image/png", customPrefix: { public: process.env.UPLOAD_FOLDER } } ).then(result => this.searchForMeme()); AWS Amplify “Unique” ID Amplify push to S3 Pull from S3
  43. 43. TriggerLambdaFunction
  44. 44. LambdaFunctionCode const s3 = new AWS.S3(); exports.handler = (event, context, callback) => { const key = event.Records ? event.Records[0].s3.object.key : process.env.TEST_IMAGE; const inputParams = { Bucket: process.env.TRIGGER_BUCKET, Key: key }; // download image from s3 that triggered the lambda event return s3.getObject(inputParams, (err, data) => { Get the image Get uploaded photo
  45. 45. LambdaFunctionCode Build the meme const input = data.Body; // composite the meme image on top of the uploaded image gm(input, "input.png") .composite("./thatsweb.png") .stream("png", (err, stdout, stderr) => { let buf = new Buffer(""); stdout.on("data", data => { buf = Buffer.concat([buf, data]); }); stdout.on("end", data => { // upload the meme to s3 const destinationParams = { Bucket: process.env.DESTINATION_BUCKET, Key: key, Body: buf, ContentType: "image/png" }; s3.putObject(destinationParams, (err, res) => { Push to public S3
  46. 46. LambdaFunctionCode Connect to DB Save Record const connection = mysql.createConnection({ host: process.env.DB_HOST, user: process.env.DB_USER, password: process.env.DB_PASS, database: process.env.DB_NAME }); connection.connect(function(err) { if (err) { callback(err); } }); const record = { uuid: recordId[1], ip: event.Records ? event.Records[0].requestParameters.sourceIPAddress : "testing-ip" }; connection.query("INSERT into thatsweb SET ?", record, err => { if (err) { callback(err); } connection.end(() => callback()); Create Object End Lambda Function
  47. 47. EndpointPolling searchForMeme() { let img = new Image(); img.onload = () => { this.photo.current.src = this.state.photoUrl; this.setState({ stage: "share" }); }; img.onerror = () => { // try again in half a second... img = null; return setTimeout(this.searchForMeme, 500); }; img.src = this.state.photoUrl; }
  48. 48. BONUS
  49. 49. FetchFlow
  50. 50. FetchMemes
  51. 51. GetEndpoint connection.query("SELECT COUNT(*) AS count FROM thatsweb", (err, results) => { const { count } = results[0]; let query = "SELECT uuid FROM thatsweb ORDER BY (id * RAND())"; if (count > 20) { query += " LIMIT 20;"; } connection.query(query, (err, results) => { if (err) { callback(err); } function shuffle(a) { for (let i = a.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [a[i], a[j]] = [a[j], a[i]]; } return a; } connection.end(() => callback(null, { memes: shuffle(results.map(({ uuid }) => uuid)) }) ); }); Get Results Send back memes
  52. 52. FetchMemes fetch("https://api.thatsweb.ca/v1/memes", { headers: { "x-api-key": process.env.API_GATEWAY_KEY } }) .then(resp => resp.json()) .then(resp => this.setState({ memes: resp.memes }) ); <div className="thatsweb-list__memes"> {memes.map((m, idx) => ( <MemeThumb uuid={m} key={idx} /> ))} </div> const MemeThumb = ({ uuid }) => { return ( <div className="thatsweb-list__meme"> <Link to={`/memes/${uuid}`}> <img src={ typeof uuid === "undefined" ? placeholder : `//www.thatsweb.ca/uploads/${uuid}.png` } alt="uploaded meme thumbnail" /> </Link> </div> ); };
  53. 53. YourTurn
  54. 54. https://www.thatsweb.ca
  55. 55. https://www.github.com/ whatadewitt/thatsweb
  56. 56. Thankyouforcoming!
  57. 57. redspace.com / T (902) 444.3490 FACEBOOK REDspace TWITTER @theREDspace LINKEDIN The REDspaceLUKE DEWITT @whatadewitt ThankYou!
  58. 58. ThankYou! Oh, by the way, we’re hiring! https://www.redspace.com/jobs

×