TorqueBox for Rubyists

Post on 06-May-2015

1,895 views 1 download

description

Presentation of TorqueBox for Rubyists at Asheville.rb

transcript

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