complex made simple: sleep better with torquebox

81
Complex Made Simple Sleep Better With TorqueBox Bob McWhirter Director of Polyglot Red Hat Creative Commons BY SA 3.0

Upload: bobmcwhirter

Post on 08-May-2015

2.786 views

Category:

Technology


0 download

DESCRIPTION

The TorqueBox presentation by Bob McWhirter as presented at RubyNation 2012 in Reston, VA.

TRANSCRIPT

Page 1: Complex Made Simple: Sleep Better with TorqueBox

Complex  Made  SimpleSleep Better With TorqueBox

Bob  McWhirterDirector  of  PolyglotRed  Hat

Creative  Commons  BY-­SA  3.0

Page 2: Complex Made Simple: Sleep Better with TorqueBox

Complex  Made  SimpleSleep Better With TorqueBox

Bob  McWhirterDirector  of  PolyglotRed  Hat

Creative  Commons  BY-­SA  3.0

Page 3: Complex Made Simple: Sleep Better with TorqueBox

Who  am  I?

๏ Director  of  Polyglot,  JBoss  Fellow  @  Red  Hat๏ TorqueBox  project  founder๏ Part  of  the  project:odd  team๏ The  Codehaus,  Drools,  Jaxen,  Groovy

Bob  McWhirter

Page 4: Complex Made Simple: Sleep Better with TorqueBox

Scenario

You've  got  a  Rails  application  to  deploy,  for  production.

Page 5: Complex Made Simple: Sleep Better with TorqueBox

But...

The  app  you  deploy  today  will  grow  in  the  future,  if  you’re  successful.

Page 6: Complex Made Simple: Sleep Better with TorqueBox

Deploy  Continuum

Roll!your!own

Platformas!a!Service

TorqueBox

Page 7: Complex Made Simple: Sleep Better with TorqueBox

What  is  TorqueBox?

TorqueBox  is  a  Ruby  Application  Server.

Based  on  JRuby  and  JBoss  AS7.

Page 8: Complex Made Simple: Sleep Better with TorqueBox

What  is  an  app-­server?

If  you’re  not  from  the  Java  world...An  application  server  is  a  process  that  hosts  your  app  and  provides  a  multitude  of  services  and  facilities.

Page 9: Complex Made Simple: Sleep Better with TorqueBox

App-­servertastic!

Application

Queues

Web HA

Cache Jobs

Page 10: Complex Made Simple: Sleep Better with TorqueBox

Anyhow...

Page 11: Complex Made Simple: Sleep Better with TorqueBox

Roll  your  own

๏ Install  OS๏ Install  packages๏ Configure  everything๏ Manage  everything

Page 12: Complex Made Simple: Sleep Better with TorqueBox

Roll  your  own๏ Apache  httpd๏ Load  balancer๏ Unicorn,  pack  of  Mongrels๏ crontab๏ SMTP๏ memcached๏ Database๏ deployment๏ monitoring

Page 13: Complex Made Simple: Sleep Better with TorqueBox

Or  outsource  some...

Page 14: Complex Made Simple: Sleep Better with TorqueBox

Roll  your  own  >>

๏ Install  OS๏ Install  packages๏ Configure  most  things๏ Manage  most  things๏ Outsource  some  things

Page 15: Complex Made Simple: Sleep Better with TorqueBox

Roll  your  own  >>๏ Apache  httpd๏ Load  balancer๏ Unicorn,  pack  of  Mongrels๏ crontab๏ SMTP  Amazon  SES,  SendGrid๏ memcached๏ Database๏ deployment  Capistrano๏ monitoring  New  Relic

Page 16: Complex Made Simple: Sleep Better with TorqueBox

Use  a  Paas  (Heroku)

Outsource  everything  but  your  app.

Page 17: Complex Made Simple: Sleep Better with TorqueBox

Heroku๏ Apache  httpd  Heroku๏ Load  balancer  Heroku๏ Unicorn,  pack  of  Mongrels  Heroku๏ crontab  Heroku๏ SMTP  SendGrid๏ memcached  Heroku๏ Database  Heroku๏ deployment  Heroku๏ monitoring  New  Relic

Page 18: Complex Made Simple: Sleep Better with TorqueBox

Or  middle-­ground

๏ Decrease  number  of  things  to  manage๏ Increase  scalability๏ Increase  availability  (optionally)

Page 19: Complex Made Simple: Sleep Better with TorqueBox

TorqueBox๏ Apache  httpd๏ Load  balancer  JBoss  mod_cluster๏ Unicorn,  pack  of  Mongrels  TorqueBox๏ crontab  TorqueBox๏ SMTP  Amazon  SES,  SendGrid๏ memcached  TorqueBox๏ Database๏ deployment  Capistrano๏ monitoring  NewRelic

Page 20: Complex Made Simple: Sleep Better with TorqueBox

Case  Study!

Page 21: Complex Made Simple: Sleep Better with TorqueBox

Appalachian  Sustainable  Agriculture  Project  (ASAP)

Page 22: Complex Made Simple: Sleep Better with TorqueBox

Application  Needs๏ Rails  2.x  web  app๏ Caching๏ Background  tasks๏ Cron  jobs๏ Deployment  from  SCM๏ Sending  email๏ Database  queries๏ Monitoring  &  metrics

Page 23: Complex Made Simple: Sleep Better with TorqueBox

As  deployed  on  Heroku

Page 24: Complex Made Simple: Sleep Better with TorqueBox

Migration  Motivation

In  this  particular  case,  client  feels  it  could  save  money,  and  have  a  better  system  by  moving  to  an  affordable  VPS,  letting  TorqueBox  absorb  some  of  the  roll-­your-­own  complexity.

Page 25: Complex Made Simple: Sleep Better with TorqueBox

Migrating  to  TorqueBox

$  rvm  install  jruby-­1.6.7

Page 26: Complex Made Simple: Sleep Better with TorqueBox

Migrating  to  TorqueBox

$  gem  install  torquebox-­server  \    -­-­pre  -­-­version=2.0.0.cr1

Simpler  once  we’re  no  longer  -­-­pre

Page 27: Complex Made Simple: Sleep Better with TorqueBox

Using  torquebox.rb  template

$  cd  myapp$  torquebox  rails

Page 28: Complex Made Simple: Sleep Better with TorqueBox

torquebox.rb  template

๏ Add  torquebox  gems  to  Gemfile๏ Add  activerecord-­jdbc-­adapter๏ Add  torquebox-­rake-­support๏ Create  directories  for  services,  jobs,  etc๏ Initialize  web  session  store๏ Initialize  Rails.cache  with  TorqueBox๏ Initialize  ActiveRecord  for  background  jobs

Page 29: Complex Made Simple: Sleep Better with TorqueBox

“Porting”  the  application

Page 30: Complex Made Simple: Sleep Better with TorqueBox

Delayed::Job

App  uses  Delayed::Job  

Replace  with  TorqueBox  Backgroundable

Page 31: Complex Made Simple: Sleep Better with TorqueBox

controller.rb

Delayed  Job

def  create    @export  =  ExcelExport.create(...)    job  =  ExcelExportJob.new      job.excel_export_id  =  @export.id    Delayed::Job.enqueue  job    @export.set_status  "Queued  for  Export"    @export.save!end

Page 32: Complex Made Simple: Sleep Better with TorqueBox

excel_export_job.rb

class  ExcelExportJob  <  Struct.new(:excel_export_id)    def  perform        ExcelExport.find(self.excel_export_id).generate_report    endend

Delayed  Job

Page 33: Complex Made Simple: Sleep Better with TorqueBox

excel_export.rb

Delayed  Jobclass  ExcelExport  <  ActiveRecord::Base    def  generate_report        begin            set_status  'Processing'            spreadsheet  =  Spreadsheet.new(self.businesses)                    set_status  'Writing'            spreadsheet.write_workbook  self.workbook_file

           set_status  'Storing  on  Amazon  S3'            File.open(self.workbook_file)  {|out|self.output  =  out}                    set_status  'Cleaning  Up'            File.delete(self.workbook_file)                    set_status  'Complete'        rescue            set_status  'Export  Error'        end    end

Page 34: Complex Made Simple: Sleep Better with TorqueBox

Delayed  Job

Mayhap  you  need  to  run  a  worker,  also...

Page 35: Complex Made Simple: Sleep Better with TorqueBox

Delayed::Job

Exporter < AR::Base

ExportJob < Struct

Database

Worker

Page 36: Complex Made Simple: Sleep Better with TorqueBox

That's  pretty  explicit

TorqueBox  allows  you  to  very  easily  run  methods  asynchronously.

Page 37: Complex Made Simple: Sleep Better with TorqueBox

excel_export.rb

Backgroundable

class  ExcelExport  <  ActiveRecord::Base    always_background  :generate_report

   def  generate_report        begin            set_status  'Processing'            ...        rescue            set_status  'Export  Error'        end    end

end    

Page 38: Complex Made Simple: Sleep Better with TorqueBox

excel_export.rb

Backgroundable

class  ExcelExport  <  ActiveRecord::Base    always_background  :generate_report

   def  generate_report        begin            set_status  'Processing'            ...        rescue            set_status  'Export  Error'        end    end

end    

Page 39: Complex Made Simple: Sleep Better with TorqueBox

export_controller.rb

Backgroundable

def  create    @export  =  ExcelExport.create(...)    @export.set_status  "Queued  for  Export"    @export.save    @export.generate_reportend

Page 40: Complex Made Simple: Sleep Better with TorqueBox

$  rm  excel_export_job.rb

excel_export_job.rb

Backgroundable

Kill  it!

Page 41: Complex Made Simple: Sleep Better with TorqueBox

Trade!

Trade  some  code  and  a  process  you  have  to  manage  for  less  code  and  an  in-­container  service.

Page 42: Complex Made Simple: Sleep Better with TorqueBox

Backgroundable

Exporter < AR::Base

ExportJob < Struct

Database

Worker

Queue Processor

Implicit!magic!

Page 43: Complex Made Simple: Sleep Better with TorqueBox

Caching

๏ template.rb  does  most  of  the  work๏Web  sessions๏Fragment  and  other  caching

Page 44: Complex Made Simple: Sleep Better with TorqueBox

No  more  memcached!

Page 45: Complex Made Simple: Sleep Better with TorqueBox

Scheduled  Jobs

๏Replaces  cron  jobs๏Deploys  with  your  application๏ Includes  application  environment๏Cron-­like  scheduling๏HA-­clustering  (optionally)

Page 46: Complex Made Simple: Sleep Better with TorqueBox

Heroku  Cron

๏Free  version  runs  1x  daily๏ Implemented  as  a  rake  task๏ Includes  application  environment

Page 47: Complex Made Simple: Sleep Better with TorqueBox

Roll  your  own

๏ crontab๏ script/runner  (boots  rails  every  time)๏ deployment  strategy๏ source  control๏ etc.

Page 48: Complex Made Simple: Sleep Better with TorqueBox

Rakefile

On  Heroku

desc  "This  task  is  called  by  the  heroku  cron  add-­on"task  :cron  =>  [:environment,                                :heroku_backup,                                :refresh_trip_planner]  

desc  "Refresh  the  trip  planner  business  data  cache"task  :refresh_trip_planner  =>  :environment  do    #    #  update  GIS  cache    #end

Page 49: Complex Made Simple: Sleep Better with TorqueBox

Scheduled  Jobs

In  TorqueBox,  a  scheduled  job  is  a  component  of  your  application.

Page 50: Complex Made Simple: Sleep Better with TorqueBox

refresh_trip_planner.rb

Straight-­forward

class  RefreshTripPlanner    def  run()        #        #  update  the  GIS  cache        #    endend

Page 51: Complex Made Simple: Sleep Better with TorqueBox

torquebox.yml

Configuration

jobs:    cache.updater:        job:                  RefreshTripPlanner        cron:                '0  0  2  *  *  ?'        description:  Refresh  trip  cache

Page 52: Complex Made Simple: Sleep Better with TorqueBox

But...

Doing  a  huge  query  once-­a-­day  isn't  ideal,  it  was  just  "free".

Page 53: Complex Made Simple: Sleep Better with TorqueBox

TorqueBox  Services

๏Avoid  the  huge  query๏Keep  data  more  fresher

Page 54: Complex Made Simple: Sleep Better with TorqueBox

trip_planner_service.rb

Keep  it  fresher

 TripPlannerService    def  initialize(  options={}  )        @queue  =  TorqueBox::Messaging::Queue.new(  '/queues/trip_planner'  )    end        def  start        Thread.new  do            initialize_cache            while  should_run                update_cache  @queue.receive            end        end    end

   def  update_cache(  business_id  )        TripPlanner.insert_or_update  business_id    end    #  initialize_cache(),  stop(),  etcend

Page 55: Complex Made Simple: Sleep Better with TorqueBox

trip_planner_service.rb

Keep  it  fresher

 TripPlannerService    def  initialize(  options={}  )        @queue  =  TorqueBox::Messaging::Queue.new(  '/queues/trip_planner'  )    end        def  start        Thread.new  do            initialize_cache            while  should_run                update_cache  @queue.receive            end        end    end

   def  update_cache(  business_id  )        TripPlanner.insert_or_update  business_id    end    #  initialize_cache(),  stop(),  etcend

def  initialize(  options={}  )    @queue  =  TorqueBox::Messaging::Queue.new(  ...  )end

Page 56: Complex Made Simple: Sleep Better with TorqueBox

trip_planner_service.rb

Keep  it  fresher

 TripPlannerService    def  initialize(  options={}  )        @queue  =  TorqueBox::Messaging::Queue.new(  '/queues/trip_planner'  )    end        def  start        Thread.new  do            initialize_cache            while  should_run                update_cache  @queue.receive            end        end    end

   def  update_cache(  business_id  )        TripPlanner.insert_or_update  business_id    end    #  initialize_cache(),  stop(),  etcend

def  start    Thread.new  do        initialize_cache        while  should_run            update_cache  @queue.receive        end    endend

Page 57: Complex Made Simple: Sleep Better with TorqueBox

require  'torquebox-­messaging'

class  Business  <  ActiveRecord::Base

   after_save  :update_trip_planner

   def  update_trip_planner        queue  =  TorqueBox::Messaging::Queue.new('/queues/trip_planner')        queue.publish(  self.id  )    end

end

app/models/business.rb

Keep  it  fresher

Page 58: Complex Made Simple: Sleep Better with TorqueBox

require  'torquebox-­messaging'

class  Business  <  ActiveRecord::Base

   after_save  :update_trip_planner

   def  update_trip_planner        queue  =  TorqueBox::Messaging::Queue.new('/queues/trip_planner')        queue.publish(  self.id  )    end

end

app/models/business.rb

Keep  it  fresher

queue  =  TorqueBox::Messaging::Queue.new(...)queue.publish(  self.id  )

Page 59: Complex Made Simple: Sleep Better with TorqueBox

Queue,  Service,  Cache

Non-blocking

Service

Cache

ActiveRecord

Business

Queue

Page 60: Complex Made Simple: Sleep Better with TorqueBox

Production!

Page 61: Complex Made Simple: Sleep Better with TorqueBox
Page 62: Complex Made Simple: Sleep Better with TorqueBox

(Remember,  we  work  for  Red  Hat)

Page 63: Complex Made Simple: Sleep Better with TorqueBox

Set  up  the  server

$  yum  install  \        java-­1.6.0-­openjdk  \        httpd  \        mod_cluster  \        git  \        postgresql-­server

Page 64: Complex Made Simple: Sleep Better with TorqueBox

Capistrano

Regular  capistrano  deployments  are  supported  given  the  recipes  provided  by  torquebox-­capistrano-­support.gem

Page 65: Complex Made Simple: Sleep Better with TorqueBox

deploy.rb

Capistrano

require 'torquebox-capistrano-support'require 'bundler/capistrano'

# source codeset :application, "buyappalachian.org"set :repository, "[email protected]:account/repo.git"set :branch, "torquebox-2.0"set :user, "torquebox"set :scm, :gitset :scm_verbose, trueset :use_sudo, false

Page 66: Complex Made Simple: Sleep Better with TorqueBox

deploy.rb  (continued)

Capistrano

# Production serverset :deploy_to, "/opt/apps/buyappalachian.org"set :torquebox_home, "/opt/torquebox/current"set :jboss_init_script, "/etc/init.d/jboss-as-standalone"set :app_environment, "RAILS_ENV: production"set :app_context, "/"

ssh_options[:forward_agent] = false

role :web, "torquebox.buyappalachian.org"role :app, "torquebox.buyappalachian.org"role :db, "torquebox.buyappalachian.org", :primary => true

Page 67: Complex Made Simple: Sleep Better with TorqueBox

Launch  on  boot

Page 68: Complex Made Simple: Sleep Better with TorqueBox

init.d

Install  /etc/init.d/jboss-­asfrom  the  stock  distribution

Page 69: Complex Made Simple: Sleep Better with TorqueBox

/etc/jboss-­as/jboss-­as.conf

JBoss  configuration

# General configuration for the init.d script# Place this file in /etc/jboss-as/jboss-as.conf# and copy $JBOSS_HOME/bin/init.d/jboss-as-standalone.sh # to /etc/init.d/jboss-as-standalone

JBOSS_USER=torqueboxJBOSS_HOME=/opt/torquebox/current/jbossJBOSS_PIDFILE=/var/run/torquebox/torquebox.pidJBOSS_CONSOLE_LOG=/var/log/torquebox/console.logJBOSS_CONFIG=standalone-ha.xml

Page 70: Complex Made Simple: Sleep Better with TorqueBox

Load  Balance  with  mod_cluster

Page 71: Complex Made Simple: Sleep Better with TorqueBox

httpd.conf

mod_cluster

LoadModule  slotmem_module              modules/mod_slotmem.soLoadModule  proxy_cluster_module  modules/mod_proxy_cluster.soLoadModule  advertise_module          modules/mod_advertise.soLoadModule  manager_module              modules/mod_manager.so

<Location  /mod_cluster_manager>        SetHandler  mod_cluster-­manager        AllowDisplay  On</Location>

Listen  torquebox-­balancer:6666

Page 72: Complex Made Simple: Sleep Better with TorqueBox

httpd.conf  (continued)

mod_cluster<VirtualHost  torquebox-­balancer:6666>      <Directory  />        Order  deny,allow        Deny  from  all        Allow  from  all    </Directory>      KeepAliveTimeout  60    MaxKeepAliveRequests  0

   EnableMCPMReceive      ManagerBalancerName  torquebox-­balancer    AllowDisplay  On    AdvertiseFrequency  5    AdvertiseSecurityKey  secret  </VirtualHost>

Page 73: Complex Made Simple: Sleep Better with TorqueBox

Deployed

[root@torquebox  opt]#  ls  -­l  apps/buyappalachian.org/total  8lrwxrwxrwx  1      23  Mar  16  15:10  current  -­>  releases/20120315230553drwxrwxr-­x  5  4096  Mar  15  19:05  releasesdrwxrwxr-­x  6  4096  Mar  15  17:29  shared

Page 74: Complex Made Simple: Sleep Better with TorqueBox

And  then  it  grows...

As  your  app  evolves,  you  might  add  stuff  like  WebSockets/STOMP,  or  HA  or  other  facilities  already  in  the  tin.

Page 75: Complex Made Simple: Sleep Better with TorqueBox

Can  we  go  further?

Page 76: Complex Made Simple: Sleep Better with TorqueBox

What's  a  PaaS?

Application

Queues

DB Email

Cache Jobs

Page 77: Complex Made Simple: Sleep Better with TorqueBox

TorqueBox  on  OpenShift

openshift.redhat.com

Page 78: Complex Made Simple: Sleep Better with TorqueBox

Roadmap  &  Status

๏Current  2.0.0.CR1๏2.0.0.Final  Real  Flippin’  Soon๏Continuing  investment  from  Red  Hat๏ Interop  with  other  languages,  such  as  Clojure  via  Immutant

Page 79: Complex Made Simple: Sleep Better with TorqueBox

Resources

http://torquebox.org/

@torquebox  on  Twitter

#torquebox  on  IRC

Page 80: Complex Made Simple: Sleep Better with TorqueBox

Question  everything.

Page 81: Complex Made Simple: Sleep Better with TorqueBox

Creative  Commons  BY-­SA  3.0