Slide 1

Slide 1 text

Node.js Mike Brevoort 15 March 2012 uncanny lessons

Slide 2

Slide 2 text

Node.js uncanny lessons Mike Brevoort @mbrevoort work at... (though opinions expressed in this presentation are my own and not meant to represent Pearson)

Slide 3

Slide 3 text

Node.js uncanny lessons Agenda 22 pieces of advice

Slide 4

Slide 4 text

Node.js uncanny lessons know your strengths •don’t force everything into node Fibonacci you say?!?

Slide 5

Slide 5 text

Node.js uncanny lessons know your powers •don’t try to work against the async nature •don’t forget to be an engineer!

Slide 6

Slide 6 text

Node.js uncanny lessons its a dynamic language! TEST

Slide 7

Slide 7 text

Node.js uncanny lessons beware of the diabolical spaghetti code app.get('/bar', function(req, res) { foo.fetchSomething(function(error, something) { if(!error) { foo.fetchSomeOne(something, function(error, someone) { if(!error) { foo.fetchBar(function(error, bar) { if(!error) { res.send("we got bar: " + bar); } else { res.send(error.statusCode); } }); } else { res.send(error.statusCode); } }); } else { res.send(error.statusCode); } }); }); it’s easy to write code that looks like this

Slide 8

Slide 8 text

Node.js uncanny lessons expect errors •typically, on error, node emits an ‘error’ event on the corresponding object •if no listeners on object for ‘error’, a top level exception is raised and the process exits

Slide 9

Slide 9 text

Node.js uncanny lessons expect errors (cont) process.on('uncaughtException', function(error) { console.log("Kaboom.... handle " + error); }); var server = http.createServer(function (req, res) {}); server.on('error', function(error) { console.log("Caught error! Don't exit!"); }); prudent approach nuclear approach > > however, you’re better off logging and rethrowing!

Slide 10

Slide 10 text

Node.js uncanny lessons Log Aggressively •The async nature of node makes it difficult to diagnose some production problems. •Why? Check out Winston (by ) logging levels + multiple transports

Slide 11

Slide 11 text

Node.js uncanny lessons don’t fall asleep at the wheel •plan for your program to crash! •Automatically restart it with a process monitor •like ‘s Forever or

Slide 12

Slide 12 text

Node.js uncanny lessons get out of the way!

Slide 13

Slide 13 text

Node.js uncanny lessons get out of the way!

Slide 14

Slide 14 text

Node.js uncanny lessons offload computationally intensive tasks •spawn a child process require('child_process').spawn() •call out to another system more apt to handle heavy lifting •use a job queue

Slide 15

Slide 15 text

Node.js uncanny lessons be weary of loops! for (var i=0, l=entries.length; i

Slide 16

Slide 16 text

Node.js uncanny lessons be weary of loops! (cont) // order matters function processEntry(entries, index) { index = index || 0; if(index === entries.length) return done(); doSomething(entries[index]); process.nextTick(function() { processEntry(entries, index++) }); } processEntry(entries); non-blocking loops

Slide 17

Slide 17 text

Node.js uncanny lessons be weary of loops! (cont) non-blocking loops // order doesn't matter var leftToProcess = entries.length; for (var i=0, l=entries.length; i

Slide 18

Slide 18 text

Node.js uncanny lessons be weary of loops! (cont) or use a library like async var async = require('async'); // order doesn't async.forEach(entries, doSomething); // order matters async.forEachSeries(entries, doSomething); // throttled 10 at a time async.forEachLimit(entries, 10, doSomething);

Slide 19

Slide 19 text

Node.js uncanny lessons Secret Agent Pools • node pools outbound http(s) connections by default for each host • default concurrent maxSockets per host is 5 • is this what you want? // disable per request http.get({host:'localhost', port:80, path:'/', agent:false}, function (res) { // Do stuff }) // effectively disable http.globalAgent.maxSockets = 99999;

Slide 20

Slide 20 text

Node.js uncanny lessons stay lean •watch your heap size •v8 does stop the world generational GC •profile gc with --trace-gc •Cost of GC is proportional to the number of live objects

Slide 21

Slide 21 text

Node.js uncanny lessons stay lean (cont) •I try to keep heap size < 200mb •Alternatively move data outside of node •instead use Redis, mongodb, CouchDB, etc •encourages statelessness, scalability and durability

Slide 22

Slide 22 text

Node.js uncanny lessons you can’t do it alone! •don’t build monolithic apps •Build loosely coupled, highly cohesive systems

Slide 23

Slide 23 text

Node.js uncanny lessons unleash your file descriptors! • node can handles 1000’s of connections!? • but your OS says... Too many open files • default # file descriptors on most unix systems is 1024 • 1 FD per socket means max open sockets < 1024 • increase the max # of file descriptors • ulimit -n • ulimit -a to see current max

Slide 24

Slide 24 text

Node.js uncanny lessons git your modules in order •NPM is awesome •Maintaining a private NPM registry has been a struggle •Alternatively use Git Module dependencies (one git repo per module) devDependencies: { "eclg-prospero": "git+ssh://[email protected]:PearsonEducation/prospero-node.git#v2.0.0" }

Slide 25

Slide 25 text

Node.js uncanny lessons count your friends •peg your npm versions { "name": "Foo Package", "description": "my Foo package", "version": "1.0.0", "author": "Mike Brevoort ", "dependencies": { "express": "2.3.2", "cluster": ">= 0.6.1", "mongodb": "0.9.x", "connect-gzip": "~0.1", "underscore": "= latest" }, "engines": { "node": "= 0.4.8" } } is this what you really want? really? >

Slide 26

Slide 26 text

Node.js uncanny lessons check ‘em in • is amazing, but check in your module dependencies (in node_modules) •Dependencies of dependencies can change unseeingly! •ignore binaries •npm rebuild on deploy

Slide 27

Slide 27 text

Node.js uncanny lessons or shrinkwrap ‘em! •npm shrinkwrap (new in 1.1.2) •Records a full module/ version dependency graph •doesn’t seem to work with git referenced modules

Slide 28

Slide 28 text

Node.js uncanny lessons Multiplicity •plan to manage multiple node.js versions •I prefer n •nvmw on windows $ n 0.4.12 0.4.8 0.6.0 ο 0.6.11 0.6.3 0.6.5 0.6.7 0.7.4 0.7.5 # run with a specific version $ n as 0.6.11 myprogram.js #using bundled npm $ n npm 0.6.11 # install a new version $ n latest $ n 0.6.10

Slide 29

Slide 29 text

Node.js uncanny lessons if you have a cape, fly • use conventions! • check out Felix Geisendorfer’s node style guide http:// nodeguide.com • for example, reserve the first parameter of any callback for an optional error object function foo() { bar.getSomething(callback); } function callback(error, baz) { if (error) return console.log(error.message || error); // something else }

Slide 30

Slide 30 text

Node.js uncanny lessons buffers are a super friend •great for shuffling binary data and streams •not part of the v8 heap so not gc’d (only the reference)

Slide 31

Slide 31 text

Node.js uncanny lessons judge your alliances be scrupulous when choosing 3rd party modules

Slide 32

Slide 32 text

Node.js uncanny lessons these connections aren’t going to clean up themselves! app.get('/something', function(req, res, next) { if(req.params.foo) { // go along happy path var foo = getSomething(req.params.foo); res.send(foo); } }); what if this is false?

Slide 33

Slide 33 text

Node.js uncanny lessons this is supposed to be fun Remember If it’s not, maybe it’s time to try Lua??

Slide 34

Slide 34 text

Node.js uncanny lessons Questions?