TorqueBox for Rubyists
-
Upload
bobmcwhirter -
Category
Technology
-
view
1.894 -
download
1
description
Transcript of TorqueBox for Rubyists
TorqueBoxEnterprise-Grade Ruby Application ServerBob McWhirter
Asheville.rbAsheville, North Carolina
2 December 2009
Creative Commons BY-SA 3.0
Bob McWhirter
• Started in C++
• Moved to Java with JDK 1.1.8
• Began Ruby and Rails in 2005
• Lived in Asheville for 4 years
• Did some open-source along the way
2
Open-Source
3
Currently
4
Bob
Java
Linux
+
+
5
== Ruby?
Actual R&D
6
I get to actually research things, and develop new stuff. Honest-to-goodness technology R&D investment.
TorqueBox
7
...in a nutshell
What is it?
A merging of the Ruby language with the Java Virtual Machine.
8
Why bother?
As Ruby matures, it’s quickly being used to solve larger, more difficult problems.
Problems we’ve solved in the enterprise with Java already.
9
Such as...?
• Scalability
• Efficient & asynchronous messaging
• Scheduled jobs
• Telephony
10
Scalability...because “Rails doesn’t scale”
11
Web Scalability
12
mongrel-style
13
Ruby
mongrel
mongrel-style
14
Ruby
mongrel
Ruby
mongrel
Ruby
mongrel
Ruby
mongrel
httpd
mongrel-style
15
Ruby
mongrel
Ruby
mongrel
Ruby
mongrel
Ruby
mongrel
httpd
passenger style
16
Rails
Rails
Rails
Rails
RubyPassengerhttpd
Conservative Spawning
passenger style
17
Worker
Worker
Worker
Worker
RailsRubyPassengerhttpd
Smart Spawning
TorqueBox style
18
RailsRuby
TorqueBox
http
queues
scheduler
MyApp
Clustering
19
Multiplicity rocks.
Concerns
When clustering, we care about sessions and load balancing.
20
Sessions
With multiple application servers, sessions must be shared, or session affinity must be used.
21
Session Sharing
Sharing sessions requires using a central store, such as memcached or ActiveRecord session stores.
22
Session Sharing
23
memcached
Worker
Worker
Worker
Worker
Session Sharing
24
But what if the central session store is unavailable, or overwhelmed?
Single point of failure!
Session Sharing
25
memcached
Worker
Worker
Worker
Worker
Session Affinity
26
Session affinity is making sure the same back-end server handles all of Todd’s requests.
Todd’sserver
Session Affinity
27
Worker
Worker
Worker
Worker
BalancerTodd
Session Affinity
28
But what if the back-end server handling Todd’s requests becomes unavailable?
Session Affinity
29
Worker
Worker
Worker
Worker
Balancer
Todd’sserver
Todd
Use Both!
30
Use session affinity when you can, but allow workers to replicate session information when necessary.
Use Both!
31
Cache
Cache
Cache
CacheWorker
Worker
Worker
Worker
Balancer
Spanning Hosts
32
Host
Host
Host
Host
Cache
Cache
Cache
CacheWorker
Worker
Worker
Worker
Balancer
Balancer in the cluster
33
Using mod_cluster for Apache httpd, the balancer participates in the cluster view.
mod_cluster
As server nodes join and leave the cluster, the balancer (mod_cluster) is aware of these changes.
34
mod_proxy_ajp
The Apache JServ Protocol (AJP) is an efficient pipeline for shuffling HTTP requests to a Java application-server for handling.
35
Oh yeah...
• Multiple apps per server or cluster.
• Virtual-host support baked in.
• Context-path support.
• Full Rack support (bare, Sinatra, etc).
• Full Java-EE stack.
36
And bundles
myapp.rails myapp.rack
37
And bundles
Single ZIP file bundle of an app. Easily move specific artifact between staging and production.
Required for cluster auto-farming deployment.
38
Rails scales!...but there’s more than just port 80.
39
Task QueuesSimply install Erlang, set up RabbitMQ, use an AMQP gem...
40
Or just use TorqueBox...and just write a Ruby class.
41
app/queues/**_queue.rb
• A class per queue.
• A method per task handled by the queue.
• A simple API to toss stuff around.
42
my_first_queue.rb
class MyFirstQueue
include TorqueBox::Queues::Base
def task_one(payload={})
o = Thing.find_by_id( payload[:thing_id] )
o.frob!
o.save!
end
end
43
my_first_queue.rb
class MyFirstQueue
include TorqueBox::Queues::Base
def task_one(payload={})
o = Thing.find_by_id( payload[:thing_id] )
o.frob!
o.save!
end
end
44
my_first_queue.rb
class MyFirstQueue
include TorqueBox::Queues::Base
def task_one(payload={})
o = Thing.find_by_id( payload[:thing_id] )
o.frob!
o.save!
end
end
45
my_first_queue.rb
class MyFirstQueue
include TorqueBox::Queues::Base
def task_one(payload={})
o = Thing.find_by_id( payload[:thing_id] )
o.frob!
o.save!
end
end
46
my_first_queue.rb
class MyFirstQueue
include TorqueBox::Queues::Base
def task_one(payload={})
o = Thing.find_by_id( payload[:thing_id] )
o.frob!
o.save!
end
end
47
Enqueue
TorqueBox::Queues.enqueue( ‘MyFirstQueue’, :task_one, { :thing_id=>42 })
48
Enqueue
TorqueBox::Queues.enqueue( ‘MyFirstQueue’, :task_one, { :thing_id=>42 })
49
Enqueue
TorqueBox::Queues.enqueue( ‘MyFirstQueue’, :task_one, { :thing_id=>42 })
50
Enqueue
TorqueBox::Queues.enqueue( ‘MyFirstQueue’, :task_one, { :thing_id=>42 })
51
Enqueue
Use from your controllers, ActiveRecord observers, or other queues.
52
Enqueueclass User < ActiveRecord::Base has_attached_file :avatar, ... after_save do |user| TorqueBox::Queues.enqueue( :image_processor_queue, :process_user_avatar, user.id ) if user.avatar_needs_processing? endend
53
Enqueueclass User < ActiveRecord::Base has_attached_file :avatar, ... after_save do |user| TorqueBox::Queues.enqueue( :image_processor_queue, :process_user_avatar, user.id ) if user.avatar_needs_processing? endend
54
Enqueueclass User < ActiveRecord::Base has_attached_file :avatar, ... after_save do |user| TorqueBox::Queues.enqueue( :image_processor_queue, :process_user_avatar, user.id ) if user.avatar_needs_processing? endend
55
Enqueueclass User < ActiveRecord::Base has_attached_file :avatar, ... after_save do |user| TorqueBox::Queues.enqueue( :image_processor_queue, :process_user_avatar, user.id ) if user.avatar_needs_processing? endend
56
Queue Benefits
• No additional systems or languages to setup and maintain.
• Clustering/HA available (including durable messages).
• No explicit queue configuration required.
57
Scheduled JobsJust write a script, and a crontab, and deploy it with your app. Don’t forget to undeploy and update it also. And check cron.log for errors.
58
Or just use TorqueBox...and just write a Ruby class.
59
app/jobs/**.rb
• A class per queue.
• A method called run()
• Configure it via jobs.yml
60
my_first_job.rbclass MyFirstJob include TorqueBox::Jobs::Base
def run() subscriptions = Subscription.find(:all) subscriptions.each do |e| send_newsletter( e ) end endend
61
my_first_job.rbclass MyFirstJob include TorqueBox::Jobs::Base
def run() subscriptions = Subscription.find(:all) subscriptions.each do |e| send_newsletter( e ) end endend
62
my_first_job.rbclass MyFirstJob include TorqueBox::Jobs::Base
def run() subscriptions = Subscription.find(:all) subscriptions.each do |e| send_newsletter( e ) end endend
63
my_first_job.rbclass MyFirstJob include TorqueBox::Jobs::Base
def run() subscriptions = Subscription.find(:all) subscriptions.each do |e| send_newsletter( e ) end endend
64
config/jobs.yml
subscription.mailer: description: send out newsletters job: MyFirstJob cron: 20 7 1 * * ?
65
config/jobs.yml
subscription.mailer: description: send out newsletters job: MyFirstJob cron: 20 7 1 * * ?
66
config/jobs.yml
subscription.mailer: description: send out newsletters job: MyFirstJob cron: 20 7 1 * * ?
67
config/jobs.yml
subscription.mailer: description: send out newsletters job: MyFirstJob cron: 20 7 1 * * ?
68
config/jobs.yml
subscription.mailer: description: send out newsletters job: MyFirstJob cron: 20 7 1 * * ?
69
config/jobs.yml
20 7 1 * * ?
70
secmin
hourd.o.m.
mond.o.y
config/jobs.yml
20 7 1 * * ?
71
Every day,
at 1:07:20 am
• Uses existing Ruby interpreter when jobs fire. No waiting for Ruby/Rails to load.
• No external system (crontab) to maintain.
• No additional daemons to monitor (daemonize)
• Full Rails environment (AR models, queues, lib/)
72
Scheduler Benefits
TelephonyJust... um... something... with Asterisk?
73
Or just use TorqueBox...and just write a Ruby class.
74
Initiate Calls
By doing SIP magic, your application can initiate calls, or connect multiple parties.
75
Press 2 to STFU
Using the Media Server, automated messages, interactive voice response (IVR) and other advanced systems can be built.
76
OMGWTFBBQPONIES!
Have your app (for instance, upon
successful job completion) fire off an SMS.
77
Telephony Benefits
•It’s just freakin’ cool.
78
ManageabilityOkay, sorta speculative, forward-looking dreaming, but...
79
Manageable
Everything ultimately maps to a managed object within the Java application-server.
We have the JOPR management console.
80
But not yet
But we haven’t exposed everything in a super nice fashion. Yet.
81
All-in-OneEverything’s in the tin.Everything works together.
82
More information...http://torquebox.org/
http://github.com/torquebox
http://twitter.com/torquebox
83
Thanks +
Q&A
84Creative Commons BY-SA 3.0