Slide 1

Slide 1 text

node.js asynchronous... for the rest of us Mike Brevoort code sample can be found at https://github.com/mbrevoort/node.js-presentation 1

Slide 2

Slide 2 text

agenda the case for node.js developing with node look at a few popular modules lessons from the trenches 2

Slide 3

Slide 3 text

3

Slide 4

Slide 4 text

typical n-tier run-a-round browser makes call to web server (waits) web server makes call to database (waits) web server returns result to browser Response time is dominated by time waiting 4

Slide 5

Slide 5 text

typical i/o latency L1: 3 cycles L2: 14 cycles RAM: 250 cycles DISK: 41,000,000 cycles NETWORK: 240,000,000 cycles http://nodejs.org/jsconf.pdf L1 L2 RAM Disk Network 0 60,000,000 120,000,000 180,000,000 240,000,000 300,000,000 5

Slide 6

Slide 6 text

http://xach.livejournal.com/ 170311.html 6

Slide 7

Slide 7 text

“Most languages were designed to solve computational problems, but Node.js is different. Node.js was designed from the ground up to efficiently handle the communication that is at the heart of modern web applications.” http://www.joyentcloud.com/products/smart-appliances/ node-js-smartmachine/ 7

Slide 8

Slide 8 text

node.js An Evented I/O network server for Javascript created by Ryan Dahl sponsored by 8

Slide 9

Slide 9 text

http://platformjs.wordpress.com/2010/11/24/node-js-under- the-hood/ Runs Javascript, but isn’t primarily Javascript 9

Slide 10

Slide 10 text

Why Javascript? most widely used programing language of the web “never under estimate the power of familiarity and friendliness” - Stacey Higginbotham, GigaOM async by nature - the browser is a single threaded event loop 10

Slide 11

Slide 11 text

Why Javascript? most widely used programing language of the web “never under estimate the power of familiarity and friendliness” - Stacey Higginbotham, GigaOM async by nature - the browser is a single threaded event loop BAH! It’s a toy language! 10

Slide 12

Slide 12 text

the event loop single threaded = no execution concurrency all execution initiated by an event events may have zero to many callbacks events are executed in order 11

Slide 13

Slide 13 text

Installing node mac, linux or windows (with cygwin hell) fear not! stable windows support coming in v0.6.0 (any day)... BUT # clone the git repo git clone git://github.com/joyent/node.git cd node # checkout the version you want git checkout v0.4.10 # build and install ./configure make && sudo make install 12

Slide 14

Slide 14 text

Running Node REPL Read-Eval-Print-Loop Invoke script node app.js arg1 arg2 process.argv[0] === "node" process.argv[1] === "app.js" process.argv[2] === "arg1" process.argv[3] === "arg2" ~/ node > var x=1, y=2, z=3; > x+y+z 6 > require('fs').statSync('./blocking.js') { dev: 234881026, ino: 3162208, mode: 33188, nlink: 1, ..... 13

Slide 15

Slide 15 text

Hello World HTTP Server var http = require('http'); http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World\n'); }).listen(8080, "127.0.0.1"); console.log('Server running at http://127.0.0.1:8080/'); 14

Slide 16

Slide 16 text

Not just HTTP var net = require('net'); var server = net.createServer(function (socket) { socket.write("Echo server\r\n"); socket.pipe(socket); }); server.listen(1337, "127.0.0.1"); http://nodejs.org/ 15

Slide 17

Slide 17 text

simple irc demo 16

Slide 18

Slide 18 text

Developing with Node install node install npm your favorite text editor Sublime Text 2, Textmate, vim, Emacs, Eclipse, whatever 17

Slide 19

Slide 19 text

npm node package manager created by Isaac Schlueter (Joyent) 18

Slide 20

Slide 20 text

npm publish, install, discover, and develop node programs puts modules in a place where node can find them manages dependencies 19

Slide 21

Slide 21 text

npm search, install # install a module (copy to node_modules) npm install socket.io # install a specific version npm install [email protected] # install module globally npm install socket.io -g # search npm search socket #info npm info socket.io 20

Slide 22

Slide 22 text

npm registry http://registry.npmjs.org/ 21

Slide 23

Slide 23 text

npmjs.org stats 22

Slide 24

Slide 24 text

package.json { "name": "express", "description": "Sinatra inspired web development framework", "version": "3.0.0", "author": "TJ Holowaychuk ", "contributors": [ { "name": "TJ Holowaychuk", "email": "[email protected]" }, { "name": "Aaron Heckmann", "email": "[email protected]" }, { "name": "Ciaran Jessup", "email": "[email protected]" }, { "name": "Guillermo Rauch", "email": "[email protected]" } ], "dependencies": { "connect": ">= 1.5.2 < 2.0.0", "mime": ">= 0.0.1", "qs": ">= 0.3.0" }, "devDependencies": { "connect-form": "0.2.1", "ejs": "0.4.2", "expresso": "0.8.1", "hamljs": "0.5.1", "jade": "0.13.0", "stylus": "0.13.0", "should": "0.2.1", "express-messages": "0.0.2", "node-markdown": ">= 0.0.1", "connect-redis": ">= 0.0.1" }, "keywords": ["framework", "sinatra", "web", "rest", "restful"], "repository": "git://github.com/visionmedia/express", "main": "index", "bin": { "express": "./bin/express" }, "scripts": { "test": "make test", "prepublish" : "npm prune" }, "engines": { "node": ">= 0.4.9 < 0.7.0" } } 23

Slide 25

Slide 25 text

npm install . package.json isn’t just for modules published to npm npm can help you manage and install dependencies in any project # from the same directory # as package.json npm install . 24

Slide 27

Slide 27 text

Public NPM Private NPM NPM Proxy back at the ranch... 26

Slide 28

Slide 28 text

Public NPM Private NPM NPM Proxy GETs back at the ranch... 26

Slide 29

Slide 29 text

Public NPM Private NPM NPM Proxy 1 GETs back at the ranch... 26

Slide 30

Slide 30 text

Public NPM Private NPM NPM Proxy 1 2 GETs back at the ranch... 26

Slide 31

Slide 31 text

Public NPM Private NPM NPM Proxy 1 2 GETs publish search back at the ranch... 26

Slide 32

Slide 32 text

Public NPM Private NPM NPM Proxy 1 2 GETs publish search search back at the ranch... 26

Slide 33

Slide 33 text

Public NPM Private NPM NPM Proxy 1 2 GETs publish search search http://npm.petdev.com:9000 back at the ranch... 26

Slide 34

Slide 34 text

Public NPM Private NPM NPM Proxy 1 2 GETs publish search search http://npm.petdev.com:9000 http://npm.petdev.com:5984 back at the ranch... 26

Slide 35

Slide 35 text

a very strong community nodejs.org Google Group mailing list IRC #node.js on freenode Stack Overflow, LinkedIn groups nodeconf, node summercamp, etc. 27

Slide 36

Slide 36 text

debugging ndb - command line debugger Eclipse debugger plugin for V8 node-inspector is very nice! 28

Slide 37

Slide 37 text

node-inspector uses WebKit Web Inspector # install with npm npm -g install node-inspector # start node-inspector node-inspector & # start node in debug mode node --debug app.js 29

Slide 38

Slide 38 text

node-inspector uses WebKit Web Inspector # install with npm npm -g install node-inspector # start node-inspector node-inspector & # start node in debug mode node --debug app.js 29

Slide 39

Slide 39 text

profiling node-inspector optionally supports the V8 profiler collects CPU and heap snapshots Speaking of heaps... 30

Slide 40

Slide 40 text

garbage collection --trace-gc option to watch GC behavior V8 is a VM --> must GC tuned for the browser 20Mb - 40Mb per tab Large node heap sizes == :( 31

Slide 41

Slide 41 text

GC Demo 32

Slide 42

Slide 42 text

several popular node modules http://splashinthepacific.files.wordpress.com/2010/10/looking-glass-721.jpg 33

Slide 43

Slide 43 text

Express Sinatra (Ruby) inspired web framework created by TJ Holowaychuk 34

Slide 44

Slide 44 text

Express request routing content negotiation view templating and partials session support static file serving fast, clean and powerful 35

Slide 45

Slide 45 text

Express Demo 36

Slide 46

Slide 46 text

Express Demo 36

Slide 47

Slide 47 text

a RESTful service? cute, terse. boring let’s do something a bit more interesting... 37

Slide 48

Slide 48 text

streaming demo 38

Slide 49

Slide 49 text

Socket.io Unified API for Websockets + fallbacks created by Guillermo Rauch 39

Slide 50

Slide 50 text

Socket.io unified API for Comet style apps transport negotiation server and client libraries feature rich, above and beyond what the websocket protocol prescribes heartbeats, timeouts, namespacing, volatile messages, message acknowledgements, etc. 40

Slide 51

Slide 51 text

socket.io demo 41

Slide 52

Slide 52 text

Lessons from the trenches 42

Slide 53

Slide 53 text

asynchronous learning curve 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); } }); }); easy to write code like this 43

Slide 54

Slide 54 text

uncaught errors 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 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 > > 44

Slide 55

Slide 55 text

plan for multiple processes from the start each node process is bound to one core many small processes better than one big one use Cluster https://github.com/learnboost/cluster var cluster = require('cluster'); cluster('app.js') .set('workers', 16) // defaults to # of cores .use(cluster.logger('logs')) .use(cluster.stats()) .use(cluster.cli()) .use(cluster.repl(8888)) .listen('80') 45

Slide 56

Slide 56 text

keep the heap small 200Mb or less if you’re worried about GC pause move data out of the node process instead use Redis, MongoDb, etc encourages statelessness, encourages scalability reduces risk of losing a single node process 46

Slide 57

Slide 57 text

everything you do blocks http://redriverpak.files.wordpress.com/ 2010/08/vwtouareg-road-block.jpg 47

Slide 58

Slide 58 text

everything you do blocks No CPU for you! http://redriverpak.files.wordpress.com/ 2010/08/vwtouareg-road-block.jpg 47

Slide 59

Slide 59 text

everything you do blocks No CPU for you! http://redriverpak.files.wordpress.com/ 2010/08/vwtouareg-road-block.jpg 47

Slide 60

Slide 60 text

be weary of loops for (var i=0, l=entries.length; i

Slide 61

Slide 61 text

non-blocking loops // 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); 49

Slide 62

Slide 62 text

non-blocking loops // order doesn't matter var leftToProcess = entries.length; for (var i=0, l=entries.length; i

Slide 63

Slide 63 text

non-blocking loops // order doesn't matter // doSomething takes callback and is Async // doSomethingAsync's happen in parallel var leftToProcess = entries.length; // doSomething's will be executed in parallel for (var i=0, l=entries.length; i

Slide 64

Slide 64 text

set ulimit -n node can handles 1000’s of connections? but your OS says... Too many open files default # file descriptors on most linux 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 52

Slide 65

Slide 65 text

pooled outbound connections node pools outbound http(s) connections by default for host + port combinations default concurrent maxSockets per host + port is 5 is this what you want? // for http as of node v0.4.10 require ('http') .getAgent("api.twitter.com", 80) .maxSockets = 100; // for https as of node v0.4.10 require ('https') .getAgent({ host:"docs.google.com", port: 443 }) .maxSockets = 100; 53

Slide 66

Slide 66 text

timeouts expect that any callback could fail and may not be called anticipate conditions where both inbound or outbound connections may hang use Mikeal Roger’s ‘request’ module I contributed timeout functionality should be part of node core ~v0.7/0.8 54

Slide 67

Slide 67 text

offload anything computationally intensive spawn a child process require('child_process').spawn call out to another system more apt to handle heavy lifting use a job queue 55

Slide 68

Slide 68 text

be specific with package dependencies { "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? > 56

Slide 69

Slide 69 text

Thank You! Questions? 58