Building and Scaling Node.js Applications

  • 1,207 views
Uploaded on

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.

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
1,207
On Slideshare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
24
Comments
0
Likes
4

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. Building and ScalingNode.js Applications Ohad Kravchick 7/5/2012 http://bit.ly/nodeApps
  • 2. 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
  • 3. 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
  • 4. 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);
  • 5. Simple web servers• Express supports: – HTTPS – Template-based views and partials + caching – Parameterized Routing /users/:user – Session – JSONP, MethodOverride, BodyParser, ENVs – Customizable Middleware
  • 6. 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 });
  • 7. 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);
  • 8. 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
  • 9. 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>
  • 10. 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 });
  • 11. 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
  • 12. 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)
  • 13. 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”
  • 14. Node vs. Apache
  • 15. 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 }
  • 16. 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
  • 17. 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
  • 18. 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 });
  • 19. 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
  • 20. FinThank YouQuestions?