Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Torquebox Asheville.rb April 2011

1,798 views

Published on

I gave a presentation about TorqueBox last night at Asheville.rb. These are my slides.

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Torquebox Asheville.rb April 2011

  1. 1. Lance Ball Asheville.rbCreative Commons BY-SA 3.0 April 2011
  2. 2. whoami•@lanceball•> Java?C > C++ > Java > Ruby Perl >•Red Hat Senior Engineer•member of
  3. 3. GoalFor you to write a Rubyapp on TorqueBoxtonight!
  4. 4. TorqueBoxthe power of JBoss with the expressiveness of Ruby
  5. 5. TorqueBox: what?•A “real” app server for Ruby•Founded in 2008•100% open-source, LGPL license•Based on JBoss AS and JRuby•Just released 1.0.0.CR2!
  6. 6. Yes, its Java
  7. 7. I promise...•No XML•No Java *•No war files *•Only Ruby and YAML* Unless you really want to
  8. 8. TorqueBox::Why• Native support for Rack apps + standalone Ruby services• Built-in: • background processing • scheduling • daemons / services • clustering• Easily scalable• Optionally enterprisey (JAAS, legacy Java, etc.)
  9. 9. JRubya good idea done well
  10. 10. JRuby: why?•Very fast runtime•Real threads•Java libraries•Java tools•Healthy community
  11. 11. JBoss ASthe good parts
  12. 12. The CompetitionUnicorn, Thin, Passenger,Trinidad, Warbler......all address only the webquestion.
  13. 13. AS = Application Server•interpreter” server + Not just “web•appshost multiple, disparate Can simultaneously•apps it hosts services to all the Provides basic
  14. 14. JBoss AS6•Tomcat for web•Infinispan for caching•HornetQ for messaging•Quartz for scheduling•PicketBox for authentication•mod_cluster for clustering
  15. 15. Setting Up TorqueBox in a few simple steps!
  16. 16. Easy Install(download 1.0.0.CR2 from torquebox.org)$ unzip torquebox-dist-1.0.0.CR2-bin.zip$ export TORQUEBOX_HOME=$PWD/torquebox-1*$ export JBOSS_HOME=$TORQUEBOX_HOME/jboss$ export JRUBY_HOME=$TORQUEBOX_HOME/jruby$ export PATH=$JRUBY_HOME/bin:$PATH
  17. 17. Easy Install(download 1.0.0.CR2 from torquebox.org)$ unzip torquebox-dist-1.0.0.CR1-bin.zip$ export TORQUEBOX_HOME=$PWD/torquebox-1*$ export JBOSS_HOME=$TORQUEBOX_HOME/jboss$ export JRUBY_HOME=$TORQUEBOX_HOME/jruby$ export PATH=$JRUBY_HOME/bin:$PATH
  18. 18. Easy Install(download 1.0.0.CR2 from torquebox.org)$ unzip torquebox-dist-1.0.0.CR2-bin.zip$ export TORQUEBOX_HOME=$PWD/torquebox-1*$ export JBOSS_HOME=$TORQUEBOX_HOME/jboss$ export JRUBY_HOME=$TORQUEBOX_HOME/jruby$ export PATH=$JRUBY_HOME/bin:$PATH
  19. 19. Easy Install(download 1.0.0.CR2 from torquebox.org)$ unzip torquebox-dist-1.0.0.CR2-bin.zip$ export TORQUEBOX_HOME=$PWD/torquebox-1*$ export JBOSS_HOME=$TORQUEBOX_HOME/jboss$ export JRUBY_HOME=$TORQUEBOX_HOME/jruby$ export PATH=$JRUBY_HOME/bin:$PATH
  20. 20. Easy Install(download 1.0.0.CR2 from torquebox.org)$ unzip torquebox-dist-1.0.0.CR1-bin.zip the jruby Make sure found in your path$ export TORQUEBOX_HOME=$PWD/torquebox-1* is in $JRUBY_HOME/$ export JBOSS_HOME=$TORQUEBOX_HOME/jboss$ export JRUBY_HOME=$TORQUEBOX_HOME/jruby$ export PATH=$JRUBY_HOME/bin:$PATH
  21. 21. Easy Install(download 1.0.0.CR2 from torquebox.org)$ unzip torquebox-dist-1.0.0.CR1-bin.zip the jruby Make sure found in your path$ export TORQUEBOX_HOME=$PWD/torquebox-1* is in $JRUBY_HOME/$ export JBOSS_HOME=$TORQUEBOX_HOME/jboss$ export JRUBY_HOME=$TORQUEBOX_HOME/jruby$ export PATH=$JRUBY_HOME/bin:$PATH
  22. 22. Easy Install$ jruby -S gem install torquebox --pre# optional$ jruby -S gem install bundler$ jruby -S gem install rails$ jruby -S gem install sinatra
  23. 23. Rake TasksRakefilerequire "torquebox-rake-support"
  24. 24. Database ConnectivityGemfilegem "activerecord-jdbc-adapter"gem "jdbc-postgres"# gem "jdbc-sqlite3"# gem "jdbc-mysql"
  25. 25. Rails Template•Adds TorqueBox rake tasks•Adds the JDBC sqlite3 gems•Adds TorqueBox session_store•Adds Backgroundable module
  26. 26. Rake Tasksrake torquebox:run Run TorqueBox serverrake torquebox:deploy[context_path] Deploy the app in the current directoryrake torquebox:undeploy Undeploy the app in the current directory
  27. 27. Rake TasksStart torquebox:run in its ownshell and leave it running.Instead of script/server orshotgun or thin or whateverelse, use torquebox:run.
  28. 28. Deployment Descriptors torquebox:deploy creates a deployment descriptor in the $TORQUEBOX_HOME/ apps/ directory
  29. 29. Hot Deployment $TORQUEBOX_HOME/apps/• anything added to apps/ will get deployed• anything removed from apps/ will get undeployed• anything updated in apps/ will get redeployed• TorqueBox deployers make JBoss grok YAML
  30. 30. Hot Deployment $TORQUEBOX_HOME/apps/ deployment•descriptors to anything added apps/ will get deployed• anything removed from apps/ will get undeployed• anything updated in apps/ will get redeployed• TorqueBox deployers make JBoss grok YAML
  31. 31. Hot Deployment $TORQUEBOX_HOME/apps/ deployment•descriptors to anything added apps/ will get deployed• anything removed from apps/ will get undeployed• anything updated in apps/ will get redeployed• TorqueBox deployers make JBoss grok YAML
  32. 32. Hot Deployment $TORQUEBOX_HOME/apps/ • anything added to apps/ will get deployed • anything removed from apps/ will get undeployedknob files (zip •archives) anything updated in apps/ will get redeployed • TorqueBox deployers make JBoss grok YAML
  33. 33. Hot Deployment $TORQUEBOX_HOME/apps/ • anything added to apps/ will get deployed • anything removed from apps/ will get undeployedknob files (zip •archives) anything updated in apps/ will get redeployed • TorqueBox deployers make JBoss grok YAML
  34. 34. Deployment Descriptorsapps/myapp-knob.ymlapplication: root: /path/to/myapp env: developmentweb: context: myapp host: www.yourhost.com static: publicenvironment: MAIL_HOST: mail.yourhost.com REPLY_TO: you@yourhost.com
  35. 35. Deployment Descriptorsapps/myapp-knob.ymlapplication: root: /path/to/myapp env: developmentweb: The fully-qualified context: myapp path to the app. host: www.yourhost.com static: public This will be theenvironment: value of either RAILS_ROOT or MAIL_HOST: mail.yourhost.com REPLY_TO: you@yourhost.com RACK_ROOT
  36. 36. Deployment Descriptorsapps/myapp-knob.ymlapplication: root: /path/to/myapp env: developmentweb: The fully-qualified context: myapp path to the app. host: www.yourhost.com static: public This will be theenvironment: value of either RAILS_ROOT or MAIL_HOST: mail.yourhost.com REPLY_TO: you@yourhost.com RACK_ROOT
  37. 37. Deployment Descriptorsapps/myapp-knob.ymlapplication: root: /path/to/myapp env: developmentweb: context: myapp The runtime mode host: www.yourhost.com the app. This of static: public will be eitherenvironment: RAILS_ENV or MAIL_HOST: mail.yourhost.com REPLY_TO: you@yourhost.com RACK_ENV
  38. 38. Deployment Descriptorsapps/myapp-knob.ymlapplication: root: /path/to/myapp env: developmentweb: context: myapp The runtime mode host: www.yourhost.com the app. This of static: public will be eitherenvironment: RAILS_ENV or MAIL_HOST: mail.yourhost.com REPLY_TO: you@yourhost.com RACK_ENV
  39. 39. Deployment Descriptors The app’s context path apps/myapp-knob.yml (or “sub URI”): http://localhost:8080/myappapplication: Can be set via rake: root: rake torquebox:deploy[myapp] /path/to/myapp env: development The default is root:web: http://localhost:8080/ context: myapp host: www.yourhost.com static: publicenvironment: MAIL_HOST: mail.yourhost.com REPLY_TO: you@yourhost.com
  40. 40. Deployment Descriptors The app’s context path apps/myapp-knob.yml (or “sub URI”): http://localhost:8080/myappapplication: Can be set via rake: root: rake torquebox:deploy[myapp] /path/to/myapp env: development The default is root:web: http://localhost:8080/ context: myapp host: www.yourhost.com static: publicenvironment: MAIL_HOST: mail.yourhost.com REPLY_TO: you@yourhost.com
  41. 41. Deployment Descriptorsapps/myapp-knob.ymlapplication: A list of virtual root: /path/to/myapp env: development hostnames toweb: which to bind the context: myapp host: www.yourhost.com static: publicenvironment: MAIL_HOST: mail.yourhost.com REPLY_TO: you@yourhost.com
  42. 42. Deployment Descriptorsapps/myapp-knob.ymlapplication: A list of virtual root: /path/to/myapp env: development hostnames toweb: which to bind the context: myapp host: www.yourhost.com static: publicenvironment: MAIL_HOST: mail.yourhost.com REPLY_TO: you@yourhost.com
  43. 43. Deployment Descriptorsapps/myapp-knob.ymlapplication: root: /path/to/myapp env: development The location ofweb: the app’s static context: myapp content, either host: www.yourhost.com static: public absolute orenvironment: relative to the MAIL_HOST: mail.yourhost.com REPLY_TO: you@yourhost.com
  44. 44. Deployment Descriptorsapps/myapp-knob.ymlapplication: root: /path/to/myapp env: development The location ofweb: the app’s static context: myapp content, either host: www.yourhost.com static: public absolute orenvironment: relative to the MAIL_HOST: mail.yourhost.com REPLY_TO: you@yourhost.com
  45. 45. Deployment Descriptorsapps/myapp-knob.ymlapplication: root: /path/to/myapp Any env: developmentweb: environment context: myapp variables host: www.yourhost.com static: publicenvironment: MAIL_HOST: mail.yourhost.com REPLY_TO: you@yourhost.com
  46. 46. Deployment Descriptorsapps/myapp-knob.ymlapplication: root: /path/to/myapp Any env: developmentweb: environment context: myapp variables host: www.yourhost.com static: publicenvironment: MAIL_HOST: mail.yourhost.com REPLY_TO: you@yourhost.com
  47. 47. Deployment Descriptors•config/torquebox.yml•internal descriptors have the same structure as the external ones in apps/•may be used to provide your own reasonable defaults
  48. 48. ComponentsPut em together, and you have an AS
  49. 49. Webmake rack, not war
  50. 50. jruby-rack •supported: rails, sinatra, etc All rack-based frameworks •deploy from where they apps No packaging required: sit on disk • No redeploy necessary to see changes when using rack reloading, shotgun or rails development mode • We use it inside Tomcat
  51. 51. Schedulingget regular later
  52. 52. Jobsapp/jobs/newsletter_sender.rbclass NewsletterSender   def run()    subscriptions = Subscription.find(:all)    subscriptions.each do |e|      send_newsletter( e )    end  end end
  53. 53. Jobsconfig/torquebox.ymljobs: monthly_newsletter: description: first of month job: NewsletterSender cron: ‘0 0 0 1 * ?’ process_tps_reports: job: TPSReportProcessor cron: ‘0 0 0 0 MON ?’
  54. 54. Jobs “Fire every half hour from 10am until 1pm on the third Friday of each month” 0 */30 10-13 ? * FRI#3Seconds Minutes Hours DOM Month DOW Year 1-7 1-12 1970- 1-31 SUN- 0-59 0-59 0-23 JAN- 2099 ?LW SAT DEC empty ?L#
  55. 55. Jobs•day ofportable. What is the first More the week on BSD again? What’s cron on Windows?• Self contained within the app. No external systems to manage and keep in sync.• Full application environment loaded and available.
  56. 56. Messaging asynchronicity
  57. 57. TorqueBox::Messaging• JMS (Java Message Service) is an API for messaging• HornetQ is the JBoss JMS implementation
  58. 58. Background Processing•Tasks•Backgroundable
  59. 59. Tasksapp/tasks/email_task.rbclass EmailTask < TorqueBox::Messaging::Task  def welcome(payload) person = Person.find_by_id(payload[:id])    person.send_welcome_spam if person  endend
  60. 60. Tasksapp/tasks/email_task.rbclass EmailTask < TorqueBox::Messaging::Task  def welcome(payload) person = Person.find_by_id(payload[:id])    person.send_welcome_spam if person  endend
  61. 61. Tasksapp/tasks/email_task.rbclass EmailTask < TorqueBox::Messaging::Task  def welcome(payload) person = Person.find_by_id(payload[:id])    person.send_welcome_spam if person  endend
  62. 62. Tasksapp/tasks/email_task.rbclass EmailTask < TorqueBox::Messaging::Task  def welcome(payload) person = Person.find_by_id(payload[:id])    person.send_welcome_spam if person  endend
  63. 63. Tasksapp/controllers/people_controller.rbclass PeopleController < ApplicationController  def create    @person = Person.new(params[:person])    respond_to do |format|      if @person.save        EmailTask.async(:welcome, :id => person.id)        # respond appropriately      end    end  endend
  64. 64. Tasksapp/controllers/people_controller.rbclass PeopleController < ApplicationController  def create    @person = Person.new(params[:person])    respond_to do |format|      if @person.save        EmailTask.async(:welcome, :id => person.id)        # respond appropriately      end    end  endend
  65. 65. BackgroundableInspired by DelayedJob’shandle_asynchronously,it’s trivial to createimplicit backgroundTasks.
  66. 66. Backgroundable lib/something.rbinclude TorqueBox::Messagingclass WelcomeEmailer include Backgroundable always_background :welcome def welcome(id) person = Person.find_by_id(id)    person.send_welcome_spam if person  end def depart(id) # do something else endend...@emailer.welcome(an_id)@something.background.depart(an_id)
  67. 67. Backgroundable lib/something.rbinclude TorqueBox::Messagingclass WelcomeEmailer include Backgroundable always_background :welcome def welcome(id) person = Person.find_by_id(id)    person.send_welcome_spam if person  end def depart(id) # do something else endend...@emailer.welcome(an_id)@something.background.depart(an_id)
  68. 68. Backgroundable lib/something.rbinclude TorqueBox::Messagingclass WelcomeEmailer include Backgroundable always_background :welcome def welcome(id) person = Person.find_by_id(id)    person.send_welcome_spam if person  end def depart(id) # do something else endend...@emailer.welcome(an_id)@something.background.depart(an_id)
  69. 69. Backgroundable lib/something.rbinclude TorqueBox::Messagingclass WelcomeEmailer include Backgroundable always_background :welcome def welcome(id) person = Person.find_by_id(id)    person.send_welcome_spam if person  end def depart(id) # do something else endend...@emailer.welcome(an_id)@something.background.depart(an_id)
  70. 70. Background Processing Call it from your controllers, models, and observers, or even other tasks. Even in non-Rails apps!
  71. 71. Background Processing•No extra tables in your database•No external system to manage•Little to no config required at all•System gets redeployed w/app•Efficient loading of rails environment•Automatic load balancing and retries•Works on Windows, if you care
  72. 72. QueuesTasks and Backgroundable arebuilt on top of Queues. Ofcourse, you may build yourown messaging based apps bydefining your own Queues,Topics, and their messageProcessors yourself.
  73. 73. Queuesconfig/torquebox.ymlqueues: /queues/questions:/queues/answers: durable: false
  74. 74. Topics•interface is different, but behavior is the same.•each message, of a only one all subscribers but topic see subscriber will see any message from a queue• use topics: section of torquebox.yml to define topics
  75. 75. ProcessorsYou can create aprocessor class toreceive messages from aTopic or Queue
  76. 76. Processorsapp/models/print_handler.rbinclude TorqueBox::Messagingclass PrintHandler < MessageProcessor def initialize(opts)    @printer = opts[printer] || default  end  def on_message(body)    puts "Processing #{body} of #{message}"  endend
  77. 77. Processorsconfig/torquebox.ymlmessaging: /topics/orders: - PrintHandler - ShoutHandler /queues/receipts: PrintHandler: concurrency: 5 config: printer: the_little_one
  78. 78. Processorsconfig/torquebox.ymlmessaging: /topics/orders: - PrintHandler - ShoutHandler /queues/receipts: PrintHandler: concurrency: 5 config: printer: the_little_one
  79. 79. Processorsconfig/torquebox.ymlmessaging: /topics/orders: - PrintHandler - ShoutHandler /queues/receipts: PrintHandler: concurrency: 5 config: printer: the_little_one
  80. 80. Processorsconfig/torquebox.ymlmessaging: /topics/orders: - PrintHandler - ShoutHandler /queues/receipts: PrintHandler: concurrency: 5 config: printer: the_little_one
  81. 81. Processorsapp/models/print_handler.rbinclude TorqueBox::Messagingclass PrintHandler < MessageProcessor def initialize(opts)    @printer = opts[printer] || default  end  def on_message(body)    puts "Processing #{body} of #{message}"  endend
  82. 82. Queues (again)But how do you send amessage?
  83. 83. Queuescontrived examplequestions = Queue.new(/queues/questions)answers = Queue.new(/queues/answers) Thread.new do  questions.publish "What time is it?"  puts answers.receive( :timeout => 1000 )end puts questions.receiveanswers.publish Time.now
  84. 84. Queuescontrived examplequestions = Queue.new(/queues/questions)answers = Queue.new(/queues/answers) Thread.new do  questions.publish "What time is it?"  puts answers.receive( :timeout => 1000 )end puts questions.receiveanswers.publish Time.now
  85. 85. Queuescontrived examplequestions = Queue.new(/queues/questions)answers = Queue.new(/queues/answers) Thread.new do  questions.publish "What time is it?"  puts answers.receive( :timeout => 1000 )end puts questions.receiveanswers.publish Time.now
  86. 86. Queuescontrived examplequestions = Queue.new(/queues/questions)answers = Queue.new(/queues/answers) Thread.new do  questions.publish "What time is it?"  puts answers.receive( :timeout => 1000 )end puts questions.receiveanswers.publish Time.now
  87. 87. Servicesrun along, lil’ daemon
  88. 88. ServicesLong-running, non-web“daemons” that sharethe runtime environmentand deployment lifecycleof your app.
  89. 89. Services•optional initialize(Hash), start() Represented as a class with and stop() methods, which should each return quickly.• Typically will start a long- running loop in a thread and respond to external events.• Configured via services: section in torquebox.yml
  90. 90. Servicesconfig/torquebox.ymlservices: TimeMachine: queue: /queue/morris_day MyMudServer: SomeOtherService:
  91. 91. Services app/services/time_machine.rbclass TimeMachine def initialize(opts) @queue = Queue.new(opts[queue]) end def start Thread.new do until @done @queue.publish(Time.now) sleep(1) end end end def stop; @done = true; endend
  92. 92. Services app/services/time_machine.rbclass TimeMachine def initialize(opts) @queue = Queue.new(opts[queue]) end def start Thread.new do until @done @queue.publish(Time.now) sleep(1) end end end def stop; @done = true; endend
  93. 93. Services app/services/time_machine.rbclass TimeMachine def initialize(opts) @queue = Queue.new(opts[queue]) end def start Thread.new do until @done @queue.publish(Time.now) sleep(1) end end end def stop; @done = true; endend
  94. 94. Services app/services/time_machine.rbclass TimeMachine def initialize(opts) @queue = Queue.new(opts[queue]) end def start Thread.new do until @done @queue.publish(Time.now) sleep(1) end end end def stop; @done = true; endend
  95. 95. Cachingsave a little for later
  96. 96. Cachingconfig/application.rbconfig.cache_store =:torque_box_store, :mode => :local# orconfig.cache_store =ActiveSupport::Cache::TorqueBoxStore.new( :mode=> :local )
  97. 97. Runtime Options shorts or sweats?
  98. 98. Runtime Optionsconfig/torquebox.yml#per app!ruby: version: 1.9 compile_mode: jit
  99. 99. Clusteringless failure faster
  100. 100. Web•session replication•mod_cluster) intelligent load-balancing (via•failover (via mod_cluster)
  101. 101. MessagingHornetQ clustersautomatically, giving youmessage processingcapability that growswith the cluster.
  102. 102. ServicesA service runs on everycluster node, unlessmarked as a singleton.
  103. 103. JobsA job runs on everycluster node, unlessmarked as a singleton(just like services).
  104. 104. CachingInfinispan clustersautomatically,"distributing" yourcache.
  105. 105. BENchmarksReal-world Rails application:RedmineComparisons:TorqueBox, Trinidad, Passenger,Unicorn, Glassfish, ThinRuntimes:JRuby, MRI, RubyEE
  106. 106. RoadmapMay - 1.0.0.FinalThen... AS7 Authentication Mobicents ??? - you tell us
  107. 107. Resources•http://torquebox.org•irc: #torquebox on freenode•https://github.com/torquebox•http://twitter.com/torquebox
  108. 108. Thanks!questions?

×