node.js - async for the rest of us

Post on 17-May-2015

12.498 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

presented at the Denver Open Source Users Group 8/2/2011

TRANSCRIPT

node.jsasynchronous...

for the rest of us

Mike Brevoort8.2.2011DOSUG

code sample can be found at https://github.com/mbrevoort/node.js-presentation

agenda

the case for node.jsdeveloping with node

look at a few popular moduleslessons from the trenches

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

typical i/o latencyL1: 3 cyclesL2: 14 cycles

RAM: 250 cyclesDISK: 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

“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/

node.jsAn Evented I/O network server for Javascript

created by Ryan Dahl

sponsored by

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!

the event loopsingle threaded = no execution concurrencyall execution initiated by an eventevents may have zero to many callbacksevents are executed in orderTom Hughes-Croucher’s postman analogy

Installing nodemac, linux or windows (with cygwin hell)

fear not! stable windows support coming in v0.6.0 (~3wks)

# clone the git repogit clone git://github.com/joyent/node.gitcd node

# checkout the version you wantgit checkout v0.4.10

# build and install./configuremake && sudo make install

Running Node

REPL Read-Eval-Print-Loop

Invoke scriptnode 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+z6> require('fs').statSync('./blocking.js'){ dev: 234881026, ino: 3162208, mode: 33188, nlink: 1,.....

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/');

Not just HTTPvar 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/

simple irc demo

Developing with Node

install nodeinstall npmyour favorite text editorSublime Text 2, Textmate, vim, Emacs, Eclipse, whatever

npmnode package manager

created by Isaac Schlueter (Joyent)

npm

publish, install, discover, and develop node programsputs modules in a place where node can find themmanages dependencies

npm search, install# install a module (copy to node_modules)npm install socket.io

# install a specific versionnpm install socket.io@0.6.0

# install module globallynpm install socket.io -g

# searchnpm search socket

#infonpm info socket.io

npm registry

http://registry.npmjs.org/

npmjs.org stats

package.json{ "name": "express", "description": "Sinatra inspired web development framework", "version": "3.0.0", "author": "TJ Holowaychuk <tj@vision-media.ca>", "contributors": [ { "name": "TJ Holowaychuk", "email": "tj@vision-media.ca" }, { "name": "Aaron Heckmann", "email": "aaron.heckmann+github@gmail.com" }, { "name": "Ciaran Jessup", "email": "ciaranj@gmail.com" }, { "name": "Guillermo Rauch", "email": "rauchg@gmail.com" } ], "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" }}

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 .

a very strong community

nodejs.orgGoogle Group mailing listIRC #node.js on freenodeStack Overflow, LinkedIn groupsnodeconf, node summercamp, etc.

debugging

ndb - command line debuggerEclipse debugger plugin for V8node-inspectoris very nice!

node-inspectoruses WebKit Web Inspector

# install with npmnpm -g install node-inspector

# start node-inspectornode-inspector &

# start node in debug modenode --debug app.js

profilingnode-inspector optionally supports the V8 profiler

collects CPU and heap snapshots

Speaking of heaps...

garbage collection--trace-gc option to watch GC behavior V8 is a VM --> must GC

tuned for the browser20Mb - 40Mb per tab

Large node heap sizes == :(

GC Demo

several popular node modules

http://splashinthepacific.files.wordpress.com/2010/10/looking-glass-721.jpg

ExpressSinatra (Ruby) inspired web framework

created by TJ Holowaychuk

Expressrequest routingcontent negotiationview templating and partialssession supportstatic file servingfast, clean and powerful

Express Demo

a RESTful service?cute, terse. boring

let’s do something a bit more interesting...

streaming demo

Socket.ioUnified API for Websockets + fallbacks

created by Guillermo Rauch

Socket.iounified API for Comet style appstransport negotiation server and client librariesfeature rich, above and beyond what the websocket protocol prescribesheartbeats, timeouts, namespacing, volatile messages, message acknowledgements, etc.

socket.io demo

Lessons from the trenches

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

uncaught errorson error, node emits an ‘error’ event on the corresponding objectif 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!");});

prudentapproach

nuclearapproach

>>

plan for multiple processes from the start

each node process is bound to one coremany small processes better than one big oneuse Clusterhttps://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')

keep the heap small200Mb or less if you’re worried about GC pausemove data out of the node processinstead use Redis, MongoDb, etcencourages statelessness, encourages scalabilityreduces risk of losing a single node process

be weary of loopsfor (var i=0, l=entries.length; i<l; i++) { doSomething(entries[i]); }

innocent enough?

if # entries = 10,000

doSomething() takes ~1ms

you block for 10 seconds!

non-blocking loops// order mattersfunction 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// order doesn't mattervar leftToProcess = entries.length;

for (var i=0, l=entries.length; i<l; i++) { (function(foo) { process.nextTick(function() { doSomething(foo); if(--leftToProcess === 0) { done(); } }); })(entries[i]);}

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 parallelfor (var i=0, l=entries.length; i<l; i++) { (function(foo) { process.nextTick(function() { doSomethingAsync(foo, function() { if(--leftToProcess === 0) { done(); } }); }); })(entries[i]);}

set ulimit -nnode can handles 1000’s of connections?

but your OS says... Too many open files

default # file descriptors on most linux systems is 10241 FD per socket means max open sockets < 1024 increase the max # of file descriptors

ulimit -n <max # FD>ulimit -a to see current max

pooled outbound connections

node pools outbound http(s) connections by default for host + port combinationsdefault concurrent maxSockets per host + port is 5is this what you want?

// for http as of node v0.4.10require ('http') .getAgent("api.twitter.com", 80) .maxSockets = 100;

// for https as of node v0.4.10require ('https') .getAgent({ host:"docs.google.com", port: 443 }) .maxSockets = 100;

timeoutsexpect that any callback could fail and may not be calledanticipate conditions where both inbound or outbound connections may hanguse Mikeal Roger’s ‘request’ moduleI contributed timeout functionalityshould be part of node core ~v0.7/0.8

offload anything computationally intensive

spawn a child processrequire('child_process').spawn

call out to another system more apt to handle heavy liftinguse a job queue

be specific with package dependencies

{ "name": "Foo Package", "description": "my Foo package", "version": "1.0.0", "author": "Mike Brevoort <mikebre@ecollege.com>", "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?>

Let me tell you about my friend node

he’s a great multi-tasker but can only do one thing at a

time

Thank You!Questions?

Mike Brevoort@mbrevoortmike [at] brevoort [dot] com

top related