complex made simple: sleep better with torquebox

85
Complex Made Simple Sleep Better With TorqueBox Lance Ball Senior Software Engineer Red Hat Creative Commons BY-SA 3.0 Friday, April 27, 12

Upload: lance-ball

Post on 08-May-2015

5.336 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: Complex Made Simple: Sleep Better With TorqueBox

Complex Made SimpleSleep Better With TorqueBox

Lance BallSenior Software EngineerRed Hat

Creative Commons BY-SA 3.0

Friday, April 27, 12

Page 2: Complex Made Simple: Sleep Better With TorqueBox

Complex Made SimpleSleep Better With TorqueBox

Lance BallSenior Software EngineerRed Hat

Creative Commons BY-SA 3.0

Friday, April 27, 12

Page 3: Complex Made Simple: Sleep Better With TorqueBox

Who am I?

๏ Senior Software Engineer @ Red Hat๏ TorqueBox core developer๏ Part of the project:odd team๏ Open source contributor

Lance Ball

Friday, April 27, 12

Page 4: Complex Made Simple: Sleep Better With TorqueBox

Scenario

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

Friday, April 27, 12

Page 5: Complex Made Simple: Sleep Better With TorqueBox

Ruby AppRails

Rack

Sinatra

Apache/Nginx

Passenger/Thin

Friday, April 27, 12

Page 6: Complex Made Simple: Sleep Better With TorqueBox

But...

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

Friday, April 27, 12

Page 7: Complex Made Simple: Sleep Better With TorqueBox

Eventual Complexity

Friday, April 27, 12

Page 8: Complex Made Simple: Sleep Better With TorqueBox

Ruby AppRails

Rack

Sinatra

Apache/Nginx

Passenger/ThinResque/

DelayedJob

Tasks

Friday, April 27, 12

Page 9: Complex Made Simple: Sleep Better With TorqueBox

Ruby AppRails

Rack

Sinatra

Apache/Nginx

Passenger/Thin

crond

JobsResque/

DelayedJob

Tasks

Friday, April 27, 12

Page 10: Complex Made Simple: Sleep Better With TorqueBox

Ruby AppRails

Rack

Sinatra

Apache/Nginx

Passenger/Thin

crond

JobsResque/

DelayedJob

Tasks

god/monit

Daemons

Friday, April 27, 12

Page 11: Complex Made Simple: Sleep Better With TorqueBox

Deploy Continuum

Friday, April 27, 12

Page 12: Complex Made Simple: Sleep Better With TorqueBox

Deploy Continuum

Friday, April 27, 12

Page 13: Complex Made Simple: Sleep Better With TorqueBox

Deploy Continuum

Friday, April 27, 12

Page 14: Complex Made Simple: Sleep Better With TorqueBox

What is TorqueBox?

TorqueBox is a Ruby Application Server.

Based on JRuby and JBoss AS7.

Friday, April 27, 12

Page 15: Complex Made Simple: Sleep Better With TorqueBox

Rails

Rack

Sinatra

ProcsTasks DaemonsJobs

HAClustering Load Balancing

JBoss ASWeb Messaging Scheduling Services

TorqueBox AS

Friday, April 27, 12

Page 16: Complex Made Simple: Sleep Better With TorqueBox

Roll your own

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

Friday, April 27, 12

Page 17: Complex Made Simple: Sleep Better With TorqueBox

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

Friday, April 27, 12

Page 18: Complex Made Simple: Sleep Better With TorqueBox

Or outsource some...

Friday, April 27, 12

Page 19: 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

Friday, April 27, 12

Page 20: Complex Made Simple: Sleep Better With TorqueBox

Use a Paas

Outsource everything but your app.

Friday, April 27, 12

Page 21: 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

Friday, April 27, 12

Page 22: 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

Friday, April 27, 12

Page 23: Complex Made Simple: Sleep Better With TorqueBox

Case Study!

Friday, April 27, 12

Page 24: Complex Made Simple: Sleep Better With TorqueBox

Appalachian Sustainable Agriculture Project (ASAP)

Friday, April 27, 12

Page 25: 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

Friday, April 27, 12

Page 26: Complex Made Simple: Sleep Better With TorqueBox

As deployed on Heroku

Friday, April 27, 12

Page 27: 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.

Friday, April 27, 12

Page 28: Complex Made Simple: Sleep Better With TorqueBox

Install

$ rvm install jruby-1.6.7$ rvm use jruby-1.6.7$ gem install torquebox-server

Friday, April 27, 12

Page 29: Complex Made Simple: Sleep Better With TorqueBox

Templatize

$ torquebox rails myapp

Friday, April 27, 12

Page 30: Complex Made Simple: Sleep Better With TorqueBox

torquebox.rb template

๏ torquebox-* and activerecord-jdbc-adapter gems

๏ torquebox-rake-support๏ Directories for services, jobs, etc๏ Web session store๏ Rails.cache with TorqueBox๏ Background jobs

Friday, April 27, 12

Page 31: Complex Made Simple: Sleep Better With TorqueBox

“Porting” the application

Friday, April 27, 12

Page 32: Complex Made Simple: Sleep Better With TorqueBox

Background Jobs

Friday, April 27, 12

Page 33: Complex Made Simple: Sleep Better With TorqueBox

Delayed::Job

App uses Delayed::Job

Replace with TorqueBox Backgroundable

Friday, April 27, 12

Page 34: 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

Friday, April 27, 12

Page 35: 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

job = ExcelExportJob.new job.excel_export_id = @export.id Delayed::Job.enqueue job

Friday, April 27, 12

Page 36: 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

Friday, April 27, 12

Page 37: Complex Made Simple: Sleep Better With TorqueBox

excel_export.rb

Delayed Job

class ExcelExport < ActiveRecord::Base  def generate_report    begin      set_status 'Processing'      spreadsheet = Spreadsheet.new(self.businesses)       spreadsheet.write_workbook self.workbook_file      set_status 'Storing on S3'      File.open(self.workbook_file) {|out|self.output = out}          File.delete(self.workbook_file)          set_status 'Complete'    rescue      set_status 'Export Error'    end  endend

Friday, April 27, 12

Page 38: Complex Made Simple: Sleep Better With TorqueBox

Delayed Job

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

Friday, April 27, 12

Page 39: Complex Made Simple: Sleep Better With TorqueBox

Delayed::Job

Exporter < AR::Base

ExportJob < Struct

Database

Worker

Friday, April 27, 12

Page 40: Complex Made Simple: Sleep Better With TorqueBox

That's pretty explicit

TorqueBox allows you to very easily run methods asynchronously.

Friday, April 27, 12

Page 41: 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  

Friday, April 27, 12

Page 42: 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  

  always_background :generate_report

Friday, April 27, 12

Page 43: 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

Friday, April 27, 12

Page 44: 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

@export.generate_report

Friday, April 27, 12

Page 45: Complex Made Simple: Sleep Better With TorqueBox

$ git rm excel_export_job.rb

excel_export_job.rb

Backgroundable

Kill it!

Friday, April 27, 12

Page 46: Complex Made Simple: Sleep Better With TorqueBox

Backgroundable

Exporter < AR::Base

ExportJob < Struct

Database

Worker

Queue Processor

Implicit!magic!

Friday, April 27, 12

Page 47: Complex Made Simple: Sleep Better With TorqueBox

Caching

Friday, April 27, 12

Page 48: Complex Made Simple: Sleep Better With TorqueBox

Caching

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

Friday, April 27, 12

Page 49: Complex Made Simple: Sleep Better With TorqueBox

No more memcached!

Friday, April 27, 12

Page 50: Complex Made Simple: Sleep Better With TorqueBox

cache = TorqueBox::Infinispan::Cache.newcache.put(“something”, anything)cache.get(“something”)

Cache

Friday, April 27, 12

Page 51: Complex Made Simple: Sleep Better With TorqueBox

cron0 0 2 * * ?/WTF??

Friday, April 27, 12

Page 52: Complex Made Simple: Sleep Better With TorqueBox

Heroku Cron

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

Friday, April 27, 12

Page 53: Complex Made Simple: Sleep Better With TorqueBox

Rakefile

Heroku Cron

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

Friday, April 27, 12

Page 54: Complex Made Simple: Sleep Better With TorqueBox

Scheduled Jobs

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

Friday, April 27, 12

Page 55: Complex Made Simple: Sleep Better With TorqueBox

refresh_trip_planner.rb

Straight-forward

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

Friday, April 27, 12

Page 56: Complex Made Simple: Sleep Better With TorqueBox

torquebox.yml

Configuration

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

Friday, April 27, 12

Page 57: Complex Made Simple: Sleep Better With TorqueBox

But...

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

Friday, April 27, 12

Page 58: Complex Made Simple: Sleep Better With TorqueBox

Services

Friday, April 27, 12

Page 59: Complex Made Simple: Sleep Better With TorqueBox

TorqueBox Services

๏Avoid the huge query๏Keep data more fresher

Friday, April 27, 12

Page 60: Complex Made Simple: Sleep Better With TorqueBox

trip_planner_service.rb

Keep it fresher class 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

Friday, April 27, 12

Page 61: 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

Friday, April 27, 12

Page 62: 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

Friday, April 27, 12

Page 63: 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

Friday, April 27, 12

Page 64: 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 )

Friday, April 27, 12

Page 65: Complex Made Simple: Sleep Better With TorqueBox

Queue, Service, Cache

Non-blocking

Service

Cache

ActiveRecord

Business

Queue

Friday, April 27, 12

Page 66: Complex Made Simple: Sleep Better With TorqueBox

Production!

Friday, April 27, 12

Page 67: Complex Made Simple: Sleep Better With TorqueBox

(Remember, I work for Red Hat)

Friday, April 27, 12

Page 68: Complex Made Simple: Sleep Better With TorqueBox

Set up the server

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

Friday, April 27, 12

Page 69: Complex Made Simple: Sleep Better With TorqueBox

Launch on boot

Friday, April 27, 12

Page 70: Complex Made Simple: Sleep Better With TorqueBox

init.d

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

Friday, April 27, 12

Page 71: 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

Friday, April 27, 12

Page 72: Complex Made Simple: Sleep Better With TorqueBox

Load Balance with mod_cluster

Friday, April 27, 12

Page 73: 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

Friday, April 27, 12

Page 74: 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>

Friday, April 27, 12

Page 75: Complex Made Simple: Sleep Better With TorqueBox

Deploy with Capistrano

Friday, April 27, 12

Page 76: Complex Made Simple: Sleep Better With TorqueBox

Capistrano

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

Friday, April 27, 12

Page 77: 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

Friday, April 27, 12

Page 78: 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.

Friday, April 27, 12

Page 79: Complex Made Simple: Sleep Better With TorqueBox

Can we go further?

Friday, April 27, 12

Page 80: Complex Made Simple: Sleep Better With TorqueBox

What's a PaaS?

Application

Queues

DB Email

Cache Jobs

Friday, April 27, 12

Page 81: Complex Made Simple: Sleep Better With TorqueBox

OPENSHIFT

http://openshift.redhat.comhttps://github.com/torquebox/torquebox-openshift-express

Friday, April 27, 12

Page 82: Complex Made Simple: Sleep Better With TorqueBox

Roadmap & Status

๏Current 2.0.1๏Continued Red Hat investment๏ Interop with other languages, such as Clojure via Immutant

Friday, April 27, 12

Page 83: Complex Made Simple: Sleep Better With TorqueBox

Resources

http://torquebox.org/

@torquebox on Twitter

#torquebox on IRC

Friday, April 27, 12

Page 84: Complex Made Simple: Sleep Better With TorqueBox

Question everything.

Friday, April 27, 12

Page 85: Complex Made Simple: Sleep Better With TorqueBox

Creative Commons BY-SA 3.0

Friday, April 27, 12