Massive applications in node.js


Published on

Presentation about the stupid stuff you should avoid when building more than trivial applications in node.js.

Published in: Technology
  • Be the first to comment

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide
  • \n
  • Hi!\n
  • Open source IDE. Javascript, javascript, javascript. And it looks awesome.\n
  • Runs in browser. Anywhere in the world.\n
  • Full lifecycle\n
  • Time to install Visual Studio, 150 times\n
  • Fully featured. \n
  • We’re huge\n
  • We have over 400.000 lines of code\n
  • In client side and server side javascript.\n
  • \n
  • Non trivial applications in a dynamic language\n
  • Extremely expressive, scales very well in theory\n
  • Shoot yourself in the foot a lot.\n
  • Clear view of the platform\n
  • 1995 LiveWire server. Actual power from the underlying platform\n
  • * Cross platform library\n* Fastest IO / Networking library on this planet\n* Async up blocking platform API calls\n
  • File system API\n
  • However, OS vendors try to abstract that away.\n
  • Synchronous code flow. Thread blocks.\n
  • Async code flow. \nNo need for threads because function pointers.\nFS, DNS, Networking, etc.\n
  • JS bindings to LibUV. Like the DOM.\n
  • \n
  • Not exclusive. Lua, C++, SpiderMonkey. \n\nJS most mature, largest set of 3rd party.\n
  • * No eco system\n* Fast VM\n* Used to async networking\n
  • * Single threaded\n* Long polling, max 300 conn.\n
  • Not all your problems going away.\nLet's do a little pop quiz:\n
  • What happens when I run `server.js` on my MacBook Air. A: it displays 'Hello Moscow', or B: it crashes.\n
  • \n
  • \n
  • \n
  • All works fine. LibUV abstracts the file system away for me, and manages this all nice and easy. Now I run it on Solaris, where our actual production servers run:\n\n
  • \n
  • Now I run it on Solaris, where our actual production servers run:\n\n
  • It crashes! The default file descriptor limit on Solaris is set to 1.024. If you read more files than that, or open more TCP sockets, or do more DNS requests. YOUR APP WILL CRASH. LibUV is great, but you are still susceptible to OS limits.\n\n
  • Don't flood your system, use async libraries that can throttle like async\n
  • In LibUV all APIs are asynchronous\n
  • Or are they?\n
  • Take this example of creating a SHA hash of a file\n
  • We create a nice stream\n
  • Then react on the events the stream gives. \n\nWho thinks this is a GOOD approach that will not block?\n
  • It blocks! Be aware of this, or better detect it before it bites you. Checking for blocking calls can be pretty simple actually. All you need is eight lines of javascript in your main app file.\n
  • If the event loop blocks, timed event like setInterval aren’t executed for a while. This way you get immediate feedback when blocking.\n
  • \n
  • Prevent blocking before going live!\n\nSo here are three tips to stop blocking!\n
  • First: Move blocking calls, that you can’t prevent out of process (forking or spawning)\n
  • Second: Put a post-commit hook on your repo that searches for function calls that have `Sync`, then fire the guy who committed it.\n
  • Or use workers\n
  • But only if the serialization takes less time than the computation itself. It’s great for heavy operations on SMALL objects, but otherwise it’s not worth it.\n
  • \n
  • * Weak typed, no static compilation. \n* Fail on production. \n* Use tooling.\n
  • todo\n
  • \n
  • * Has stuff you DONT want to do\n
  • * Tooling helps you identify problems\n
  • * Especially for weak typed dynamic languages\n
  • Spot the number of errors in this code sample\n
  • \n
  • \n
  • \n
  • With static program analysis, we can annotate this code\n
  • And spot the errors\n
  • \n
  • \n
  • \n
  • \n
  • Open source, work in progress.\n
  • App doesn’t block, never crashes. \n
  • Read file method. Who thinks this is a good approach?\n
  • Oh noes!\n
  • Insert into database\n
  • Never make mistakes. Forget the return.\n
  • Never calling callback.\n
  • Futures or Promises. Wrap callbacks.\n
  • But these are the pitifalls when using node, but on an architectural level there are downsides as well. When, due to some sloppy coding, or due to a faulty third party library, an unhandled exception occurs:\n
  • The first months after launch, there were days that we didn't reach an average uptime of 7 minutes. So monitor your log files very carefully, and use software to daemonize your app, like forever or node.js, so you are back on track very fast.\n
  • * Review every third party library that you use\n* Use forever or run.js\n* Monitor log files for application crashes\n* Fix problems!\n
  • The major problem here is that every piece of code runs in the same context as your mission critical systems. That's nice for a hobby website, but when building an IDE like Cloud9, we need stability first. That's why we came up with [Architect](\n\n
  • Architect is a development framework that originally tackled another problem of building massive applications: dependency management. Package managers are great for the big picture but it gets very complicated if you modularize every tiny bit of your app. Architect takes a different approach: \n
  • A plugin is a small piece of an application, that consumes other plugins, and expose certain methods. A simple HTTP server plugin would look like:\n
  • Now the complete inner working of HTTP, routing, etc. is embedded in one plugin, and it exposes one single method for other plugins. Take a 'Hello World' plugin built on top of this.\n
  • The plugin that consumes http, doesn't need to know anything about the internal working. There is a method available and it can call it.\nArchitect will now resolve the dependency graph at startup, create the plugins in the correct order, and will also display errors when you reference a plugin that is not registered.\n
  • Architect apps are sets of plugins\n\nAn architect 'Hello world' application is therefore nothing more than a simple configuration file with a list of plugins:\n
  • And starting up is just calling architect from a node.js file:\n
  • Plugin lists are awesome, because you can vary the plugin list based on the environment where your application runs. You can enable simple plugins that log all HTTP requests, find globals, etc. on development, but disable them on production.\n
  • The Cloud9 configuration file (per development environment) was 330 lines long. No one knows which setting is used where and the config object was passed around all the time. Architect solves that by having different configurations per plugin. If the `http` plugin we created has to run on a different port, we can configure that in config.\n
  • When the plugin is loaded, the configuration will be there. So you always have the settings that matter for THAT specific plugin, and nothing more or less.\n
  • \n
  • The plugin system allows for some great sweatness as well when refactoring. Say we want to introduce `connect`, http middleware. We can remove the current `http` plugin, and create a new connect based one.\n
  • When the API we expose is the same ALL other plugins will just work fine without any work!\n
  • On the local installable version of Cloud9 we communicate directly with the filesystem. We built a simple `fs` plugin that exposes methods like `readFile`, `writeFile` etc. When you run your app on the hosted version of cloud9, we load a different `fs` plugin, that communicates over a secure network tunnel. Similar functionality, different implementation.\n\n
  • That solves some stuff, but not crashing an application when a stupid error occurs. There are two features in Architect that help you isolate plugins.\n
  • A container is a seperate `node` process that contains a set of plugins. The http plugin can run in it's own container, and the hello-world plugin in another. Architect will handle the inter process communication so you don't have to change any of your code. Only an error in `hello` will be out of process! Win, win!\n
  • The hosted version of Cloud9 consists of two main parts:\n\n1. The IDE, which is the open source IDE with some plugins swapped\n2. Infrastructure code, like a dashboard with your projects\n\nThe infrastructure code and the IDE are completely different. They don't need to communicate. So when we need to open a new IDE instance, we let the infrastructure spawn a new architect process that loads all the plugins required for an IDE! This way every IDE runs in it's own process and a crash at a user's IDE instance won't bubble through to all infrastructure code!\n\nThis is also great because we have several project types, when you load a normal project we won't load the FTP plugins and vice versa. \n
  • Architect has some other handy features, like easily and transparently reuse node cluster, which allows you to scale out an application to all cores of your server, but feel free to contact me after the event.\n
  • Don’t let this talk scare you away!\n
  • \n
  • \n
  • \n
  • Massive applications in node.js

    1. 1. MASSIVEapplications on node.js
    2. 2. @drbernhard
    3. 3. CreateDeploy Run/Debug Share Test
    4. 4. The easiest way to create Node.js apps
    5. 5. ins Run lug /De Collaboration P bug Cloudfou ndry g st in H T e eroku bD AV Git W e Search Clou Az ureLanguage Analysis d st o rag Ftp e Vim mo ns uck e de Rev isio CLIBi tb t
    6. 6. Pretty big app
    7. 7. More than 400K lines (with semicolons)
    8. 8. Of JavaScript
    9. 9. Pure madness
    10. 10. Why sparta madness?
    11. 11. Javascript/Node.jsmake you more productive
    12. 12. But they won’t helpyou through your growing pains
    13. 13. Google’s V8 engineas an executable!
    14. 14. LibUV
    15. 15. Я предпочитаю асинхронные!
    16. 16. I hateasynchronous!
    17. 17. Javascript LibUV
    18. 18. Javascript bindings to LibUV Standard libraries in JS JS executed in V8
    19. 19. QUIZ!
    20. 20. Reference file system Loop from 0 to 1 Read file async Print out data
    21. 21. In node, all APIs areasynchronous
    22. 22. In node, all APIs areasynchronous?
    23. 23. Getting a hash
    24. 24. Getting a hash
    25. 25. Getting a hash
    26. 26. Getting a hash
    27. 27. DTrace + node-stackvis
    28. 28. Use workers
    29. 29. Use workers BUT only ifserialization < computation
    30. 30. Your application will fail
    31. 31. Normal developers
    32. 32. JavaScript Developer
    33. 33. Tooling matters
    34. 34. Tooling mattersespecially for JavaScript
    35. 35. Use the power of...
    36. 36. ta ti c
    37. 37. program analysis
    38. 38. Iterating using undeclared variable
    39. 39. Warning: you are in an anonymous inner function with its own “this” pointer
    40. 40. Did you mean length?
    41. 41. Closure scope bug
    42. 42. “The most important thing I have doneas a programmer in recent years is toaggressively pursue static codeanalysis.” John Carmack
    43. 43.
    44. 44. Callback hell
    45. 45. Happy coding!
    46. 46. Questions?
    47. 47. @drbernhard