Your SlideShare is downloading. ×
Massive applications in node.js
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Massive applications in node.js

14,270
views

Published on

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

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

Published in: Technology

0 Comments
17 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
14,270
On Slideshare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
148
Comments
0
Likes
17
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
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](http://github.com/c9/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
  • Transcript

    • 1. MASSIVEapplications on node.js
    • 2. @drbernhard
    • 3. CreateDeploy Run/Debug Share Test
    • 4. The easiest way to create Node.js apps
    • 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. Pretty big app
    • 7. More than 400K lines (with semicolons)
    • 8. Of JavaScript
    • 9. Pure madness
    • 10. Why sparta madness?
    • 11. Javascript/Node.jsmake you more productive
    • 12. But they won’t helpyou through your growing pains
    • 13. Google’s V8 engineas an executable!
    • 14. LibUV
    • 15. Я предпочитаю асинхронные!
    • 16. I hateasynchronous!
    • 17. Javascript LibUV
    • 18. Javascript bindings to LibUV Standard libraries in JS JS executed in V8
    • 19. QUIZ!
    • 20. Reference file system Loop from 0 to 1 Read file async Print out data
    • 21. In node, all APIs areasynchronous
    • 22. In node, all APIs areasynchronous?
    • 23. Getting a hash
    • 24. Getting a hash
    • 25. Getting a hash
    • 26. Getting a hash
    • 27. DTrace + node-stackvis http://blog.nodejs.org/2012/04/25/profiling-node-js/
    • 28. Use workers
    • 29. Use workers BUT only ifserialization < computation
    • 30. Your application will fail
    • 31. Normal developers
    • 32. JavaScript Developer
    • 33. Tooling matters
    • 34. Tooling mattersespecially for JavaScript
    • 35. Use the power of...
    • 36. ta ti c
    • 37. program analysis
    • 38. Iterating using undeclared variable
    • 39. Warning: you are in an anonymous inner function with its own “this” pointer
    • 40. Did you mean length?
    • 41. Closure scope bug
    • 42. “The most important thing I have doneas a programmer in recent years is toaggressively pursue static codeanalysis.” John Carmack
    • 43. treehugger.jsgithub.com/ajaxorg/treehugger
    • 44. Callback hell
    • 45. Happy coding!
    • 46. Questions?
    • 47. http://c9.io http://github.com/janjongboom @drbernhard

    ×