Building and Scaling Node.js Applications
Upcoming SlideShare
Loading in...5
×
 

Building and Scaling Node.js Applications

on

  • 1,555 views

A introduction to web frameworks built on node. A discussion about scaling up and out your single server.

A introduction to web frameworks built on node. A discussion about scaling up and out your single server.

Statistics

Views

Total Views
1,555
Views on SlideShare
1,555
Embed Views
0

Actions

Likes
3
Downloads
22
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Building and Scaling Node.js Applications Building and Scaling Node.js Applications Presentation Transcript

    • Building and ScalingNode.js Applications Ohad Kravchick 7/5/2012 http://bit.ly/nodeApps
    • When to use Node and when not to• Dont use node to server static files - there are better and easier [to configure] servers than node (NGINX, varnish, HAProxy)• Dont use node for simple CRUD apps - you will have to build it all yourself• You have to build almost everything yourself - great for APIs – Great for iterative development• Use it for real-time – Node is responding to requests super fast
    • What do you need to start• Node (http://nodejs.org/) – brew install node or download via URL• nvm (https://github.com/creationix/nvm/) – nvm install v0.7.1• npm (http://npmjs.org/) – we have our NYT repo• online docs and tutorials, READMEs• your favorite text editor• node whatever.js – node compiles your code before every invocation
    • Simple web servers• http 1 var http = require(http); 2 http.createServer(function (req, res) { 3 res.writeHead(200, {Content-Type: text/plain}); 4 res.end(Hello Worldn); 5 }).listen(1337, "127.0.0.1"); 6 console.log(Server running at http://127.0.0.1:1337/);• express 1 var express = require(express); 2 var app = express.createServer(); 3 app.get(/, function(req, res){ 4 res.send(Hello World); 5 }); 6 app.listen(3000);
    • Simple web servers• Express supports: – HTTPS – Template-based views and partials + caching – Parameterized Routing /users/:user – Session – JSONP, MethodOverride, BodyParser, ENVs – Customizable Middleware
    • Middleware 1 function loadUser(req, res, next) { 2 // You would fetch your user from the db 3 var user = users[req.params.id]; 4 if (user) { 5 req.user = user; 6 next(); 7 } else { 8 next(new Error(Failed to load user + req.params.id)); 9 }10 }1112 app.get(/user/:id, loadUser, function(req, res){13 res.send(Viewing user + req.user.name);14 });
    • Middleware plugins• Uses connect 1 var express = require(express); 2 var app = express.createServer(); 3 4 app.use(express.logger(dev)); 5 app.use(express.bodyParser()); 6 app.use(express.cookieParser()); 7 app.use(express.favicon()); 8 app.use(express.session({ secret: my secret here })); 9 app.use(app.router); 10 app.use(express.static(public)); 11 app.use(express.directory(public)); 12 app.use(express.errorHandler({showStack: true, dumpExceptions: true})); 13 14 app.get(/, function (req, res) { 15 res.send(hello world); 16 }); 17 18 app.listen(3000);
    • Middleware plugins• logger request logger with custom format support• csrf Cross-site request forgery protection• compress Gzip compression middleware• basicAuth basic http authentication• bodyParser extensible request body parser• json application/json parser• urlencoded application/x-www-form-urlencoded parser• multipart multipart/form-data parser• cookieParser cookie parser• session session management support with bundled MemoryStore• cookieSession cookie-based session support• methodOverride faux HTTP method support• responseTime calculates response-time and exposes via X-Response-Time• staticCache memory cache layer for the static() middleware• static streaming static file server supporting Range and more• directory directory listing middleware• vhost virtual host sub-domain mapping middleware• favicon efficient favicon server (with default icon)• limit limit the bytesize of request bodies• query automatic querystring parser, populating req.query• errorHandler flexible error handler
    • Real-time using Node• Socket.IO – WebSockets, Flash, long-polling, iframe forever – Supports IE 5.5+ – Runs cross-domain• Server 1 var io = require(socket.io).listen(80); 2 3 io.sockets.on(connection, function (socket) { 4 socket.emit(news, { hello: world }); 5 socket.on(my other event, function (data) { 6 console.log(data); 7 }); 8 }); 1 <script src="/socket.io/socket.io.js"></script>• Client 2 <script> 3 var socket = io.connect(http://localhost); 4 socket.on(news, function (data) { 5 console.log(data); 6 socket.emit(my other event, { my: data }); 7 }); 8 </script>
    • Simple DBs• mysql 1 var mysql = require(mysql); 2 var connection = mysql.createConnection({host: example.org, user: bob, password: secret}); 3 var state = NY; 4 connection.query(SELECT * FROM users WHERE state = ?, [state], function(err, results) { 5 var index; 6 if (err) throw err; 7 for (index in results) { 8 console.log(Found user + fields[index].username + from + state); 9 } 10 connection.end(function(err) { }); 11 });• mongo 1 var mongodb = require(mongodb); 2 var server = new mongodb.Server("127.0.0.1", 27017, {}); 3 new mongodb.Db(test, server, {}).open(function (error, client) { 4 if (error) throw error; 5 var collection = new mongodb.Collection(client, test_collection); 6 collection.find({}, {limit:10}).toArray(function(err, docs) { 7 console.dir(docs); 8 }); 9 });
    • Debugging• Node --debug whatever.js• node-inspector-------------------------------------------------------------- 8080 ----------------| Node.js server <--> 5858 <--> node-inspector | <-----------------> | web client |-------------------------------------------------------------- ---------------- DebuggerProtocol – Demo• kill -s USR1 <pid>• node --debug-brk much_faster_whatever.js
    • General• Uncaught Exception kills the server – Log errors using process.on(uncaugtException) – deamontools supervise, monit• Logging – Winston (https://github.com/flatiron/winston/)• Use ab for testing – sudo sysctl -w net.inet.tcp.msl=300 – Demo (ex3)
    • Concurrency model• Non-blocking IO – Uses epoll, kqueue, select• Single-threaded event-loop (uses libev and libeio) – As oppose to thread per request – less context-switching, less CPU usage, less memory• The event loop is not intended to make computationally intensive tasks responsive, it’s meant to cut the resource waste related to waiting for I/O by Mikito Takada• Long synchronous code WILL BLOCK ALL OTHERS – Extract heavy code to its own service or process – Use WebWorkers to spawn a “process”
    • Node vs. Apache
    • Maximizing the server• Single thread running on a single CPU• Use cluster to take all CPUs 1 var cluster = require(cluster); 2 var http = require(http); 3 var numCPUs = require(os).cpus().length; 4 5 if (cluster.isMaster) { 6 // Fork workers. 7 for (var i = 0; i < numCPUs; i++) { 8 cluster.fork(); 9 } 10 } else { 11 // Workers can share any TCP connection 12 // In this case its a HTTP server 13 http.createServer(function(req, res) { 14 res.writeHead(200); 15 res.end("hello worldn"); 16 }).listen(8000); 17 }
    • Sharing between instances• As you spawn multiple instances, you need to share data (=memory)• You can use IPC• You can use DB• Or, you can use in-memory cache – memcached • Strings, integers, anything else is serialized • Set, get, delete, replace, append, prepend • Expiry – redis
    • redis• Key-value storage that atomically supports: – Strings: get, set, strlen, append, getrange, setrange – Bit strings: setbit, getbit, bitcount, bitop – Integers and floats: incr, decr, incrby, decrby, – Lists: llen, lpop, lpush, lrem, linsert, lindex, lset, lrange, – Sets: sadd, sismember, srem, spop, smembers, scard • Inter-sets: sinter, sinterstore, sdiff, sdiffstore, sunion, sunionstore – Sorted sets: zscore, zadd, zrem, zrank, zrange, zrangebyscore – Hashes: hset, hget, hmset, hmget, hdel, hexists, hkeys, hvals, hgetall, hincrby• Native to developers• Makes the developer think about the implications of large-scale• Demo
    • redis 1 var redis = require("redis"), 2 client = redis.createClient(); 3 4 client.set("string key", "string val", redis.print); 5 client.hset("hash key", "hashtest 1", "some value", redis.print); 6 client.hset(["hash key", "hashtest 2", "some other value"], redis.print); 7 client.hkeys("hash key", function (err, replies) { 8 console.log(replies.length + " replies:"); 9 replies.forEach(function (reply, i) {10 console.log(" " + i + ": " + reply);11 });12 client.quit();13 });
    • redis• Blazingly fast, in-memory cache – Size limited to memory – Good for ephemeral data (cache, session), for syncing servers• Can be saved to disk, mostly for faster start up• Use async/Q for handling multiple requests• Supports expiry, pub-sub, transactions, server- side LUA scripts• connect-redis for automatic session sync
    • FinThank YouQuestions?