how not to write in node.js
DESCRIPTION
Node.js facts and myths, revealed architecture and scaling eventapproach.TRANSCRIPT
![Page 3: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/3.jpg)
About me
getfokus.com useselly.com
![Page 4: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/4.jpg)
How software lives in hardware?
•Operating systems are process based• Each process has assigned processor,
registers, memory
http://www.cs.uic.edu/~jbell/CourseNotes/OperatingSystems/4_Threads.html
![Page 5: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/5.jpg)
How software lives in hardware?
•Process paralelism using threads (thread pools)• Switching processor over
processes/threads causes context switching
http://www.cs.uic.edu/~jbell/CourseNotes/OperatingSystems/4_Threads.html
![Page 6: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/6.jpg)
How software lives in hardware?
1. Avoid context switching = wasting time
![Page 7: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/7.jpg)
How software lives in hardware?
In trivial, sequential approach
• Each operation is executed sequentially:
O(t) > O(t+1)
• if O(t) stucks, O(t+1) waits…
http://cs.brown.edu/courses/cs196-5/f12/handouts/async.pdf
![Page 8: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/8.jpg)
How software lives in hardware?
This is cool, software flow is predictibleBut not in high throughput I/O
![Page 9: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/9.jpg)
http://blog.mixu.net/2011/02/01/understanding-the-node-js-event-loop/
![Page 10: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/10.jpg)
How software lives in hardware?
High throughput I/O doesn’t mean:
•Memory operations• Fast single-thread computing
![Page 11: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/11.jpg)
How software lives in hardware?
High throughput I/O means:
•HTTP requests•Database connections•Queue system dispatching•HDD operations
![Page 12: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/12.jpg)
Single-threaded, event loop model
Problem:
Imagine a man, who has a task:1. Walk around2. When bucket is full of water,
just pour another bucket3. Go to next bucket
http://www.nightmare.com/medusa/async_sockets.html
![Page 13: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/13.jpg)
Single-threaded, event loop model
What is nonblocking I/O?
Imagine a man, who has a task:1. Walk around2. When bucket is full of water,
just pour another bucket3. Go to next bucket
http://www.nightmare.com/medusa/async_sockets.html
![Page 14: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/14.jpg)
Single-threaded, event loop model
Problem:
Imagine a man, who has a task:1. Walk around2. When bucket is full of water,
just pour another bucket,if not… continue
3. Go to next buckethttp://www.nightmare.com/medusa/async_sockets.html
![Page 15: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/15.jpg)
Single-threaded, event loop model
How it is realised in low-level operating system?
•select()•/dev/pool descriptors•kqueue•pool•epool
![Page 16: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/16.jpg)
Single-threaded, event loop model
How it is realised in low-level operating system?
#include <sys/types.h>
#include <sys/socket.h>
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, const struct timeval *timeout);
![Page 17: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/17.jpg)
Single-threaded, event loop model
2. Avoid I/O blocking
![Page 18: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/18.jpg)
Node.js architecture
http://nodejs.org/logos/
![Page 19: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/19.jpg)
Node.js architecture
Node std library
node bindings (socket, http, …)
Event loop(libev)Google V8 Thread Pool
(libeio)
JavaScript
C/C++
![Page 20: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/20.jpg)
Node.js architecture
• Single-threadedno context switching
• Event loopno waits
• Javascript (Google V8)• ECMA-262 support
![Page 21: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/21.jpg)
Node.js architecture
http://www.tocadoelfo.com.br/2012/04/por-que-estou-aprendendo-nodejs.html
![Page 22: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/22.jpg)
ECMA-262 support
var arr = []
for(var i = 0, j = arr.length; i < j; ++i) {
var row = arr[i] // ufff…
}
var arr = []
arr.forEach(function(row) {
})
![Page 23: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/23.jpg)
„Parallelism”is a myth
![Page 24: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/24.jpg)
Node.js architecture
• Everything runs in parallel except your code
•When currently code is running,(not waiting for I/O descriptors)whole event loop is blocked
![Page 25: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/25.jpg)
„Parallelism”
• Let’s compute Fibonacci
function fib(n) {
return (n < 2) ? 1 : (fib(n-2)+fib(n-1));
}
This will simply block main (single) thread.
![Page 26: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/26.jpg)
„Parallelism”
•How about process.nextTick() ?
![Page 27: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/27.jpg)
„Parallelism”
•… but next iteration over function is delayed into next event loop iteration• That means each descriptor is checked before
computation.
![Page 28: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/28.jpg)
„Parallelism”
process.nextTick()to speed up computations is a myth
Node.js is not good solution to make single-process computations
![Page 29: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/29.jpg)
„Parallelism”
You can still fork another process
• threads_a_gogopool = require('threads_a_gogo').createPool(5)pool.any.eval('myFunction( ... )')
• Fork processvar fork = require('child_process').fork;var child = fork(__filename, [ 'arg1' ]);
![Page 30: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/30.jpg)
Callback hellis a mythwe can deal with it
![Page 31: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/31.jpg)
Callback hell
• Language construction – callback function•When operation is ready, call function passed as an
argument
someOperation(arg1, arg2, function() {
console.log('cool!');
})
![Page 32: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/32.jpg)
Callback hell
•When many operations are ready…
![Page 33: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/33.jpg)
var amqp = require('amqp');var connection = amqp.createConnection();
connection.on('ready', function() { connection.exchange("ex1", function(exchange) {
connection.queue('queue1', function(q) {q.bind(exchange, 'r1');
q.subscribe(function(json, headers, info, m) {console.log("msg: " +
JSON.stringify(json));});
});});
}); This is callback hell
![Page 34: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/34.jpg)
Callback hell
Deal with callback hell in many ways:
•Define callbacks as local variables•Use async module•Use PROMISE design pattern
![Page 35: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/35.jpg)
Callback hell
Define callbacks as local variables, like this:
var whenSthElseDone = function() {
// done...
}
var whenSthDone = function() {
operation(whenSthElseDone)
}
operation(whenSthDone)
![Page 36: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/36.jpg)
Callback hell
Use async module:
async.series([
function(callback) {
operation1(callback)
},
function(callback) {
operationBloking()
return callback()
}
],
function() {
// all done...
})
![Page 37: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/37.jpg)
Callback hell
PROMISE design pattern:
var Promise = require('promise');
var promise = new Promise(function (resolve, reject) {
operation1(function (err, res) {
if (err) reject(err);
else resolve(res);
});
});
![Page 38: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/38.jpg)
Callback hell
PROMISE design pattern:
promise.then(function(res) {
// done...
})
![Page 39: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/39.jpg)
Events (event bus)Triggering event does’t block whole event loop is a myth
![Page 40: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/40.jpg)
Eventsvar eventbus = require('events').EventEmitter
myFunction() {
operation1(function() {
eventbus.emit('myFunctionIsDone', {
result: 1234
})
}
}
![Page 41: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/41.jpg)
Eventsvar eventbus = require('events').EventEmitter
eventbus.on('myFunctionIsDone', function(data) {
console.log('cool! ')
})
Trigger waits until all listeners are done. So do not make long-running operations in event subscribers.
![Page 42: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/42.jpg)
Scaling EventEmitterTriggering events in event bus via EventEmitter does not scale!
![Page 43: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/43.jpg)
Scaling EventEmitter
• Triggering events in event bus via EventEmitterdoes not scale!• Events are visible locally in main thread
![Page 44: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/44.jpg)
Scaling EventEmitter
We need to use external queue system
to touch distributed nodes(3rd party for our application written in Node.js)
![Page 45: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/45.jpg)
Scaling EventEmitter
RabbitMQ is cool because:
•based on AMQP protocol(so integrates 3rd party software – an abstraction)•Queue async system•Publish-subscribe async model•Request-Response model
![Page 46: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/46.jpg)
Scaling EventEmitter
Emit:
1. Trigger event in your application via EventEmitter2. Catch it locally3. Re-trigger via RabbitMQ
![Page 47: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/47.jpg)
Scaling EventEmitter
Receive:
1. Subscribe on RabbitMQ exchange2. Trigger local event in application
![Page 48: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/48.jpg)
Scaling EventEmitter
This is only to separate responsibilitiesand good design of application
![Page 49: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/49.jpg)
Not only Node.jsNode.js is not a religion! It is only an implementation of async programming model
![Page 50: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/50.jpg)
Not only Node.js
Node.js is not a religion. Last time - hype.It only utilizes event-loop model, known from a long time…
• GUI frameworks• Tornado – Python• Linkedin parseq – Java• Async and Await – C#• Cramp – Ruby• reactphp – PHP, ehhh… WAT?!
![Page 51: How NOT to write in Node.js](https://reader036.vdocuments.us/reader036/viewer/2022062418/554a0815b4c905557a8b574e/html5/thumbnails/51.jpg)
Event loop, single-threaded model is not solution for all your problems…Especially for long-running computings in single thread.It’s good for high throughput I/O.