Share
Embed
Transcript
48 slides
-
"Evented I/O for V8 JavaScript" Concurrent, scalable network programs Speaks
HTTP natively Asynchronous, non-blocking by design -
var p_client = new Db('integration_tests_20', new Server("127.0.0.1", 27017, {}), {'pk':CustomPKFactory});
p_client.open(function(err, p_client) { p_client.dropDatabase(function(err, done) { p_client.createCollection('test_custom_key', function(err, collection) { collection.insert({'a':1}, function(err, docs) { collection.find({'_id':new ObjectID("aaaaaaaaaaaa")}, function(err, cursor) { cursor.toArray(function(err, items) { test.assertEquals(1, items.length); // Let's close the db p_client.close(); }); }); }); }); }); }); Callback hell gist.github.com/1309020 -
Rack API Middleware support Ruby fibers No callback hell 1.9.2,
jruby, rubinius -
Rack Example class HelloWorld def call(env) [200, {'Content-Type' => 'text/html'},
["Hello Rack"]] end end run HelloWorld.new -
Node.js Example var http = require('http'); http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello Node\n'); }).listen(9292, "127.0.0.1"); console.log('Server running at http://127.0.0.1:9292/'); -
EventMachine Example require 'rubygems' require 'eventmachine' require 'evma_httpserver' class HelloWorld
< EM::Connection include EM::HttpServer def post_init super no_environment_strings end def process_http_request response = EM::DelegatedHttpResponse.new(self) response.status = 200 response.content_type 'text/html' response.content = 'Hello EventMachine' response.send_response end end EM.run{ EM.start_server '0.0.0.0', 9292, HelloWorld } -
Goliath Example require 'rubygems' require 'goliath' class Proxy < Goliath::API
def response(env) [200, {}, "Hello Goliath"] end end -
Rack Example class HelloWorld def call(env) [200, {'Content-Type' => 'text/html'},
["Hello Rack"]] end end run HelloWorld.new require 'rubygems' require 'goliath' class Proxy < Goliath::API def response(env) [200, {}, "Hello Goliath"] end end -
rack => 423 goliath => 2125 node => 6084 em
=> 8814 Performance (requests/s) ab -n 1000 -c 100 http://localhost:9000/ -
var http = require('http'), connect = require('connect'), redis = require("redis"),
client = redis.createClient(), b62 = require('base62'); var server = connect.createServer(connect.query()); server.use('/', connect.router(function(app){ app.get('/', function(req, res, next){ res.writeHead(200, {'Content-Type': 'text/html'}); if (req.query.url){ client.keys('*',function(err, result){ key = b62.encode(result.length) client.set(key, req.query.url, function(err, result){ res.write('http://localhost:9000/'+key) res.end() }); }); } else { res.write('Hi') res.end() } }); app.get('/:key', function(req, res, next){ client.get(req.params.key, function(err, result){ res.writeHead(302, {'Location': result}); res.end() }); }); }) ); server.listen(9000); console.log('Server running at http://127.0.0.1:9000/'); Node Example github.com/andrew/node-shortener -
class Shortener < EM::Connection include EM::HttpServer attr_reader :http_request_uri, :http_query_string def
post_init super no_environment_strings end def process_http_request redis = EM::Protocols::Redis.connect path = @http_request_uri.to_s query = @http_query_string.to_s response = EM::DelegatedHttpResponse.new(self) case path when '/' if @http_query_string params = URI.decode_www_form(query) url = params.assoc('url').last.chomp redis.keys '*' do |result| key = result.size.base62_encode redis.set key, url do |result| response.status = 200 response.content_type 'text/html' response.content = "http://localhost:9000/#{key}" response.send_response end end else response.status = 200 response.content_type 'text/html' response.content = 'Hi' response.send_response end else redis.get path[1..-1] do |result| response.status = 302 response.headers["Location"] = result response.send_response end end end end EM.run{ EM.start_server '0.0.0.0', 9000, Shortener } EM Example github.com/andrew/em-shortener -
REDIS = EventMachine::Synchrony::ConnectionPool.new(:size => 5) do Redis.connect end class Redirect
< Goliath::API use Goliath::Rack::Params def response(env) url = REDIS.get params[:key] if url [302, {:location => url}, nil] else [404, {}, 'Not Found'] end end end class Create < Goliath::API use Goliath::Rack::Params def response(env) if params['url'] key = REDIS.keys.size.base62_encode REDIS.set(key, params['url']) [200, {}, "http://#{env['HTTP_HOST']}/#{key}"] else [200, {}, "Hi!"] end end end class Shortener < Goliath::API map "/" do run Create.new end map "/:key" do run Redirect.new end end Goliath Example github.com/andrew/goliath-shortener -
goliath => 1048 node => 3660 em => 7943 Performance
(requests/s) ab -n 1000 -c 100 http://localhost:9000/2W -
Express.js app.get('/', function(req, res){ res.send('Hello World'); }); expressjs.com app.get "/",
(req, res) -> res.send "Hello World" -
class HomeAction < Cramp::Action def start render "Hello World" finish
end end Cramp cramp.in -
var http = require('http'), connect = require('connect'), redis = require("redis"),
client = redis.createClient(), b62 = require('base62'); var server = connect.createServer(connect.query()); server.use('/', connect.router(function(app){ app.get('/', function(req, res, next){ res.writeHead(200, {'Content-Type': 'text/html'}); if (req.query.url){ client.keys('*',function(err, result){ key = b62.encode(result.length) client.set(key, req.query.url, function(err, result){ res.write('http://localhost:9000/'+key) res.end() }); }); } else { res.write('Hi') res.end() } }); app.get('/:key', function(req, res, next){ client.get(req.params.key, function(err, result){ res.writeHead(302, {'Location': result}); res.end() }); }); }) ); server.listen(9000); console.log('Server running at http://127.0.0.1:9000/'); Node Example github.com/andrew/node-shortener -
http = require("http") connect = require("connect") redis = require("redis") client
= redis.createClient() b62 = require("base62") server = connect.createServer(connect.query()) server.use "/", connect.router((app) -> app.get "/", (req, res, next) -> res.writeHead 200, "Content-Type": "text/html" if req.query.url client.keys "*", (err, result) -> key = b62.encode(result.length) client.set key, req.query.url, (err, result) -> res.write "http://localhost:9000/" + key res.end() else res.write "Hi" res.end() app.get "/:key", (req, res, next) -> client.get req.params.key, (err, result) -> res.writeHead 302, Location: result res.end() ) server.listen 9000 console.log "Server running at http://127.0.0.1:9000/" Coffeescript Example -
Node Pros Shared code between client and server Vibrant Community
Lightning Fast Cons Javascript Callback hell Less mature -
EventMachine Pros It’s ruby! Mature Clever DSLs Also fast Cons
More difficult to write than normal ruby Restricted to EM libraries Not the new hotness