Introduction to Nodejs

  • 14,037 views
Uploaded on

Introduction to Nodejs with examples

Introduction to Nodejs with examples

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
14,037
On Slideshare
0
From Embeds
0
Number of Embeds
5

Actions

Shares
Downloads
416
Comments
0
Likes
25

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

Transcript

  • 1. verona21/05/2011
  • 2. gabriele lanagabriele.lana@cleancode.it twitter: @gabrielelana
  • 3. why node.js?“Nodes goal is to provide an easy way to buildscalable network programs” http://nodejs.org/#about
  • 4. 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
  • 5. Single threadsynchronous I/0
  • 6. Single threadsynchronous I/0
  • 7. multiple threadsynchronous I/0
  • 8. multiple threadsynchronous I/0
  • 9. you can “always” scale with multiplemachines but it costs you $$$
  • 10. but...what is HE doing?
  • 11. CPU BOUND TASKS? but...what is HE doing?
  • 12. CPU BOUND TASKS? ...OR I/o but... BOUNDwhat is HE TASKS? doing?
  • 13. synchronous I/0function 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() }}
  • 14. synchronous I/0function 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() }}
  • 15. synchronous I/0function 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() }}
  • 16. synchronous I/0function 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() }}
  • 17. single threadasynchronous I/0
  • 18. single threadasynchronous I/0 I am “callback” call me if you need me...
  • 19. hello_world_server.js Event Emitter var http = require("http") var server = http.createServer(function(request, response) { response.writeHead(200, { "Content-Type": "plain/text" }) response.write("Hello Worldn") response.end() }) server.listen(8080) console.log("> SERVER STARTED")
  • 20. hello_world_server.js Event Emitter var http = require("http") var server = http.createServer(function(request, response) { response.writeHead(200, { "Content-Type": "plain/text" }) response.write("Hello Worldn") response.end() }) server.listen(8080) console.log("> SERVER STARTED")
  • 21. hello_world_server.js Event Emitter var http = require("http") var server = http.createServer(function(request, response) { response.writeHead(200, { "Content-Type": "plain/text" }) response.write("Hello Worldn") response.end() }) server.listen(8080) console.log("> SERVER STARTED")
  • 22. hello_world_server.js Event Emitter var http = require("http") var server = http.createServer(function(request, response) { response.writeHead(200, { "Content-Type": "plain/text" }) response.write("Hello Worldn") response.end() }) server.listen(8080) console.log("> SERVER STARTED")
  • 23. Event Emittercoder@apollo:~/Work/src/node/examples$ node hello_world_server.js> SERVER STARTED #1coder@apollo:~$ curl "http://localhost:8080/"Hello World #2
  • 24. Event Emitter var server = require("http").createServer()hello_world_server.js 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 Worldn") server.close() }) response.on("close", function() { console.log("> RESPONSE CLOSED") }) })
  • 25. hello_world_server.js Event Emitter ... server.on("close", function() { console.log("> SERVER CLOSED") }) server.on("listening", function() { console.log("> SERVER STARTED") }) server.listen(8080)
  • 26. Event Emittercoder@apollo:~/Work/src/node/examples$ node hello_world_server.js> SERVER STARTED #1coder@apollo:~$ curl "http://localhost:8080/"Hello World #2 #1> REQUEST STARTED> REQUEST CLOSED> SERVER CLOSED
  • 27. why socomplicated?
  • 28. data streamS server.on("request", function(request, response) { var chunks = [], output = fs.createWriteStream("./output")proxy_stream.js 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("OKn") output.end() server.close() }) })
  • 29. data streamScoder@apollo:~/Work/src/node/examples$ node stream_doubler.js #1coder@apollo:~$ curl "http://localhost:8080/" --data $1n2n3nOK #2coder@apollo:~/Work/src/node/examples$ cat output246 #1
  • 30. why javascript?• Friendly callbacks• ubiquitous (well known)• no I/o primitives• one language to rule them all
  • 31. web applications before: a webmind shift #1 server with some application logic application Web server application application application
  • 32. web applications after: an applicationmind shift #1 accessible over http web server application
  • 33. web applications after: an applicationmind shift #1 that can communicate and collaborate with the world web server application
  • 34. web applications before: statefulmind shift #2 • no easy to scale • no easy to reuse v M c
  • 35. web applications before: statefulmind shift #2 • no easy to scale • no easy to reuse v M c conversation application state state
  • 36. web applications before: statefulmind shift #2 • no easy to scale • no easy to reuse v M c tightly coupled
  • 37. web applications after: statelessmind shift #2 • easy to scale • easy to reuse v http M c
  • 38. web applications after: statelessmind shift #2 • easy to scale • easy to reuse v http M cconversation application state state
  • 39. web applications after: statelessmind shift #2 http web server M http statefull connection• easy to scale M• easy to reuse
  • 40. no fluffjust stuff
  • 41. What aboutcpu bound tasks?
  • 42. the forklong_running_job.sh be with you #!/bin/bash for count in `seq 1 100`; do echo $count sleep 0.1 done
  • 43. the forklong_running_server.js be 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() }) })
  • 44. the fork be with youcoder@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...
  • 45. the fork be with youcoder@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...
  • 46. enter cometw at chwatch M spawn ch atw watch w w t a at ch ch
  • 47. enter cometdemo
  • 48. INSTALL NPM (node packet manager)coder@apollo:~/Work/src/node/examples$ curl http://npmjs.org/install.sh | sh...npm okIt workedcoder@apollo:~/Work/src/node/examples$ npm search | wc -l1918coder@apollo:~/Work/src/node/examples$ npm install connect socket.io underscorecoder@apollo:~/Work/src/node/examples$ npm list!"# connect@1.4.1$ !"" mime@1.2.2$ %"" qs@0.1.0%"" socket.io@0.6.17%"" underscore@1.1.6
  • 49. server/ routingprogress_server.js 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}) )
  • 50. server/ routingprogress_server.js 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("OKn") job.stdout.on("data", function(output) { var progress = parseInt(output.toString(), 10) _(connections).each(function(connection) { connection.send({"id": id, "progress": progress}) }) }) })
  • 51. server/ socket.ioprogress_server.js io.listen(server).on("connection", function(client) { connections[client.sessionId] = client client.on("disconnect", function() { delete connections[client.sessionId] }) })
  • 52. server/ simulationprogress_server.js 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() })
  • 53. interface/html <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>index.html </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>
  • 54. interface/ socket.io <html> ... <script> $(function() { var socket = new io.Socket()index.html socket.on("connect", function() { }) socket.on("disconnect", function() { }) socket.on("message", function(job) { $("#template").progressBar(job.id, job.progress) }) socket.connect() }) </script> </html>
  • 55. interface/ progress bar $.fn.progressBar = function(id, progress) { var $template = $(this) $("#job-" + id) .otherwise(function() { return $template.children().clone()progress.js .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() }) }) }
  • 56. interface/ progress bar $.fn.otherwise = function(ifNotFound) { if (this.length === 0) { return ifNotFound() }progress.js 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 }
  • 57. we can do itwith a littlemore “style”
  • 58. server/ event emitter var Job = (function() { var EventEmitter = require("events").EventEmitter,progress_server.js 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 })()
  • 59. server/ event emitterprogress_server.js 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("OKn") })
  • 60. node.js is awesome but when should i use it?
  • 61. when to use it?• chat/messaging• real-time applications• intelligent proxies• high concurrency applications• communication hubs• coordinators
  • 62. please tellme something bad about node.js
  • 63. 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
  • 64. vs
  • 65. Questions?
  • 66. gabriele lana gabriele.lana@cleancode.it twitter: @gabrielelanahttp://joind.in/3359