SlideShare a Scribd company logo
Node.js Tutorial
Tom Hughes-Croucher, Principal
Jetpacks For Dinosaurs, LLC

tom@jetpacksfordinosaurs.com
@sh1mmer
Introduction
•   Tom Hughes-Croucher
•   Principal at Jetpacks for Dinosaurs
•   Node.js and High-performance web site
    consulting and training
•   Walmart, MySpace, Joyent,Yahoo!, NASA, Tesco,
    etc
•   Node.js contributor
•   Lead author of "Node: Up and Running"
Scalable Server-Side Code with JavaScript




                Node                       Up and Running




                                          Tom Hughes-Croucher




  http://ofps.oreilly.com/titles/9781449398583/
http://shop.oreilly.com/product/0636920015956.do
Training
  Online




 In person
Node refresher
Code!
Interactive Debugging
Enki:~/Code/node-examples $ node --debug
helloworld.js
debugger listening on port 5858
Server running at http://127.0.0.1:8124/
enki:~ sh1mmer$ ps -A | grep node
19093 ttys001 0:00.39 node index.js
19273 ttys002 0:00.00 grep node
enki:~ sh1mmer$ kill -s USR1 19093
enki:~ sh1mmer$ node index.js
Hit SIGUSR1 - starting debugger agent.
debugger listening on port 5858
Enki:~ $ sudo npm install -g node-inspector
node-inspector@0.1.8 ./node_modules/node-inspector
├── websocket-server@1.4.04
└── paperboy@0.0.2
Enki:~ $ node-inspector
visit http://0.0.0.0:8080/debug?port=5858 to start
debugging
Writing robust Node.js applications
Exercises

• Modify a basic HTTP server to return the
  text "I'm learning Node"
• Change the HTTP response to HTML and
  return your text in an HTML page
• Return the User-Agent string from the
  browser as part of your HTML page
Express.js
Sinatra Style MVC
   framework
var app = require('express').createServer();

app.get('/', function(req, res){
    res.send('hello world');
});

app.listen(3000);
HTTP Verb Oriented
Middleware
app.use(express.bodyParser());
app.use(express.cookieParser());

app.post('/', function(req, res){
  // Perhaps we posted several items with a form
  // (use the bodyParser() middleware for this)
  var items = req.body.items;
  console.log(items);
  res.send('logging');
});
Templating
var express = require("express");

app.configure(function () {
     var public = __dirname + "/../public/";
     public = require("path").normalize(public);

      app.set("views", __dirname + "/views");
      app.set("view engine", "jade");
});

app.get("/", function (req, res) {
     res.render("index", {
        locals : {
           h1: 'Router Stats',
           scripts : [
              "/public/smoothie.js",
              "/public/raphael.js",
              "/public/base.js",
              "/public/gfx.js",
              "/public/explore.js",
              "/public/app.js"
           ]
        }
     }
});
Exercise
• Create an Express server
• Make routes for ‘/’ & ‘/products’
• Serve two different pages based on
  value of the query string parameter
  "page"

• Create a redirect from /old to /new
• Set a cookie on the client
Building a chat server
Node Architectures
The obvious
architecture
Client   Front-end   Database




User       Node        DB
What about this?
Heavy
         Front-end
Client               Processor   Database
           Farm
                       Work



User       Node
           Node       Node
                      Node         DB
            Node
            Node       Node
                       Node
Don’t we want to move
    “heavy work”?
Client → Server   Server → DB




         Computation     Computation
Better architecture
Front-end
Client                Database
           Farm

                         DB


User       Node
           Node
            Node
            Node                    Big Slow
                     Logging farm
                                      Disk

                        Node
                        Node          Disk
Move work which isn’t
user-facing out of main
      event loop
Ensure consistency of
  Node processes
Distributing work
Cluster
var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  // Fork workers.
  for (var i = 0; i < numCPUs; i++) {
    cluster.fork();
  }
  cluster.on('death', function(worker) {
    console.log('worker ' + worker.pid + ' died');
  });
} else {
  // Worker processes have a http server.
  http.Server(function(req, res) {
    res.writeHead(200);
    res.end("hello worldn"); }).listen(8000);
}
Use load balancers to
  distribute across
       servers
node-proxy
   squid
  varnish
 haproxy
Unbundle SSL
          stud, stunnel, etc

http://vincent.bernat.im/en/blog/2011-
   ssl-benchmark.html#conclusion
Sharding
Disclaimer:
 Sharding is hard
See CAP theorem
Socket.io
Web Socket library
client and server
with the shared API
var app = require('express').createServer(),
   io = require('socket.io').listen(app);

app.listen(80);

app.get('/', function (req, res) {
  res.sendfile(__dirname + '/index.html');
});

io.sockets.on('connection', function (socket) {
  socket.emit('news', { hello: 'world' });
  socket.on('my other event', function (data) {
    console.log(data);
  });
});
<!DOCTYPE html>
<html>
<body>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost');
socket.connect();
socket.on('connect', function(){ console.log('connect') })
socket.on('message', function(){ console.log('message') })
socket.on('disconnect', function(){ console.log('disconnect'); })
</script>
</body>
</html>
Transports
• WebSocket
• Adobe® Flash® Socket
• AJAX long polling
• AJAX multipart streaming
• Forever iframe
• JSONP Polling
options = {
 transports: ['websocket'],
 log: util.log }

io.listen(server, options)
// note, io.listen() will create a http server for you
var io = require('socket.io').listen(80);

io.sockets.on('connection', function (socket) {
  io.sockets.emit('this', { will: 'be received by everyone'});

  socket.on('private message', function (from, msg) {
    console.log('I received a private message by ', from, ' saying ',
msg);
  });

  socket.on('disconnect', function () {
    sockets.emit('user disconnected');
  });
});
Exercises
• Create a socket.io connect to an
  express server
• Create a route which loads a page that
  includes socket.io

• Send "hello world" to the client
  sockets
• Make the client respond with "thanks"
  and disconnect from the server
Using Redis with
   Socket.io
Why use Redis?

• No shared memory
• Cluster on server won’t share client data
• Multiple servers can use the same Redis
var express = require('express')
, app = express.createServer();

var sio = require('socket.io')
, RedisStore = sio.RedisStore
, io = sio.listen(app);

app.listen(8080);

app.get('/', function(req,res) {
  res.sendfile(__dirname + '/index.html');
});

io.sockets.on('connection', function (socket) {
  socket.on('chat', function (data) {
    console.log(data);
    socket.broadcast.emit('chat', data);
  })
});
var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  // Fork workers.
  for (var i = 0; i < numCPUs; i++) {
    cluster.fork();
  }
} else {
  var express = require('express')
  , app = express.createServer();

    var sio = require('socket.io')
    , RedisStore = sio.RedisStore
    , io = sio.listen(app);

    app.listen(8080);

    app.get('/', function(req,res) {
      res.sendfile(__dirname + '/index.html');
    });

    // Somehow pass this information to the workers
    io.set('store', new RedisStore);

    // Do the work here
    io.sockets.on('connection', function (socket) {
      socket.on('chat', function (data) {
        console.log(data);
        socket.broadcast.emit('chat', data);
      })
    });
}
Node in production
Error handling
var http = require('http');

var req = http.request({
   host: 'www.google.com',
   path: '/',
   port: 80,
   method: 'POST'
   }, function (response) {
   // Do stuff with the response here
});
node.js:134
   throw e; // process.nextTick error, or 'error' event on first tick
^ Error: Uncaught, unspecified 'error' event.
at EventEmitter.emit (events.js:47:15) at Object.<anonymous> (/
Users/you/y-u-no-listen-for-errors.js:5:9) at Module._compile
(module.js:404:26) at Object..js (module.js:410:10) at Module.load
(module.js:336:31) at Function._load (module.js:297:12) at
Array.<anonymous> (module.js:423:10) at EventEmitter._tickCallback
(node.js:126:26)
var http = require('http');

try {
  var req = http.request({
     host: 'www.google.com',
     path: '/',
     port: 80,
     method: 'POST'
     }, function (response) {
     // Do stuff with the response here
  });
} catch(e) {
var http = require('http');

var req = http.request({
   host: 'www.google.com',
   path: '/',
   port: 80,
   method: 'POST'
   }, function (response) {
   // Do stuff with the response here
});

req.on('error', function (err) {
  //safely handle this if possible
});
// Suppress errors
process.on('uncaughtException', function (err) {
  // Log it!
  console.dir(err);
});
EventEmitter leaks
(node) warning: possible EventEmitter memory leak detected. 11
listeners added. Use emitter.setMaxListeners() to increase limit. Trace:
  at Pool.<anonymous> (events.js:101:17)
  at Object.proxyRequest (~/http-proxy/lib/node-http-proxy.js:185:7)
  at Server.<anonymous> (/Users/some-user/myapp.js:14:9)
  at Server.emit (events.js:45:17)
  at HTTPParser.onIncoming (http.js:1078:12)
  at HTTPParser.onHeadersComplete (http.js:87:31)
  at Socket.ondata (http.js:977:22)
  at Socket._onReadable (net.js:654:27)
  at IOWatcher.onReadable [as callback] (net.js:156:10)
var events = require('events');

function doSomethingThenTellMe () {
 var emitter = new events.EventEmitter();

 setTimeout(function () {
   emitter.emit('done');
   }, 2000);
   return emitter;
 }

var doingIt = doSomethingThenTellMe();

doingIt.on('done', function () {
  console.log("Ok, it's done");
});
// Why are you using `.on()`?
// You only expect this event to fire once.
once() is awesome
var events = require('events');

function doSomethingThenTellMe () {
 var emitter = new events.EventEmitter();

 setTimeout(function () {
   emitter.emit('done');
   }, 2000);
   return emitter;
 }

var doingIt = doSomethingThenTellMe();

doingIt.once('done', function () {
  console.log("Ok, it's done");
});
Process monitoring
Upstart
description "node.js server"
author    "croucher`"

start on startup
stop on shutdown

script
   # We found $HOME is needed. Without it, we ran into
problems
   export HOME="/root"

  exec /usr/local/bin/node /var/noderoot/index.js 2>&1 >> /
var/log/node.log
end script
forever
$ cd /path/to/your/app
$ forever start bin/yourapp
info: Running action: start
info: Forever processing
file: examples/server.js
$ forever list
info: Running action: list
info: Forever processes running
  [0] bin/yourapp [77041, 77040] /Users/You/.forever
20dL.log 0:0:0:1.788
NPM Packaging
Enki:~/Code/node-dnsserve(master) $ ls
LICENSE
 
 README
 
 dnsserver.js
package.json
Enki:~/Code/node-dnsserve(master) $
{
  "name": "dns-server",
  "description": "DNS server for Node",
  "version": "0.0.1a",
  "author": "Tom Hughes-Croucher
<tom.croucher@gmail.com>",
  "main" : "dnsserver"
}
Enki:~/Code/node-dnsserve(master) $ sudo npm
install . -g
dns-server@0.0.1a /usr/local/lib/node_modules/dns-
server
Enki:~/Code/node-dnsserve(master) $
Enki:~/Code/node-dnsserve(master) $ sudo npm link

/usr/local/lib/node_modules/dns-server -> /Users/sh1mmer/Code/
node-dnsserve
Enki:~/Code/node-dnsserve(master) $ npm ls -g
/usr/local/lib
├── dns-server@0.0.1a -> /Users/sh1mmer/Code/node-dnsserve
└─┬ npm@1.0.6
 ├── abbrev@1.0.3
 ├── node-uuid@1.1.0
 ├── nopt@1.0.4
 └── semver@1.0.5
Enki:~/Code/node-dnsserve(master) $
Enki:~/Code/node-dnsserve(master) $ npm adduser
Username: foobarbaz
Password:
Email:
Enki:~/Code/node-dnsserve(master) $ npm publish
npm WARN Sending authorization over insecure
channel.
Enki:~/Code/node-dnsserve(master) $
{
    "name": "winston",
    "description": "A multi-transport async logging library for Node.js",
    "version": "0.2.7",
    "author": "Charlie Robbins <charlie.robbins@gmail.com>",
    "contributors": [
      { "name": "Matthew Bergman", "email": "mzbphoto@gmail.com" }
    ],
    "repository": {
      "type": "git",
      "url": "http://github.com/indexzero/winston.git"
    },
    "keywords": ["logging", "sysadmin", "tools"],
    "dependencies": {
      "colors": ">= 0.3.0",
      "eyes": ">= 0.1.6",
      "loggly": ">= 0.1.4",
      "vows": ">= 0.5.2"
    },
    "main": "./lib/winston",
    "scripts": { "test": "vows test/*-test.js --spec" },
    "engines": { "node": ">= 0.3.0" }
}
{
    "name": "winston",
    "description": "A multi-transport async logging library for Node.js",
    "version": "0.2.7",
    "author": "Charlie Robbins <charlie.robbins@gmail.com>",
    "contributors": [
      { "name": "Matthew Bergman", "email": "mzbphoto@gmail.com" }
    ],
    "repository": {
      "type": "git",
      "url": "http://github.com/indexzero/winston.git"
    },
    "keywords": ["logging", "sysadmin", "tools"],
    "dependencies": {
      "colors": ">= 0.x.x",
      "eyes": ">= 0.1.x",
      "loggly": ">= 0.1.x",
      "vows": ">= 0.5.x"
    },
    "main": "./lib/winston",
    "scripts": { "test": "vows test/*-test.js --spec" },
    "engines": { "node": ">= 0.3.0" }
}
Questions

tom@jetpacksfordinosaurs.com
         @sh1mmer

More Related Content

What's hot (20)

KEY
OSCON 2011 - Node.js Tutorial
Tom Croucher
 
PPTX
Java script at backend nodejs
Amit Thakkar
 
PPT
RESTful API In Node Js using Express
Jeetendra singh
 
PPTX
Introduction Node.js
Erik van Appeldoorn
 
PDF
NodeJS
LinkMe Srl
 
PPT
Node js presentation
martincabrera
 
PPT
Building your first Node app with Connect & Express
Christian Joudrey
 
PDF
NodeJS for Beginner
Apaichon Punopas
 
PDF
Node.js - A Quick Tour
Felix Geisendörfer
 
PDF
Node.js Explained
Jeff Kunkle
 
PDF
Non-blocking I/O, Event loops and node.js
Marcus Frödin
 
PDF
Original slides from Ryan Dahl's NodeJs intro talk
Aarti Parikh
 
PDF
Nodejs in Production
William Bruno Moraes
 
PDF
All aboard the NodeJS Express
David Boyer
 
PPT
Nodejs Event Driven Concurrency for Web Applications
Ganesh Iyer
 
PDF
Getting started with developing Nodejs
Phil Hawksworth
 
KEY
Building a real life application in node js
fakedarren
 
PPTX
Intro to Node.js (v1)
Chris Cowan
 
PDF
Node Architecture and Getting Started with Express
jguerrero999
 
KEY
Introduction to node.js
jacekbecela
 
OSCON 2011 - Node.js Tutorial
Tom Croucher
 
Java script at backend nodejs
Amit Thakkar
 
RESTful API In Node Js using Express
Jeetendra singh
 
Introduction Node.js
Erik van Appeldoorn
 
NodeJS
LinkMe Srl
 
Node js presentation
martincabrera
 
Building your first Node app with Connect & Express
Christian Joudrey
 
NodeJS for Beginner
Apaichon Punopas
 
Node.js - A Quick Tour
Felix Geisendörfer
 
Node.js Explained
Jeff Kunkle
 
Non-blocking I/O, Event loops and node.js
Marcus Frödin
 
Original slides from Ryan Dahl's NodeJs intro talk
Aarti Parikh
 
Nodejs in Production
William Bruno Moraes
 
All aboard the NodeJS Express
David Boyer
 
Nodejs Event Driven Concurrency for Web Applications
Ganesh Iyer
 
Getting started with developing Nodejs
Phil Hawksworth
 
Building a real life application in node js
fakedarren
 
Intro to Node.js (v1)
Chris Cowan
 
Node Architecture and Getting Started with Express
jguerrero999
 
Introduction to node.js
jacekbecela
 

Viewers also liked (20)

KEY
Node.js - Best practices
Felix Geisendörfer
 
PDF
Introduction to Nodejs
Gabriele Lana
 
PDF
Modern UI Development With Node.js
Ryan Anklam
 
PPTX
Introduction to Node.js
Vikash Singh
 
PDF
Native Desktop App with Node.js Webkit (HTML, CSS & Javascript)
Eddie Lau
 
PDF
Introduction to Node.js: perspectives from a Drupal dev
mcantelon
 
PPTX
Angular 2.0: Getting ready
Axilis
 
PDF
Grunt JS - Getting Started With Grunt
Douglas Reynolds
 
PPTX
Grunt - The JavaScript Task Runner
Mohammed Arif
 
PPTX
Node.js Patterns for Discerning Developers
cacois
 
PDF
(C)NodeJS
Jackson Tian
 
KEY
Node.js ― Hello, world! の1歩先へ。
Tatsuya Tobioka
 
PDF
Codemotion rome 2015 bluemix lab tutorial -- Codemotion Rome 2015
Codemotion
 
PDF
Luciano Fiandesio - Docker 101 | Codemotion Milan 2015
Codemotion
 
ODP
Scaling and securing node.js apps
Maciej Lasyk
 
PDF
Building web apps with node.js, socket.io, knockout.js and zombie.js - Codemo...
Ivan Loire
 
PDF
An introduction to workflow-based programming with Node-RED
Boris Adryan
 
ODP
Node.js security
Maciej Lasyk
 
PDF
Flow Base Programming with Node-RED and Functional Reactive Programming with ...
Sven Beauprez
 
PDF
Come rendere il proprio prodotto una bomba creandogli una intera community in...
Codemotion
 
Node.js - Best practices
Felix Geisendörfer
 
Introduction to Nodejs
Gabriele Lana
 
Modern UI Development With Node.js
Ryan Anklam
 
Introduction to Node.js
Vikash Singh
 
Native Desktop App with Node.js Webkit (HTML, CSS & Javascript)
Eddie Lau
 
Introduction to Node.js: perspectives from a Drupal dev
mcantelon
 
Angular 2.0: Getting ready
Axilis
 
Grunt JS - Getting Started With Grunt
Douglas Reynolds
 
Grunt - The JavaScript Task Runner
Mohammed Arif
 
Node.js Patterns for Discerning Developers
cacois
 
(C)NodeJS
Jackson Tian
 
Node.js ― Hello, world! の1歩先へ。
Tatsuya Tobioka
 
Codemotion rome 2015 bluemix lab tutorial -- Codemotion Rome 2015
Codemotion
 
Luciano Fiandesio - Docker 101 | Codemotion Milan 2015
Codemotion
 
Scaling and securing node.js apps
Maciej Lasyk
 
Building web apps with node.js, socket.io, knockout.js and zombie.js - Codemo...
Ivan Loire
 
An introduction to workflow-based programming with Node-RED
Boris Adryan
 
Node.js security
Maciej Lasyk
 
Flow Base Programming with Node-RED and Functional Reactive Programming with ...
Sven Beauprez
 
Come rendere il proprio prodotto una bomba creandogli una intera community in...
Codemotion
 
Ad

Similar to Writing robust Node.js applications (20)

PPTX
Building and Scaling Node.js Applications
Ohad Kravchick
 
PDF
Node.js - async for the rest of us.
Mike Brevoort
 
PDF
Nodejs - A quick tour (v6)
Felix Geisendörfer
 
KEY
Practical Use of MongoDB for Node.js
async_io
 
PDF
Introduction to Node.js
Somkiat Puisungnoen
 
KEY
Playing With Fire - An Introduction to Node.js
Mike Hagedorn
 
KEY
Node.js - The New, New Hotness
Daniel Shaw
 
PPTX
Nodejs
Vinod Kumar Marupu
 
KEY
A language for the Internet: Why JavaScript and Node.js is right for Internet...
Tom Croucher
 
ODP
Introduce about Nodejs - duyetdev.com
Van-Duyet Le
 
PDF
Nodejs - A quick tour (v5)
Felix Geisendörfer
 
PDF
Developing realtime apps with Drupal and NodeJS
drupalcampest
 
KEY
A language for the Internet: Why JavaScript and Node.js is right for Internet...
Tom Croucher
 
PPTX
An overview of node.js
valuebound
 
PDF
soft-shake.ch - Hands on Node.js
soft-shake.ch
 
PDF
Introduction to Node.js: What, why and how?
Christian Joudrey
 
KEY
Node.js - A practical introduction (v2)
Felix Geisendörfer
 
PPTX
A slightly advanced introduction to node.js
Sudar Muthu
 
PPTX
Scalable network applications, event-driven - Node JS
Cosmin Mereuta
 
PDF
JavaScript is the new black - Why Node.js is going to rock your world - Web 2...
Tom Croucher
 
Building and Scaling Node.js Applications
Ohad Kravchick
 
Node.js - async for the rest of us.
Mike Brevoort
 
Nodejs - A quick tour (v6)
Felix Geisendörfer
 
Practical Use of MongoDB for Node.js
async_io
 
Introduction to Node.js
Somkiat Puisungnoen
 
Playing With Fire - An Introduction to Node.js
Mike Hagedorn
 
Node.js - The New, New Hotness
Daniel Shaw
 
A language for the Internet: Why JavaScript and Node.js is right for Internet...
Tom Croucher
 
Introduce about Nodejs - duyetdev.com
Van-Duyet Le
 
Nodejs - A quick tour (v5)
Felix Geisendörfer
 
Developing realtime apps with Drupal and NodeJS
drupalcampest
 
A language for the Internet: Why JavaScript and Node.js is right for Internet...
Tom Croucher
 
An overview of node.js
valuebound
 
soft-shake.ch - Hands on Node.js
soft-shake.ch
 
Introduction to Node.js: What, why and how?
Christian Joudrey
 
Node.js - A practical introduction (v2)
Felix Geisendörfer
 
A slightly advanced introduction to node.js
Sudar Muthu
 
Scalable network applications, event-driven - Node JS
Cosmin Mereuta
 
JavaScript is the new black - Why Node.js is going to rock your world - Web 2...
Tom Croucher
 
Ad

More from Tom Croucher (20)

PDF
Using Node.js to Build Great Streaming Services - HTML5 Dev Conf
Tom Croucher
 
KEY
Streams are Awesome - (Node.js) TimesOpen Sep 2012
Tom Croucher
 
KEY
Using Node.js to improve the performance of Mobile apps and Mobile web
Tom Croucher
 
KEY
Creating the Internet of Things with JavaScript - Fluent Conf
Tom Croucher
 
KEY
Using Node.js to make HTML5 work for everyone
Tom Croucher
 
PDF
Lessons from a coding veteran - Web Directions @Media
Tom Croucher
 
KEY
Multi-tiered Node Architectures - JSConf 2011
Tom Croucher
 
PDF
How to stop writing spaghetti code
Tom Croucher
 
PDF
Doing Horrible Things with DNS - Web Directions South
Tom Croucher
 
PDF
Doing Horrible Things to DNS in the Name of Science - SF Performance Meetup
Tom Croucher
 
KEY
How to stop writing spaghetti code - JSConf.eu 2010
Tom Croucher
 
PDF
Sf perf
Tom Croucher
 
PDF
Server Side JavaScript - You ain't seen nothing yet
Tom Croucher
 
PDF
JavaScript Everywhere! Creating a 100% JavaScript web stack
Tom Croucher
 
PDF
Mobile Data: How to avoid the latency trap - SWDC 2010
Tom Croucher
 
KEY
Let's run JavaScript Everywhere
Tom Croucher
 
KEY
Pirate yql
Tom Croucher
 
KEY
YQL Tutorial
Tom Croucher
 
PPT
How to avoid the latency trap and lessons about software design
Tom Croucher
 
PPT
Unicorns Metrics and Hotsauce - Lessons about Evangelism from the Yahoo! Deve...
Tom Croucher
 
Using Node.js to Build Great Streaming Services - HTML5 Dev Conf
Tom Croucher
 
Streams are Awesome - (Node.js) TimesOpen Sep 2012
Tom Croucher
 
Using Node.js to improve the performance of Mobile apps and Mobile web
Tom Croucher
 
Creating the Internet of Things with JavaScript - Fluent Conf
Tom Croucher
 
Using Node.js to make HTML5 work for everyone
Tom Croucher
 
Lessons from a coding veteran - Web Directions @Media
Tom Croucher
 
Multi-tiered Node Architectures - JSConf 2011
Tom Croucher
 
How to stop writing spaghetti code
Tom Croucher
 
Doing Horrible Things with DNS - Web Directions South
Tom Croucher
 
Doing Horrible Things to DNS in the Name of Science - SF Performance Meetup
Tom Croucher
 
How to stop writing spaghetti code - JSConf.eu 2010
Tom Croucher
 
Sf perf
Tom Croucher
 
Server Side JavaScript - You ain't seen nothing yet
Tom Croucher
 
JavaScript Everywhere! Creating a 100% JavaScript web stack
Tom Croucher
 
Mobile Data: How to avoid the latency trap - SWDC 2010
Tom Croucher
 
Let's run JavaScript Everywhere
Tom Croucher
 
Pirate yql
Tom Croucher
 
YQL Tutorial
Tom Croucher
 
How to avoid the latency trap and lessons about software design
Tom Croucher
 
Unicorns Metrics and Hotsauce - Lessons about Evangelism from the Yahoo! Deve...
Tom Croucher
 

Recently uploaded (20)

PDF
Bitcoin for Millennials podcast with Bram, Power Laws of Bitcoin
Stephen Perrenod
 
PDF
IoT-Powered Industrial Transformation – Smart Manufacturing to Connected Heal...
Rejig Digital
 
DOCX
Cryptography Quiz: test your knowledge of this important security concept.
Rajni Bhardwaj Grover
 
PPTX
The Project Compass - GDG on Campus MSIT
dscmsitkol
 
PPTX
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
PDF
Transforming Utility Networks: Large-scale Data Migrations with FME
Safe Software
 
PDF
CIFDAQ Market Insights for July 7th 2025
CIFDAQ
 
PPTX
COMPARISON OF RASTER ANALYSIS TOOLS OF QGIS AND ARCGIS
Sharanya Sarkar
 
PDF
[Newgen] NewgenONE Marvin Brochure 1.pdf
darshakparmar
 
PDF
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
PPTX
AUTOMATION AND ROBOTICS IN PHARMA INDUSTRY.pptx
sameeraaabegumm
 
PDF
Mastering Financial Management in Direct Selling
Epixel MLM Software
 
DOCX
Python coding for beginners !! Start now!#
Rajni Bhardwaj Grover
 
PDF
Agentic AI lifecycle for Enterprise Hyper-Automation
Debmalya Biswas
 
PDF
"AI Transformation: Directions and Challenges", Pavlo Shaternik
Fwdays
 
PDF
Staying Human in a Machine- Accelerated World
Catalin Jora
 
PDF
Reverse Engineering of Security Products: Developing an Advanced Microsoft De...
nwbxhhcyjv
 
PDF
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
PDF
What Makes Contify’s News API Stand Out: Key Features at a Glance
Contify
 
PPTX
WooCommerce Workshop: Bring Your Laptop
Laura Hartwig
 
Bitcoin for Millennials podcast with Bram, Power Laws of Bitcoin
Stephen Perrenod
 
IoT-Powered Industrial Transformation – Smart Manufacturing to Connected Heal...
Rejig Digital
 
Cryptography Quiz: test your knowledge of this important security concept.
Rajni Bhardwaj Grover
 
The Project Compass - GDG on Campus MSIT
dscmsitkol
 
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
Transforming Utility Networks: Large-scale Data Migrations with FME
Safe Software
 
CIFDAQ Market Insights for July 7th 2025
CIFDAQ
 
COMPARISON OF RASTER ANALYSIS TOOLS OF QGIS AND ARCGIS
Sharanya Sarkar
 
[Newgen] NewgenONE Marvin Brochure 1.pdf
darshakparmar
 
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
AUTOMATION AND ROBOTICS IN PHARMA INDUSTRY.pptx
sameeraaabegumm
 
Mastering Financial Management in Direct Selling
Epixel MLM Software
 
Python coding for beginners !! Start now!#
Rajni Bhardwaj Grover
 
Agentic AI lifecycle for Enterprise Hyper-Automation
Debmalya Biswas
 
"AI Transformation: Directions and Challenges", Pavlo Shaternik
Fwdays
 
Staying Human in a Machine- Accelerated World
Catalin Jora
 
Reverse Engineering of Security Products: Developing an Advanced Microsoft De...
nwbxhhcyjv
 
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
What Makes Contify’s News API Stand Out: Key Features at a Glance
Contify
 
WooCommerce Workshop: Bring Your Laptop
Laura Hartwig
 

Writing robust Node.js applications

  • 1. Node.js Tutorial Tom Hughes-Croucher, Principal Jetpacks For Dinosaurs, LLC [email protected] @sh1mmer
  • 2. Introduction • Tom Hughes-Croucher • Principal at Jetpacks for Dinosaurs • Node.js and High-performance web site consulting and training • Walmart, MySpace, Joyent,Yahoo!, NASA, Tesco, etc • Node.js contributor • Lead author of "Node: Up and Running"
  • 3. Scalable Server-Side Code with JavaScript Node Up and Running Tom Hughes-Croucher http://ofps.oreilly.com/titles/9781449398583/ http://shop.oreilly.com/product/0636920015956.do
  • 4. Training Online In person
  • 8. Enki:~/Code/node-examples $ node --debug helloworld.js debugger listening on port 5858 Server running at http://127.0.0.1:8124/
  • 9. enki:~ sh1mmer$ ps -A | grep node 19093 ttys001 0:00.39 node index.js 19273 ttys002 0:00.00 grep node enki:~ sh1mmer$ kill -s USR1 19093
  • 10. enki:~ sh1mmer$ node index.js Hit SIGUSR1 - starting debugger agent. debugger listening on port 5858
  • 11. Enki:~ $ sudo npm install -g node-inspector [email protected] ./node_modules/node-inspector ├── [email protected] └── [email protected] Enki:~ $ node-inspector visit http://0.0.0.0:8080/debug?port=5858 to start debugging
  • 13. Exercises • Modify a basic HTTP server to return the text "I'm learning Node" • Change the HTTP response to HTML and return your text in an HTML page • Return the User-Agent string from the browser as part of your HTML page
  • 15. Sinatra Style MVC framework
  • 16. var app = require('express').createServer(); app.get('/', function(req, res){ res.send('hello world'); }); app.listen(3000);
  • 19. app.use(express.bodyParser()); app.use(express.cookieParser()); app.post('/', function(req, res){ // Perhaps we posted several items with a form // (use the bodyParser() middleware for this) var items = req.body.items; console.log(items); res.send('logging'); });
  • 21. var express = require("express"); app.configure(function () { var public = __dirname + "/../public/"; public = require("path").normalize(public); app.set("views", __dirname + "/views"); app.set("view engine", "jade"); }); app.get("/", function (req, res) { res.render("index", { locals : { h1: 'Router Stats', scripts : [ "/public/smoothie.js", "/public/raphael.js", "/public/base.js", "/public/gfx.js", "/public/explore.js", "/public/app.js" ] } } });
  • 22. Exercise • Create an Express server • Make routes for ‘/’ & ‘/products’ • Serve two different pages based on value of the query string parameter "page" • Create a redirect from /old to /new • Set a cookie on the client
  • 23. Building a chat server
  • 26. Client Front-end Database User Node DB
  • 28. Heavy Front-end Client Processor Database Farm Work User Node Node Node Node DB Node Node Node Node
  • 29. Don’t we want to move “heavy work”?
  • 30. Client → Server Server → DB Computation Computation
  • 32. Front-end Client Database Farm DB User Node Node Node Node Big Slow Logging farm Disk Node Node Disk
  • 33. Move work which isn’t user-facing out of main event loop
  • 34. Ensure consistency of Node processes
  • 37. var cluster = require('cluster'); var http = require('http'); var numCPUs = require('os').cpus().length; if (cluster.isMaster) { // Fork workers. for (var i = 0; i < numCPUs; i++) { cluster.fork(); } cluster.on('death', function(worker) { console.log('worker ' + worker.pid + ' died'); }); } else { // Worker processes have a http server. http.Server(function(req, res) { res.writeHead(200); res.end("hello worldn"); }).listen(8000); }
  • 38. Use load balancers to distribute across servers
  • 39. node-proxy squid varnish haproxy
  • 40. Unbundle SSL stud, stunnel, etc http://vincent.bernat.im/en/blog/2011- ssl-benchmark.html#conclusion
  • 42. Disclaimer: Sharding is hard See CAP theorem
  • 45. client and server with the shared API
  • 46. var app = require('express').createServer(), io = require('socket.io').listen(app); app.listen(80); app.get('/', function (req, res) {   res.sendfile(__dirname + '/index.html'); }); io.sockets.on('connection', function (socket) {   socket.emit('news', { hello: 'world' });   socket.on('my other event', function (data) {     console.log(data);   }); });
  • 47. <!DOCTYPE html> <html> <body> <script src="/socket.io/socket.io.js"></script> <script> var socket = io.connect('http://localhost'); socket.connect(); socket.on('connect', function(){ console.log('connect') }) socket.on('message', function(){ console.log('message') }) socket.on('disconnect', function(){ console.log('disconnect'); }) </script> </body> </html>
  • 48. Transports • WebSocket • Adobe® Flash® Socket • AJAX long polling • AJAX multipart streaming • Forever iframe • JSONP Polling
  • 49. options = { transports: ['websocket'], log: util.log } io.listen(server, options)
  • 50. // note, io.listen() will create a http server for you var io = require('socket.io').listen(80); io.sockets.on('connection', function (socket) {   io.sockets.emit('this', { will: 'be received by everyone'});   socket.on('private message', function (from, msg) {     console.log('I received a private message by ', from, ' saying ', msg);   });   socket.on('disconnect', function () {     sockets.emit('user disconnected');   }); });
  • 51. Exercises • Create a socket.io connect to an express server • Create a route which loads a page that includes socket.io • Send "hello world" to the client sockets • Make the client respond with "thanks" and disconnect from the server
  • 52. Using Redis with Socket.io
  • 53. Why use Redis? • No shared memory • Cluster on server won’t share client data • Multiple servers can use the same Redis
  • 54. var express = require('express') , app = express.createServer(); var sio = require('socket.io') , RedisStore = sio.RedisStore , io = sio.listen(app); app.listen(8080); app.get('/', function(req,res) { res.sendfile(__dirname + '/index.html'); }); io.sockets.on('connection', function (socket) { socket.on('chat', function (data) { console.log(data); socket.broadcast.emit('chat', data); }) });
  • 55. var cluster = require('cluster'); var http = require('http'); var numCPUs = require('os').cpus().length; if (cluster.isMaster) { // Fork workers. for (var i = 0; i < numCPUs; i++) { cluster.fork(); } } else { var express = require('express') , app = express.createServer(); var sio = require('socket.io') , RedisStore = sio.RedisStore , io = sio.listen(app); app.listen(8080); app.get('/', function(req,res) { res.sendfile(__dirname + '/index.html'); }); // Somehow pass this information to the workers io.set('store', new RedisStore); // Do the work here io.sockets.on('connection', function (socket) { socket.on('chat', function (data) { console.log(data); socket.broadcast.emit('chat', data); }) }); }
  • 58. var http = require('http'); var req = http.request({ host: 'www.google.com', path: '/', port: 80, method: 'POST' }, function (response) { // Do stuff with the response here });
  • 59. node.js:134 throw e; // process.nextTick error, or 'error' event on first tick ^ Error: Uncaught, unspecified 'error' event. at EventEmitter.emit (events.js:47:15) at Object.<anonymous> (/ Users/you/y-u-no-listen-for-errors.js:5:9) at Module._compile (module.js:404:26) at Object..js (module.js:410:10) at Module.load (module.js:336:31) at Function._load (module.js:297:12) at Array.<anonymous> (module.js:423:10) at EventEmitter._tickCallback (node.js:126:26)
  • 60. var http = require('http'); try { var req = http.request({ host: 'www.google.com', path: '/', port: 80, method: 'POST' }, function (response) { // Do stuff with the response here }); } catch(e) {
  • 61. var http = require('http'); var req = http.request({ host: 'www.google.com', path: '/', port: 80, method: 'POST' }, function (response) { // Do stuff with the response here }); req.on('error', function (err) { //safely handle this if possible });
  • 62. // Suppress errors process.on('uncaughtException', function (err) { // Log it! console.dir(err); });
  • 64. (node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit. Trace: at Pool.<anonymous> (events.js:101:17) at Object.proxyRequest (~/http-proxy/lib/node-http-proxy.js:185:7) at Server.<anonymous> (/Users/some-user/myapp.js:14:9) at Server.emit (events.js:45:17) at HTTPParser.onIncoming (http.js:1078:12) at HTTPParser.onHeadersComplete (http.js:87:31) at Socket.ondata (http.js:977:22) at Socket._onReadable (net.js:654:27) at IOWatcher.onReadable [as callback] (net.js:156:10)
  • 65. var events = require('events'); function doSomethingThenTellMe () { var emitter = new events.EventEmitter(); setTimeout(function () { emitter.emit('done'); }, 2000); return emitter; } var doingIt = doSomethingThenTellMe(); doingIt.on('done', function () { console.log("Ok, it's done"); }); // Why are you using `.on()`? // You only expect this event to fire once.
  • 67. var events = require('events'); function doSomethingThenTellMe () { var emitter = new events.EventEmitter(); setTimeout(function () { emitter.emit('done'); }, 2000); return emitter; } var doingIt = doSomethingThenTellMe(); doingIt.once('done', function () { console.log("Ok, it's done"); });
  • 70. description "node.js server" author "croucher`" start on startup stop on shutdown script # We found $HOME is needed. Without it, we ran into problems export HOME="/root" exec /usr/local/bin/node /var/noderoot/index.js 2>&1 >> / var/log/node.log end script
  • 72. $ cd /path/to/your/app $ forever start bin/yourapp info: Running action: start info: Forever processing file: examples/server.js $ forever list info: Running action: list info: Forever processes running [0] bin/yourapp [77041, 77040] /Users/You/.forever 20dL.log 0:0:0:1.788
  • 74. Enki:~/Code/node-dnsserve(master) $ ls LICENSE README dnsserver.js package.json Enki:~/Code/node-dnsserve(master) $
  • 75. { "name": "dns-server", "description": "DNS server for Node", "version": "0.0.1a", "author": "Tom Hughes-Croucher <[email protected]>", "main" : "dnsserver" }
  • 76. Enki:~/Code/node-dnsserve(master) $ sudo npm install . -g [email protected] /usr/local/lib/node_modules/dns- server Enki:~/Code/node-dnsserve(master) $
  • 77. Enki:~/Code/node-dnsserve(master) $ sudo npm link /usr/local/lib/node_modules/dns-server -> /Users/sh1mmer/Code/ node-dnsserve Enki:~/Code/node-dnsserve(master) $ npm ls -g /usr/local/lib ├── [email protected] -> /Users/sh1mmer/Code/node-dnsserve └─┬ [email protected] ├── [email protected] ├── [email protected] ├── [email protected] └── [email protected] Enki:~/Code/node-dnsserve(master) $
  • 78. Enki:~/Code/node-dnsserve(master) $ npm adduser Username: foobarbaz Password: Email:
  • 79. Enki:~/Code/node-dnsserve(master) $ npm publish npm WARN Sending authorization over insecure channel. Enki:~/Code/node-dnsserve(master) $
  • 80. { "name": "winston", "description": "A multi-transport async logging library for Node.js", "version": "0.2.7", "author": "Charlie Robbins <[email protected]>", "contributors": [ { "name": "Matthew Bergman", "email": "[email protected]" } ], "repository": { "type": "git", "url": "http://github.com/indexzero/winston.git" }, "keywords": ["logging", "sysadmin", "tools"], "dependencies": { "colors": ">= 0.3.0", "eyes": ">= 0.1.6", "loggly": ">= 0.1.4", "vows": ">= 0.5.2" }, "main": "./lib/winston", "scripts": { "test": "vows test/*-test.js --spec" }, "engines": { "node": ">= 0.3.0" } }
  • 81. { "name": "winston", "description": "A multi-transport async logging library for Node.js", "version": "0.2.7", "author": "Charlie Robbins <[email protected]>", "contributors": [ { "name": "Matthew Bergman", "email": "[email protected]" } ], "repository": { "type": "git", "url": "http://github.com/indexzero/winston.git" }, "keywords": ["logging", "sysadmin", "tools"], "dependencies": { "colors": ">= 0.x.x", "eyes": ">= 0.1.x", "loggly": ">= 0.1.x", "vows": ">= 0.5.x" }, "main": "./lib/winston", "scripts": { "test": "vows test/*-test.js --spec" }, "engines": { "node": ">= 0.3.0" } }

Editor's Notes