FuzedErlang and Rails, Sittin’ in a Tree
Dave Fayram & Tom Preston-Werner
github.com/KirinDave/
fuzed
“If humans can land robots on
Mars, then there is no reason
we can’t make a fast Ruby.”
—Evan Phoenix
http
://flickr.co
m/p
hoto
s/drb
rain/4
21875792/
Phoenix
But no matter how fast Ruby is...
...we will always need a way to scale it!
Traditional Scaling
nginx
internet
mongrel mongrel
mongrel
nginx
internet
mongrel
mongrel
mongrel
mongrel
mongrel
mongrel
mongrel
mongrel
mongrel
internet
nginx
load
balancer
nginx
What happens if a machine fails?
What happens if you need to add more
hardware fast?
What happens if you have a mixture of very fast and
very slow pages?
What do you do about a staging setup?
How do you deal with scaling in a flexible cloud
(like EC2)?
What happens if you change your environment
(e.g. from EC2 to a colo facility)?
Real Time
Cluster
Assembly
What happens if a machine fails?
It will automatically be taken out of rotation, and
rejoin once back up.
What happens if you need to add more
hardware fast?
No configuration changes necessary.
Just add more nodes.
What happens if you have a mixture of very fast and
very slow pages?
Fuzed uses “next available resource”
queuing. Not a problem.
What do you do about a staging setup?
Run multiple versions of your app in the same cloud!
How do you deal with scaling in a flexible cloud
(like EC2)?
Please. Fuzed was MADE for a dynamic cloud environment.
What happens if you change your environment
(e.g. from EC2 to a colo facility)?
Change a few hostnames in startup
commands. Done.
Insanely Flexible
or, what I like to call
Multiple Dimensions of Horizontal Scalability
faceplate
faceplate
master
faceplate
faceplate
master
worker
worker
worker
faceplate
faceplate
faceplate
faceplate
master
worker
worker
worker
faceplate
faceplate
faceplate
faceplate worker
master
worker
worker
worker
worker
worker
worker
worker
Things Fuzed Does Not
Help You With
DB
Scaling your Database
DB
DB
DB
DB
Scaling your Databasebummer
dude!
DB
DB
DB
Raw Speed
SWEETSWEET
Basic Fuzed Architecture
masterfaceplate resource_manager
resource_manager
worker
worker
worker
port
port
port
masterfaceplate
details
resource_manager
worker
worker
worker
port
port
port
masterfaceplate
master
resource_manager
worker
worker
worker
port
port
portpool
port
port
port
faceplate
master
resource_manager
worker
worker
worker
port
port
portpool
port
port
port
faceplate
master
resource_manager
worker
worker
worker
port
port
portpool
port
port
port
faceplate
internet
master
resource_manager
worker
worker
worker
port
port
portpool
port
port
port
faceplate
internet
master
resource_manager
worker
worker
worker
port
port
portpool
port
port
port
faceplate
internet
master
resource_manager
worker
worker
worker
port
port
portpool
port
port
faceplate
internet
port
master
resource_manager
worker
worker
worker
port
port
portpool
port
port
faceplate
internet
port
master
resource_manager
worker
worker
worker
port
port
portpool
port
port
faceplate
internet
port
master
resource_manager
worker
worker
worker
port
port
portpool
port
port
faceplate
internet
port
master
resource_manager
worker
worker
worker
port
port
portpool
port
port
faceplate
internet
port
master
resource_manager
worker
worker
worker
port
port
portpool
port
port
faceplate
internet
port
master
resource_manager
worker
worker
worker
port
port
portpool
port
port
port
faceplate
internet
ChassisLike the River Styx only
where Erlang is the Earth and Ruby is Hades.
Wait—that came out wrong.
class RailsHandler < Chassis
kind "rails"
handle(:handle_request, :request) do |args|
$handler.service(args[:request])
end
end
Rails Chassis
class RailsHandler < Chassis
kind "rails"
handle(:handle_request, :request) do |args|
$handler.service(args[:request])
end
end
Rails Chassis
Request (rack-style){ "SERVER_NAME" => "frontend_responder", "HTTP_USER_AGENT" => "Mozilla/5.0 Firefox/3.0", "HTTP_ACCEPT_ENCODING" => "gzip,deflate", "PATH_INFO" => "/main/go", "HTTP_HOST" => "localhost:8080", "HTTP_ACCEPT_LANGUAGE" => "en-us,en;q=0.5", "REQUEST_PATH" => "/", "HTTP_KEEP_ALIVE" => "300", "HTTP_VERSION" => "1.1", "HTTP_ACCEPT_CHARSET" => "ISO-8859-1,utf-8;q=0.7,*;q=0.7", "SERVER_PORT" => nil, "Cache-Control" => "max-age=0", "QUERY_STRING" => "", "HTTP_ACCEPT" => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "HTTP_CONNECTION" => "keep-alive", "REQUEST_METHOD" => "GET", "rack.input" => #<StringIO:0x238cc1c>, "rack.errors" => #<IO:0x2f7c4>, "rack.run_once" => false, "rack.url_scheme" => "http", "rack.multiprocess" => false, "rack.multithread" => true, "rack.version" => [0, 1]}
[:response,
[[:status, 200], [:allheaders,
[[:header, "Server", "YAWS + Fuzed 0.0.1"], [:header, "Content-Type", "text/html; charset=utf-8"],
[:header, "Cache-Control", "no-cache"], [:header, "Connection", "close"],
[:header, "Content-Length", "4"]]], [:html, "done"]]]
Response (yaws-style)
Chassis is a language agnostic construct
Ruby
Python
LispScheme
BefungeC
Oh, you need a scalableJSON server too?
require 'chassis'
class AdderNode < Chassis kind "calculon"
handle(:add, :arg1, :arg2) do |args| args[:arg1] + args[:arg2] end
handle(:crash) do |args| raise "You asked me to crash, so I did." endend
Eliminate the master as a single point of failure
mastermaster
master
master
•URL paths
•HTTP headers
•Error handling (flexible strategies)
Additional dispatch details
More Chassis ModulesWe love contributions!
http://github.com/KirinDave/fuzed
Fuzed is:
Your secret scalability weapon!
Thanks to our employer
Powerset