Introduction to Nodejs

69
verona 21/05/2011

description

Introduction to Nodejs with examples

Transcript of Introduction to Nodejs

Page 1: Introduction to Nodejs

verona21/05/2011

Page 3: Introduction to Nodejs

“Node's goal is to provide an easy

way to build scalable network

programs”

http://nodejs.org/#about

why node.js?

Page 4: Introduction to Nodejs

what is node.js?

• asynchronous i/o framework• core in c++ on top of v8• rest of it in javascript• swiss army knife for network

related stuffs• can handle thousands of

concurrent connections with minimal overhead (cpu/memory) on a single process

Page 5: Introduction to Nodejs

Single threadsynchronous I/0

Page 6: Introduction to Nodejs

Single threadsynchronous I/0

Page 7: Introduction to Nodejs

multiple threadsynchronous I/0

Page 8: Introduction to Nodejs

multiple threadsynchronous I/0

Page 9: Introduction to Nodejs

you can“always”

scale withmultiple

machines butit costsyou $$$

Page 10: Introduction to Nodejs
Page 11: Introduction to Nodejs

but...what is HEdoing?

Page 12: Introduction to Nodejs

but...what is HEdoing?

CPU BOUNDTASKS?

Page 13: Introduction to Nodejs

but...what is HEdoing?

CPU BOUNDTASKS?

...OR I/oBOUNDTASKS?

Page 14: Introduction to Nodejs

function productsInCart(request, response) { var db = new Db() var user = new User(request) if (user.isAuthorized("cart/products")) { response.write( JSON.stringify( db.productsInCart(user.cartId()) ) ) } else { response.unauthorized() }}

synchronous I/0

Page 15: Introduction to Nodejs

function productsInCart(request, response) { var db = new Db() var user = new User(request) if (user.isAuthorized("cart/products")) { response.write( JSON.stringify( db.productsInCart(user.cartId()) ) ) } else { response.unauthorized() }}

synchronous I/0

Page 16: Introduction to Nodejs

function productsInCart(request, response) { var db = new Db() var user = new User(request) if (user.isAuthorized("cart/products")) { response.write( JSON.stringify( db.productsInCart(user.cartId()) ) ) } else { response.unauthorized() }}

synchronous I/0

Page 17: Introduction to Nodejs

function productsInCart(request, response) { var db = new Db() var user = new User(request) if (user.isAuthorized("cart/products")) { response.write( JSON.stringify( db.productsInCart(user.cartId()) ) ) } else { response.unauthorized() }}

synchronous I/0

Page 18: Introduction to Nodejs

single threadasynchronous I/0

single threadasynchronous I/0

Page 19: Introduction to Nodejs

single threadasynchronous I/0

single threadasynchronous I/0

I am“callback”

call meif you

need me...

Page 20: Introduction to Nodejs

Event Emitter

var http = require("http")

var server = http.createServer(function(request, response) { response.writeHead(200, { "Content-Type": "plain/text" }) response.write("Hello World\n") response.end()})

server.listen(8080)

console.log("> SERVER STARTED")

hello

_w

orld_server.j

s

Page 21: Introduction to Nodejs

Event Emitter

var http = require("http")

var server = http.createServer(function(request, response) { response.writeHead(200, { "Content-Type": "plain/text" }) response.write("Hello World\n") response.end()})

server.listen(8080)

console.log("> SERVER STARTED")

hello

_w

orld_server.j

s

Page 22: Introduction to Nodejs

Event Emitter

var http = require("http")

var server = http.createServer(function(request, response) { response.writeHead(200, { "Content-Type": "plain/text" }) response.write("Hello World\n") response.end()})

server.listen(8080)

console.log("> SERVER STARTED")

hello

_w

orld_server.j

s

Page 23: Introduction to Nodejs

Event Emitter

var http = require("http")

var server = http.createServer(function(request, response) { response.writeHead(200, { "Content-Type": "plain/text" }) response.write("Hello World\n") response.end()})

server.listen(8080)

console.log("> SERVER STARTED")

hello

_w

orld_server.j

s

Page 24: Introduction to Nodejs

coder@apollo:~/Work/src/node/examples$ node hello_world_server.js> SERVER STARTED

coder@apollo:~$ curl "http://localhost:8080/"Hello World

#1

#2

Event Emitter

Page 25: Introduction to Nodejs

var server = require("http").createServer()

server.on("request", function(request, response) { console.log("> REQUEST STARTED") request.on("end", function() { console.log("> REQUEST CLOSED") response.writeHead(200, { "Content-Type": "plain/text" }) response.end("Hello World\n") server.close() }) response.on("close", function() { console.log("> RESPONSE CLOSED") })})h

ello

_w

orld_server.j

sEvent Emitter

Page 26: Introduction to Nodejs

...

server.on("close", function() { console.log("> SERVER CLOSED")})

server.on("listening", function() { console.log("> SERVER STARTED")})

server.listen(8080)

hello

_w

orld_server.j

sEvent Emitter

Page 27: Introduction to Nodejs

coder@apollo:~/Work/src/node/examples$ node hello_world_server.js> SERVER STARTED

coder@apollo:~$ curl "http://localhost:8080/"Hello World

> REQUEST STARTED> REQUEST CLOSED> SERVER CLOSED

#1

#2

#1

Event Emitter

Page 28: Introduction to Nodejs

why socomplicated?

Page 29: Introduction to Nodejs

server.on("request", function(request, response) { var chunks = [], output = fs.createWriteStream("./output")

request.on("data", function(chunk) { chunks = forEachLine(chunks.concat(chunk), function(line) { output.write(parseInt(line, 10) * 2) output.write("\n") }) })

request.on("end", function() { response.writeHead(200, { "Content-Type": "plain/text" }) response.end("OK\n") output.end() server.close() })})

pro

xy_stream

.jsdata streamS

Page 30: Introduction to Nodejs

coder@apollo:~/Work/src/node/examples$ node stream_doubler.js

coder@apollo:~$ curl "http://localhost:8080/" --data $'1\n2\n3\n'OK

coder@apollo:~/Work/src/node/examples$ cat output 246

#1

#2

#1

data streamS

Page 31: Introduction to Nodejs

why javascript?

• Friendly callbacks• ubiquitous (well known)• no I/o primitives• one language to rule them all

Page 32: Introduction to Nodejs

mind shift #1

application

application

application

application

Web s

erver

web applications before: a web

server with some application logic

Page 33: Introduction to Nodejs

mind shift #1

web applications after: an application

accessible over http

web s

erver

application

Page 34: Introduction to Nodejs

mind shift #1

web applications after: an application

that can communicate and collaborate with

the worldw

eb s

erver

application

Page 35: Introduction to Nodejs

mind shift #2

web applications before: stateful

• no easy to scale• no easy to reuse

M

c

v

Page 36: Introduction to Nodejs

mind shift #2

web applications before: stateful

• no easy to scale• no easy to reuse

applicationstate

conversationstate

M

c

v

Page 37: Introduction to Nodejs

mind shift #2

web applications before: stateful

• no easy to scale• no easy to reuse

M

c

v

tightly coupled

Page 38: Introduction to Nodejs

mind shift #2

web applications after: stateless

• easy to scale• easy to reuse

http M

c

v

Page 39: Introduction to Nodejs

mind shift #2

web applications after: stateless

• easy to scale• easy to reuse

http M

c

v

conversationstate

applicationstate

Page 40: Introduction to Nodejs

mind shift #2

web applications after: stateless

• easy to scale• easy to reuse

http

M

http

web s

erver

statefullconnection

M

Page 41: Introduction to Nodejs

no fluffjust stuff

Page 42: Introduction to Nodejs

What aboutcpu bound

tasks?

Page 43: Introduction to Nodejs

the forkbe with you

#!/bin/bash

for count in `seq 1 100`; do echo $count sleep 0.1done

lo

ng_runnin

g_jo

b.s

h

Page 44: Introduction to Nodejs

the forkbe with you

var spawn = require("child_process").spawn, server = require("http").createServer()

server.on("request", function(request, response) { var job = spawn("./long_running_job.sh")

job.stdout.on("data", function(tick) { response.write(tick) })

job.on("exit", function() { response.end() })})

lo

ng_runnin

g_server.j

s

Page 45: Introduction to Nodejs

the forkbe with you

coder@apollo:~$ ab -c 1 -n 1 "http://localhost:8080/"...Concurrency Level: 1Time taken for tests: 10.531 seconds...

coder@apollo:~$ ab -c 1 -n 2 "http://localhost:8080/"...Concurrency Level: 1Time taken for tests: 20.108 seconds...

Page 46: Introduction to Nodejs

the forkbe with you

coder@apollo:~$ ab -c 2 -n 1 "http://localhost:8080/"...Concurrency Level: 2Time taken for tests: 10.634 seconds...

coder@apollo:~$ ab -c 100 -n 100 "http://localhost:8080/"...Concurrency Level: 100Time taken for tests: 11.198 seconds...

coder@apollo:~$ ab -c 500 -n 500 "http://localhost:8080/"...Concurrency Level: 500Time taken for tests: 31.082 seconds...

Page 47: Introduction to Nodejs

enter comet

watc

h

Mwatch

watch

spawn

watch

watc

h

watc

h

Page 48: Introduction to Nodejs

enter comet

demo

Page 49: Introduction to Nodejs

INSTALL NPM(node packet manager)

coder@apollo:~/Work/src/node/examples$ curl http://npmjs.org/install.sh | sh...npm okIt worked

coder@apollo:~/Work/src/node/examples$ npm search | wc -l1918

coder@apollo:~/Work/src/node/examples$ npm install connect socket.io underscorecoder@apollo:~/Work/src/node/examples$ npm list!"# [email protected] $ !"" [email protected] $ %"" [email protected] %"" [email protected]%"" [email protected]

Page 50: Introduction to Nodejs

pro

gress_server.j

s

var server = connect( connect.favicon(), connect.logger({"buffer": true}), connect.router(function(resource) { resource.post("/spawn", function(request, response) { ... }) }), connect.static(path.join(__dirname, "public"), {"cache": true}))

server/routing

Page 51: Introduction to Nodejs

pro

gress_server.j

s resource.post("/spawn", function(request, response) { var job = spawn(path.join(__dirname, "bin", "job.sh")), id = ++counter response.writeHead(202, {"Content-Type": "plain/text"}) response.end("OK\n")

job.stdout.on("data", function(output) { var progress = parseInt(output.toString(), 10) _(connections).each(function(connection) { connection.send({"id": id, "progress": progress}) }) }) })

server/routing

Page 52: Introduction to Nodejs

pro

gress_server.j

s

io.listen(server).on("connection", function(client) {

connections[client.sessionId] = client

client.on("disconnect", function() { delete connections[client.sessionId] })

})

server/socket.io

Page 53: Introduction to Nodejs

pro

gress_server.j

s server.listen(port, host, function() { var spawnJobsInterval = setInterval(function() { http.request({ "port": port, "host": host, "method": "POST", "path": "/spawn" }).end() }, Math.floor(Math.random()*2000)+500)

server.on("close", function() { clearInterval(spawnJobsInterval) process.exit() })})

process.on("SIGINT", function() { server.close()})

server/simulation

Page 54: Introduction to Nodejs

<html> <head> <title>Node.js - Long Running Jobs</title> <link href="css/style.css" rel="stylesheet" /> <script type="text/javascript" src="/socket.io/socket.io.js"></script> <script type="text/javascript" src="js/jquery-1.6.0.js"></script> <script type="text/javascript" src="js/progress.js"></script> </head> <body> <div id="template"> <div class="progress-container"> <span class="progress-text">JOB/? - ?%</span> <div class="progress-bar"></div> </div> </div> <div id="container"> </div> </body> <script> ... </script></html>

interface/htmlin

dex.h

tml

Page 55: Introduction to Nodejs

<html> ... <script> $(function() { var socket = new io.Socket()

socket.on("connect", function() { }) socket.on("disconnect", function() { }) socket.on("message", function(job) { $("#template").progressBar(job.id, job.progress) })

socket.connect() }) </script></html>

interface/socket.io

index.h

tml

Page 56: Introduction to Nodejs

$.fn.progressBar = function(id, progress) { var $template = $(this) $("#job-" + id) .otherwise(function() { return $template.children().clone() .attr("id", "job-" + id) .find(".progress-text").text("JOB/" + id + " - 0%").end() .appendTo("#container") }) .find(".progress-text").text("JOB/" + id + " - " + progress + "%").end() .find(".progress-bar").css("width", progress + "%").end() .tap(function() { if (progress === 100) { $(this) .find(".progress-bar").css("background-color", "red").end() .after(500, function() { $(this).fadeOut("slow", function() { $(this).remove() }) }) }

interface/progress bar

pro

gress.j

s

Page 57: Introduction to Nodejs

$.fn.otherwise = function(ifNotFound) { if (this.length === 0) { return ifNotFound() } return this}

$.fn.after = function(milliseconds, doSomething) { var self = this setTimeout(function() { doSomething.apply(self) }, milliseconds) return this}

$.fn.tap = function() { var fn = Array.prototype.shift.apply(arguments) fn.apply(this, arguments) return this}

interface/progress bar

pro

gress.j

s

Page 58: Introduction to Nodejs

single threadasynchronous I/0

we can do itwith a littlemore “style”

Page 59: Introduction to Nodejs

pro

gress_server.j

s

var Job = (function() { var EventEmitter = require("events").EventEmitter, spawn = require("child_process").spawn, inherits = require("util").inherits

function Job(id) { EventEmitter.call(this) this.id = id }

inherits(Job, EventEmitter)

Job.prototype.run = function() { return _(this).tap(function(job) { spawn(path.join(__dirname, "bin", "job.sh")) .stdout.on("data", function(output) { job.emit("progress", job.id, parseInt(output.toString(), 10)) }) }) } return Job})()

server/event emitter

Page 60: Introduction to Nodejs

pro

gress_server.j

s

resource.post("/spawn", function(request, response) { new Job(++counter) .on("progress", function(id, progress) { _(connections).each(function(connection) { connection.send({"id": id, "progress": progress}) }) }) .run()

response.writeHead(202, { "Content-Type": "plain/text" }) response.end("OK\n")})

server/event emitter

Page 61: Introduction to Nodejs

node.js is awesome but when should i use it?

Page 62: Introduction to Nodejs

• chat/messaging• real-time applications• intelligent proxies• high concurrency applications• communication hubs• coordinators

when to use it?

Page 63: Introduction to Nodejs

please tell me somethingbad aboutnode.js

Page 64: Introduction to Nodejs

some warnings

• release stable 0.4.7 (young)• lots of stuffs to look at• lots of half backed stuffs• retro compatibility???• bad at handling static contents• Bad at handling binary contents• hard to find organized and

authoritative informations

Page 65: Introduction to Nodejs

vs

Page 66: Introduction to Nodejs
Page 67: Introduction to Nodejs
Page 68: Introduction to Nodejs

Questions?