Node.js for Rubists

Post on 15-May-2015

865 views 2 download

Tags:

transcript

Speaker: Sagiv Ofek

why?

Node's goal is to provide an easy way to build scalable network programs. --Ryan Dahl

how?

Keep slow operations from blocking other operations.

Traditional I/O

var pickUpLine = file.read('file.txt');tryYourBestWithThat(pickUpLine);

can you tell wat's wrong here?

//zzzzzzz

ruby blocking sample

parties = Party.where(:line => ['Free Drinks', 'Supermodels','Koby Peretz']).all

parties.go

Modern Computer Latency

● L1: 3 cycles● L2: 14 cycles● RAM: 250 cycles—————————

● DISK: 41,000,000 cycles● NETWORK: 240,000,000 cycles

Blocking

Non - Blocking

Modern Computer Latency

● reaching RAM is like going from here to the Red Light District.

● Accessing the network is like going to the moon.

so, what shall we do?

we have processes!

time to use our gizillions cores!● does not scale well, hundreds of connections

means hundreds of processes.● Spinning up a new process takes

significantly more memory, a megabyte on some platforms.

we have threads!

● Coarse-grained locks – more blocking● Fine-grained locks – more complexity● Risk for deadlocks● Hard to reason about and therefore to get

right● Context switching overhead

we have libraries!

There are asynchronous I/O libraries for Ruby as well, like EventMachine or Cool.IO for example. And of course there's Twisted for Python, Async, Event and EV for Perl, Rx for .NET, Async Computation Expressions for F# and libaio, libevent and libev for C. (BTW: Node.js is actually implemented using libev)

we have libraries!

When you are within the event loop, you cannot make any blocking calls. However, pretty much the entire Ruby IO, File and Dir classes, as well as the networking and database libraries and so on are all mostly synchronous and blocking. (And the same is true for pretty much all of the other languages as well.) So, when you write code in EventMachine or Cool.IO or Twisted, you have to be very careful which methods you call and which libraries you use in order to avoid accidentally making blocking I/O calls.

nginx vs. apache

● Apache uses 1 thread per connection.○ 1 thread per connection is limiting for massive

concurrency● Nginx doesn't use threads

○ it runs an event loop○ small memory allocation per connection○ Especially relevant when dealing with I/O All code

runs in a single thread○ No need for multithreading – no locks!

nginx vs. apache

nginx vs. apache

http://blog.webfaction.com/a-little-holiday-present

benchmarking - req/sec

100 concurrent clients1 megabyte response ● node 822 ● nginx 708● thin 85● mongrel 4

why should i care?

● I love Ruby● I can use EventMachine for async● And, after all, my Rails app doesn't have

youporn’s traffic

what do we want?

● closures● event-driven language (callbacks)● easy to code● non-blocking, no processes/threads hassle● widely usewindow.onload = function() { alert("Apollo 11 landed!")}d

● Ruby is a programming language and Rails is a web application framework.

● Node.js is neither a language nor an application framework, it's an asynchronous I/O library.

● ECMAScript is crap- can't read files, load scripts, access the network. You can't even access the friggin' web! (which is kind of ironic for a web scripting language) => Node is great!

● A set of bindings to Google’s V8 Javascript VM (fast, super-duper fast)

● A purely evented, non-blocking infrastructure that makes it super simple to build highly concurrent programs

● Ability to handle thousands of concurrent connections with minimal overhead on a single process

● all blocking I/O written from scratch (in C)● CommonJS module format● one code to rule them all!

node is

● only exposes non-blocking asynchronous interfaces

● only one thread, one stack (like browser)● low level features: fs, tcp, udp● has killer HTTP support

Async I/O

file.read('file.txt', function(pickUpLine) { tryYourBestWithThat(pickUpLine);});flirtWithTheUglyOne();

win!

installing node.js

> brew install node.jsor> git clone http://github.com/ry/node.git && cd node> ./configure && make && make install

time to code!

demo - node console, global, process, version, env, pid, hello world

CommonJS & Modules

CommonJS is a community driven effort to standardize packaging of JavaScript libraries, known as modules. Modules written which comply to this standard provide portability between other compliant frameworks such as narwhal, and in some cases even browsers.

CommonJS & Modules

hello.jsexports.world = function() { return 'Hello World';};

app.jsvar hello = require('./hello');var sys = require('sys');sys.puts(hello.world());

http server

var sys = require('sys'), http = require('http');http.createServer(function (req, res) {

res.writeHead(200, {'Content-Type': 'text/plain'});

res.write('Hello World');res.end();

}).listen(8000);sys.puts('Running at http://127.0.0.1:8000/');

tcp server

var tcp = require('net');tcp.createServer(function(socket) { socket.addListener('connect', function() { socket.send("Hi, How Are You?\n> "); }); socket.addListener('receive', function(data) { socket.send(data); });}).listen(4000);

child process

var spawn = require('child_process').spawn, ls = spawn('ls');ls.stdout.on('data', function (data) { console.log('stdout: ' + data);});console.log('Spawned child pid: ' + ls.pid);ls.stdin.end();

libraries

● Connect (middleware)● Express (sinatra)● Mongoose (db)● Expresso / should.js (TDD)● node_redis (guess)● npm● much (much) more...

'ruby is so yesterday's news'...

● Tower.js● RailwayJS

RailwayJS

● full stack MVC framework.● Doing to Node what Rails has done to Ruby.

> sudo npm install railway -g> railway init blog && cd blog> npm install -l> railway generate crud post title content> railway server 8888> open http://127.0.0.1:8888/posts

hello world!TEXT_IO.PUT_LINE ("Hello, World!"); Response.Write("Hello, World!")10 PRINT "Hello, World!"System.Console.WriteLine("Hello, World!");std::cout << "Hello, World!\n";DISPLAY "Hello, World!".fmt.Printf("Hello, World!\n");System.out.println("Hello, World!");(format t "Hello World!~%")printf( "Hello, World!\n" );print "Hello, World!\n";echo 'Hello, World!';:- write('Hello world'),nl.puts "Hello, World!"

adaaspbasicc#c++cobolgojavalispobjectiveCperlPHPprologruby

Javascript ftw!

one language to rule them alll

alert('the end!');