Crank Up Your Apps With                                                           Jim Crossley                            ...
Jim  who?• “recovering  java  architect”• java  since  ’96,  ruby  since  ’06• emacs  and  guitars  since  forever• Red  H...
3
Bob  McWhirter                 4
Agenda • High-­level  BS  and  Development     Process • Web,  Messaging,  Scheduling,     Services,  Clustering          ...
TorqueBoxthe power of JBoss with the expressiveness of Ruby                                                     6
TorqueBox:  what?• A  “real”  app  server  for  Ruby• Founded  in  2008• Bob’s  “labor  of  love”• 100%  open-­source,  LG...
TorqueBox:  why?• “Native”  support  for  Rack  apps• Built-­in  background  processing• Built-­in  scheduling• Built-­in ...
JRubya good idea done well                        9
JRuby:  why?• Very  fast  runtime• Real  threads• Java  libraries• Java  tools• Healthy  community                        10
JRuby:  why  not?• Slower  start  up• Native  gems • FFI • C  extension  support• Some  Ruby  libs  not  thread-­safe     ...
JBoss  ASbut before we get to that...                               12
Enterprise  Java   misconceptions                    13
Is itScary?         14
Acronymious? WAR      JAXBEAR JSTL SLSB JSF JNLPJTA JPA   JNI JCK  JAX-­RPC JDOM JAXP JAX-­WS  JSE JEE JMM JTS        JWS ...
Bloated?           16
Bewildering?               17
Enterprise  Java  is  all  that        and more! but...                                  18
I  promise...• No  XML  • No  Java  *• No  war  files  *• Only  Ruby,  YAML  and...* Unless you really want to            ...
JBoss  ASthe enterprisey good parts                             20
JBoss  AS6• Tomcat  for  web• Infinispan  for  caching• HornetQ  for  messaging• Quartz  for  scheduling• mod_cluster  for...
AS  =  Application  Server• Not  just  “web  server  +  interpreter”• More  like  initd  than  httpd• Can  host  multiple,...
Hot  Deployment    $JBOSS_HOME/server/default/deploy/•   anything  added  to  deploy/      will  get  deployed•   anything...
Hot  Deployment    $JBOSS_HOME/server/default/deploy/•           deployment      anything  added  to  deploy/      will  g...
Hot  Deployment    $JBOSS_HOME/server/default/deploy/•   anything  added  to  deploy/      will  get  deployed•   anything...
Development  Process    how do they work?                        26
easy  install$  wget  http://torquebox.org/torquebox-­dev.zip$  unzip  torquebox-­dev.zip$  export  TORQUEBOX_HOME=$PWD/to...
easy  install$  wget  http://torquebox.org/torquebox-­dev.zip$  unzip  torquebox-­dev.zip$  export  TORQUEBOX_HOME=$PWD/to...
easy  install$  wget  http://torquebox.org/torquebox-­dev.zip$  unzip  torquebox-­dev.zip$  export  TORQUEBOX_HOME=$PWD/to...
easy  install$  wget  http://torquebox.org/torquebox-­dev.zip$  unzip  torquebox-­dev.zip Make  sure  the  jruby          ...
easy  install$  jruby  -­S  gem  install  bundler$  jruby  -­S  gem  install  rails$  jruby  -­S  gem  install  sinatra   ...
rake  tasksRakefilerequire  "org.torquebox.rake-­support"                                         32
rake  tasksrake  torquebox:run        Run  TorqueBox  serverrake  torquebox:deploy[context_path]        Deploy  the  app  ...
rake  tasks Start  torquebox:run  in  its  own   shell  and  leave  it  running.  Instead   of  script/server  or  shotgun...
deployment  descriptors torquebox:deploy  creates   a  deployment  descriptor  in  the   JBoss  deploy/  directory        ...
deployment  descriptorsdeploy/myapp-­{rails,rack}.ymlapplication:  root:    /path/to/myapp  env:     developmentweb:  cont...
deployment  descriptorsdeploy/myapp-­{rails,rack}.ymlapplication:  root:    /path/to/myapp  env:     developmentweb:  cont...
deployment  descriptorsdeploy/myapp-­{rails,rack}.ymlapplication:  root:    /path/to/myapp  env:     developmentweb:  cont...
deployment  descriptors                        The  app’s  context  path   deploy/myapp-­{rails,rack}.yml                 ...
deployment  descriptorsdeploy/myapp-­{rails,rack}.ymlapplication:  root:    /path/to/myapp      A  list  of  virtual    en...
deployment  descriptorsdeploy/myapp-­{rails,rack}.ymlapplication:  root:    /path/to/myapp  env:     developmentweb:      ...
deployment  descriptorsdeploy/myapp-­{rails,rack}.ymlapplication:  root:    /path/to/myapp  env:     developmentweb:      ...
deployment  descriptorsdeploy/myapp-­{rails,rack}.ymlapplication:  root:    /path/to/myapp  env:     development      Any ...
deployment  descriptors•   config/torquebox.yml  •   internal  descriptors  have  the      same  structure  as  the      e...
Webmake rack, not war                     45
jruby-­rack• All  rack-­based  frameworks    supported:  rails,  sinatra,  etc• No  packaging  required:  apps  deploy    ...
database  connectivityGemfilegem  "activerecord-­jdbc-­adapter"gem  "jdbc-­postgres"#  gem  "jdbc-­sqlite3"#  gem  "jdbc-­...
rails  template• Adds  TorqueBox  rake  tasks• Adds  the  JDBC  sqlite3  gems• Adds  TorqueBox  session_store• Adds  Backg...
my  first  rails  app$  jruby  -­S  rails  new  myapp  -­m          $TORQUEBOX_HOME/share/rails/template.rb$  cd  myapp$  ...
Messaging asynchronicity                  50
lots  of  optionsRabbitMQ     Resque      cron       BackgroundDRb                            workling      CronEdit      ...
TorqueBox::Messaging• JMS  (Java  Message  Service)    is  an  API  for  messaging• implementation  HornetQ  is  the  JBos...
TorqueBox::Messaging•   Task•   Backgroundable•   MessageProcessor•   Queue•   Topic                       53
TorqueBox::Messaging• No  extra  tables  in  your  database• No  external  system  to  manage• Little  to  no  config  req...
Tasksapp/tasks/email_task.rbclass  EmailTask  <  TorqueBox::Messaging::Task    def  welcome(payload)        person  =  pay...
Tasksapp/tasks/email_task.rbclass  EmailTask  <  TorqueBox::Messaging::Task    def  welcome(payload)        person  =  pay...
Tasksapp/tasks/email_task.rbclass  EmailTask  <  TorqueBox::Messaging::Task    def  welcome(payload)        person  =  pay...
Tasksapp/tasks/email_task.rbclass  EmailTask  <  TorqueBox::Messaging::Task    def  welcome(payload)        person  =  pay...
Tasksapp/tasks/email_task.rbclass  EmailTask  <  TorqueBox::Messaging::Task    def  welcome(payload)        person  =  pay...
Tasksapp/controllers/people_controller.rbclass  PeopleController  <  ApplicationController    def  create        @person  ...
Tasksapp/controllers/people_controller.rbclass  PeopleController  <  ApplicationController    def  create        @person  ...
TasksCall  them  from  your  controllers,  models,  and  observers,  or  even  other  tasks.  Even  in  non-­Rails  apps! ...
BackgroundableInspired  by  DelayedJob’s  handle_asynchronously,  it’s  trivial  to  create  implicit  background  Tasks. ...
Backgroundablelib/something.rbinclude  TorqueBox::Messaging  class  Something    include  Backgroundable    always_backgro...
Backgroundablelib/something.rbinclude  TorqueBox::Messaging  class  Something    include  Backgroundable    always_backgro...
Backgroundablelib/something.rbinclude  TorqueBox::Messaging  class  Something    include  Backgroundable    always_backgro...
Backgroundablelib/something.rbinclude  TorqueBox::Messaging  class  Something    include  Backgroundable    always_backgro...
Backgroundableapp/models/slow_poke.rbclass  SlowPoke  <  ActiveRecord::Base    def  takes_forever;;  end    def  might_tak...
QueuesTasks  are  built  on  top  of  Queues.    Of  course,  you  may  build  your  own  “MOM”  apps  by  defining  your ...
Queuesconfig/queues.yml/queues/questions:/queues/answers:    durable:  false                      70
ProcessorsYou  can  create  a  processor  class  to  receive  messages  from  a  Topic  or  Queue                         ...
Processorsconfig/messaging.yml/topics/print: PrintHandler/queues/popular:  - PopularHandler  - AdultObserver:      filter:...
Processorsconfig/messaging.yml/topics/print: PrintHandler/queues/popular:  - PopularHandler  - AdultObserver:      filter:...
Processorsconfig/messaging.yml/topics/print: PrintHandler/queues/popular:  - PopularHandler  - AdultObserver:      filter:...
Processorsconfig/messaging.yml/topics/print: PrintHandler/queues/popular:  - PopularHandler  - AdultObserver:      filter:...
Processorsapp/models/print_handler.rbinclude  TorqueBox::Messagingclass  PrintHandler  <  MessageProcessor    def  on_mess...
Queues  (again) But  how  do  you  send  a   message?                                77
Queuesexampleinclude  TorqueBoxreq  =  Messaging::Queue.new  /queues/questionsres  =  Messaging::Queue.new  /queues/answer...
Queuesexampleinclude  TorqueBoxreq  =  Messaging::Queue.new  /queues/questionsres  =  Messaging::Queue.new  /queues/answer...
Queuesexampleinclude  TorqueBoxreq  =  Messaging::Queue.new  /queues/questionsres  =  Messaging::Queue.new  /queues/answer...
Queuesexampleinclude  TorqueBoxreq  =  Messaging::Queue.new  /queues/questionsres  =  Messaging::Queue.new  /queues/answer...
Queues“on  the  fly”include  TorqueBoxqueue  =  Messaging::Queue.new  /queues/fooqueue.create    ...  queue.destroy       ...
Topics• behavior  is  different,  but  interface  is    the  same.• all  subscribers  of  a  topic  see  each    message, ...
Schedulingget regular later                    84
Jobsapp/jobs/newsletter_sender.rbclass  NewsletterSender      def  run()        subscriptions  =  Subscription.find(:all) ...
Jobsconfig/jobs.ymlmonthly_newsletter:    description:  first  of  month    job:  NewsletterSender    cron:  ‘0  0  0  1  ...
Jobs “Fire  every  half  hour  from  10am  until  1pm       on  the  third  Friday  of  each  month”  0      */30 10-13   ...
Jobs• More  portable.  What  is  the  first  day    of  the  week  on  BSD  again?    What’s      cron  on  Windows?•   Se...
Servicesrun along, lil’ daemon                         89
ServicesLong-­running,  non-­web  “daemons”  that  share  the  runtime  environment  and  deployment  lifecycle  of  your ...
Services• Represented  as  a  class  with    optional  initialize(Hash),      start()  and  stop()  methods,      which  s...
Servicesconfig/services.ymlIrcBot:    server:  freenode.net    channel:  #torquebox    publish:  /topics/ircMyMudServer:So...
Servicesapp/{models,etc}/my_service.rbclass  MyService    def  initialize  opts={}        name  =  opts[:publish]        @...
Servicesapp/{models,etc}/my_service.rbclass  MyService    def  initialize  opts={}        name  =  opts[:publish]        @...
Servicesapp/{models,etc}/my_service.rbclass  MyService    def  initialize  opts={}        name  =  opts[:publish]        @...
Servicesapp/{models,etc}/my_service.rbclass  MyService    def  initialize  opts={}        name  =  opts[:publish]        @...
Servicesapp/{models,etc}/my_service.rbclass  MyService    def  run        until  @done            @queue.publish(Time.now)...
Servicesapp/{models,etc}/my_service.rbclass  MyService    def  run        until  @done            @queue.publish(Time.now)...
Servicesapp/services/evented_service.rbclass  EventedService    def  initialize  opts={}        @opts  =  opts    end    d...
Clusteringless failure faster                      100
out-­of-­the-­box• JBoss  provides • session  replication • load-­balanced  messaging• mod_cluster  provides • session  af...
JBOSS_CONFTorqueBox  ships  with  two  JBoss  server  configurations:  default  (not  clustered)  and  all  (clustered).  ...
deploy  and  run$  export  JBOSS_CONF=all$  jruby  -­S  rake  torquebox:deploy$  jruby  -­S  rake  torquebox:run          ...
mod_clusterA  reverse  proxy  implemented  as  an  Apache  module  with  JBoss  awareness.  Constantly  gathers  load  sta...
mod_cluster              105
mod_cluster• Dynamic  configuration• Server-­side  load  factor  calculation• Fine-­grained  web  app  lifecycle• AJP  (Ap...
Futurecoming soon              107
Future• Performance  benchmarking  and    optimization• Infinispan  for  ActiveSupport::Cache    and  NoSQL  persistence• ...
Resources• http://torquebox.org• #torquebox  on  freenode• https://github.com/torquebox• http://twitter.com/torquebox• htt...
Thanks!questions?             110
Upcoming SlideShare
Loading in...5
×

Crank Up Your Apps With TorqueBox

4,748

Published on

Presentation by Jim Crossley at Magic Ruby 2011

0 Comments
7 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
4,748
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
32
Comments
0
Likes
7
Embeds 0
No embeds

No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • easy JEE integration\nreplacement for JSF\n
  • \n
  • Can also apply ruby tools, e.g. Cucumber and RSpec, to java.\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Hot deployment, clustering, caching, messaging, scheduling, transactions, lifecycle management, etc.\n
  • \n
  • \n
  • \n
  • \n
  • Ensure you have Java 6 installed\n
  • Ensure you have Java 6 installed\n
  • Ensure you have Java 6 installed\n
  • Ensure you have Java 6 installed\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Not imposing JEE arbitrary packaging conventions on ruby just to enjoy the JEE services.\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Or integrate with a legacy Java app through its queues.\n
  • \n
  • \n
  • destinations on the left, processors on the right!\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Ruby messages being Base64-encoded over JMS String-type messages\n
  • \n
  • \n
  • \n
  • \n
  • Should reside beneath app/jobs\nOnly a run() method is required\n
  • \n
  • \n
  • The last day of the month\nThe last weekday of the month\nThe weekday closest to the 15th\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Recent articles posted on torquebox.org detailing clustering config\n
  • reverse proxy / load balancer\n
  • \n
  • \n
  • \n
  • \n
  • As server nodes join and leave the cluster, the balancer (mod_cluster) is aware of these changes.\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • *.bat equivalents\nwindows service config\n
  • \n
  • \n
  • Crank Up Your Apps With TorqueBox

    1. 1. Crank Up Your Apps With Jim Crossley MagicRubyCreative  Commons  BY-­SA  3.0 Feb 2011 1
    2. 2. Jim  who?• “recovering  java  architect”• java  since  ’96,  ruby  since  ’06• emacs  and  guitars  since  forever• Red  Hat  Senior  Engineer  • proud  member  of 2
    3. 3. 3
    4. 4. Bob  McWhirter 4
    5. 5. Agenda • High-­level  BS  and  Development   Process • Web,  Messaging,  Scheduling,   Services,  Clustering 5
    6. 6. TorqueBoxthe power of JBoss with the expressiveness of Ruby 6
    7. 7. TorqueBox:  what?• A  “real”  app  server  for  Ruby• Founded  in  2008• Bob’s  “labor  of  love”• 100%  open-­source,  LGPL  license• Reflects  a  strong  commitment  to   Ruby  from  Red  Hat 7
    8. 8. TorqueBox:  why?• “Native”  support  for  Rack  apps• Built-­in  background  processing• Built-­in  scheduling• Built-­in  clustering• Easily  scalable• Optionally  enterprisey 8
    9. 9. JRubya good idea done well 9
    10. 10. JRuby:  why?• Very  fast  runtime• Real  threads• Java  libraries• Java  tools• Healthy  community 10
    11. 11. JRuby:  why  not?• Slower  start  up• Native  gems • FFI • C  extension  support• Some  Ruby  libs  not  thread-­safe 11
    12. 12. JBoss  ASbut before we get to that... 12
    13. 13. Enterprise  Java misconceptions 13
    14. 14. Is itScary? 14
    15. 15. Acronymious? WAR JAXBEAR JSTL SLSB JSF JNLPJTA JPA   JNI JCK JAX-­RPC JDOM JAXP JAX-­WS JSE JEE JMM JTS JWS NIO JDO AWT   JMX JLS JAR JRE JCP   JSR JNDI JSP SAF EJB JME POJOJMSJDBC   JDK JVM JAX-­RS JPQL NPE 15
    16. 16. Bloated? 16
    17. 17. Bewildering? 17
    18. 18. Enterprise  Java  is  all  that and more! but... 18
    19. 19. I  promise...• No  XML  • No  Java  *• No  war  files  *• Only  Ruby,  YAML  and...* Unless you really want to 19
    20. 20. JBoss  ASthe enterprisey good parts 20
    21. 21. JBoss  AS6• Tomcat  for  web• Infinispan  for  caching• HornetQ  for  messaging• Quartz  for  scheduling• mod_cluster  for  clustering 21
    22. 22. AS  =  Application  Server• Not  just  “web  server  +  interpreter”• More  like  initd  than  httpd• Can  host  multiple,  disparate  apps   simultaneously• Provides  basic  services  to  all  the   apps  it  hosts 22
    23. 23. Hot  Deployment $JBOSS_HOME/server/default/deploy/• anything  added  to  deploy/   will  get  deployed• anything  removed  from   deploy/  will  get   undeployed• anything  updated  in   deploy/  will  get  redeployed• TorqueBox  deployers   make  JBoss  grok  YAML   and  ruby  archives 23
    24. 24. Hot  Deployment $JBOSS_HOME/server/default/deploy/• deployment   anything  added  to  deploy/   will  get  deployed descriptors• anything  removed  from   deploy/  will  get   undeployed• anything  updated  in   deploy/  will  get  redeployed• TorqueBox  deployers   make  JBoss  grok  YAML   and  ruby  archives 24
    25. 25. Hot  Deployment $JBOSS_HOME/server/default/deploy/• anything  added  to  deploy/   will  get  deployed• anything  removed  from   deploy/  will  get   undeployed• anything  updated  in   zip  files   deploy/  will  get  redeployed• (archives) TorqueBox  deployers   make  JBoss  grok  YAML   and  ruby  archives 25
    26. 26. Development  Process how do they work? 26
    27. 27. easy  install$  wget  http://torquebox.org/torquebox-­dev.zip$  unzip  torquebox-­dev.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 27
    28. 28. easy  install$  wget  http://torquebox.org/torquebox-­dev.zip$  unzip  torquebox-­dev.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 28
    29. 29. easy  install$  wget  http://torquebox.org/torquebox-­dev.zip$  unzip  torquebox-­dev.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 29
    30. 30. easy  install$  wget  http://torquebox.org/torquebox-­dev.zip$  unzip  torquebox-­dev.zip Make  sure  the  jruby   found  in  your  path  is  in   $JRUBY_HOME/bin.$  export  TORQUEBOX_HOME=$PWD/torquebox-­1*$  export  JBOSS_HOME=$TORQUEBOX_HOME/jboss$  export  JRUBY_HOME=$TORQUEBOX_HOME/jruby$  export  PATH=$JRUBY_HOME/bin:$PATH 30
    31. 31. easy  install$  jruby  -­S  gem  install  bundler$  jruby  -­S  gem  install  rails$  jruby  -­S  gem  install  sinatra 31
    32. 32. rake  tasksRakefilerequire  "org.torquebox.rake-­support" 32
    33. 33. 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 33
    34. 34. rake  tasks Start  torquebox:run  in  its  own   shell  and  leave  it  running.  Instead   of  script/server  or  shotgun   or  thin  or  whatever  else,   use  torquebox:deploy. 34
    35. 35. deployment  descriptors torquebox:deploy  creates   a  deployment  descriptor  in  the   JBoss  deploy/  directory 35
    36. 36. deployment  descriptorsdeploy/myapp-­{rails,rack}.ymlapplication: root: /path/to/myapp env: developmentweb: context: myapp host: www.yourhost.com static: public rackup: config.ruenvironment: MAIL_HOST: mail.yourhost.com REPLY_TO: you@yourhost.com 36
    37. 37. deployment  descriptorsdeploy/myapp-­{rails,rack}.ymlapplication: root: /path/to/myapp env: developmentweb: context: myapp The  fully-­qualified   host: www.yourhost.com path  to  the  app.     static: public This  will  be  the  value   rackup: config.ruenvironment: of  either   RAILS_ROOT  or   MAIL_HOST: mail.yourhost.com REPLY_TO: you@yourhost.com RACK_ROOT 37
    38. 38. deployment  descriptorsdeploy/myapp-­{rails,rack}.ymlapplication: root: /path/to/myapp env: developmentweb: context: myapp host: www.yourhost.comThe  runtime  mode  of   static: public the  app.    This  will  be   rackup: config.ruenvironment: either  RAILS_ENV   MAIL_HOST: mail.yourhost.comor  RACK_ENV REPLY_TO: you@yourhost.com 38
    39. 39. deployment  descriptors The  app’s  context  path   deploy/myapp-­{rails,rack}.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: public rackup: config.ruenvironment: MAIL_HOST: mail.yourhost.com REPLY_TO: you@yourhost.com 39
    40. 40. deployment  descriptorsdeploy/myapp-­{rails,rack}.ymlapplication: root: /path/to/myapp A  list  of  virtual   env: development hostnames  to  which  web: to  bind  the  app. context: myapp host: www.yourhost.com static: public rackup: config.ruenvironment: MAIL_HOST: mail.yourhost.com REPLY_TO: you@yourhost.com 40
    41. 41. deployment  descriptorsdeploy/myapp-­{rails,rack}.ymlapplication: root: /path/to/myapp env: developmentweb: The  location  of  the   context: myapp app’s  static   host: www.yourhost.com content,  either   static: public absolute  or  relative   rackup: config.ru to  the  app’s  root.environment: MAIL_HOST: mail.yourhost.com REPLY_TO: you@yourhost.com 41
    42. 42. deployment  descriptorsdeploy/myapp-­{rails,rack}.ymlapplication: root: /path/to/myapp env: developmentweb: The  name  of  the   context: myapp rackup  script  used  to   host: www.yourhost.com boot  your  app static: public rackup: config.ruenvironment: MAIL_HOST: mail.yourhost.com REPLY_TO: you@yourhost.com 42
    43. 43. deployment  descriptorsdeploy/myapp-­{rails,rack}.ymlapplication: root: /path/to/myapp env: development Any  environment  web: variables  required   context: myapp by  the  app. host: www.yourhost.com static: public rackup: config.ruenvironment: MAIL_HOST: mail.yourhost.com REPLY_TO: you@yourhost.com 43
    44. 44. deployment  descriptors• config/torquebox.yml  • internal  descriptors  have  the   same  structure  as  the   external  ones  in  deploy/• may  be  used  to  provide  your   own  reasonable  defaults 44
    45. 45. Webmake rack, not war 45
    46. 46. jruby-­rack• All  rack-­based  frameworks   supported:  rails,  sinatra,  etc• No  packaging  required:  apps  deploy   from  where  they  sit  on  disk• No  redeploy  necessary  to  see   changes  when  using  rack  reloading   or  rails  development  mode 46
    47. 47. database  connectivityGemfilegem  "activerecord-­jdbc-­adapter"gem  "jdbc-­postgres"#  gem  "jdbc-­sqlite3"#  gem  "jdbc-­mysql" 47
    48. 48. rails  template• Adds  TorqueBox  rake  tasks• Adds  the  JDBC  sqlite3  gems• Adds  TorqueBox  session_store• Adds  Backgroundable  module 48
    49. 49. my  first  rails  app$  jruby  -­S  rails  new  myapp  -­m          $TORQUEBOX_HOME/share/rails/template.rb$  cd  myapp$  jruby  -­S  bundle  install$  jruby  -­S  rake  torquebox:deploy 49
    50. 50. Messaging asynchronicity 50
    51. 51. lots  of  optionsRabbitMQ Resque cron BackgroundDRb workling CronEdit BackgroundJob Kestral rufus-scheduler JobFu Ap4rAmazon SQS async_observer Taskr Sparrow Background-Fu beanstalkd DelayedJob RailsCron Open4 Conveyor WorkerQueue daemons rake ActiveMQ starling Spawn ActiveMessaging 51
    52. 52. TorqueBox::Messaging• JMS  (Java  Message  Service)   is  an  API  for  messaging• implementation HornetQ  is  the  JBoss  JMS   52
    53. 53. TorqueBox::Messaging• Task• Backgroundable• MessageProcessor• Queue• Topic 53
    54. 54. TorqueBox::Messaging• No  extra  tables  in  your  database• No  external  system  to  manage• Little  to  no  config  required  at  all• No  redeploy  necessary  in  dev  mode• Efficient  loading  of  rails  environment• Automatic  load  balancing  and  retries• Works  on  Windows,  if  you  care 54
    55. 55. Tasksapp/tasks/email_task.rbclass  EmailTask  <  TorqueBox::Messaging::Task    def  welcome(payload)        person  =  payload[:person]          person  ||=  Person.find_by_id(payload[:id])        if  person            #  send  the  email            person.welcomed  =  true            person.save!        end    endend 55
    56. 56. Tasksapp/tasks/email_task.rbclass  EmailTask  <  TorqueBox::Messaging::Task    def  welcome(payload)        person  =  payload[:person]          person  ||=  Person.find_by_id(payload[:id])        if  person            #  send  the  email            person.welcomed  =  true            person.save!        end    endend 56
    57. 57. Tasksapp/tasks/email_task.rbclass  EmailTask  <  TorqueBox::Messaging::Task    def  welcome(payload)        person  =  payload[:person]          person  ||=  Person.find_by_id(payload[:id])        if  person            #  send  the  email            person.welcomed  =  true            person.save!        end    endend 57
    58. 58. Tasksapp/tasks/email_task.rbclass  EmailTask  <  TorqueBox::Messaging::Task    def  welcome(payload)        person  =  payload[:person]          person  ||=  Person.find_by_id(payload[:id])        if  person            #  send  the  email            person.welcomed  =  true            person.save!        end    endend 58
    59. 59. Tasksapp/tasks/email_task.rbclass  EmailTask  <  TorqueBox::Messaging::Task    def  welcome(payload)        person  =  payload[:person]          person  ||=  Person.find_by_id(payload[:id])        if  person            #  send  the  email            person.welcomed  =  true            person.save!        end    endend 59
    60. 60. 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 60
    61. 61. 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 61
    62. 62. TasksCall  them  from  your  controllers,  models,  and  observers,  or  even  other  tasks.  Even  in  non-­Rails  apps! 62
    63. 63. BackgroundableInspired  by  DelayedJob’s  handle_asynchronously,  it’s  trivial  to  create  implicit  background  Tasks. 63
    64. 64. Backgroundablelib/something.rbinclude  TorqueBox::Messaging  class  Something    include  Backgroundable    always_background  :foo    def  foo;;  end    def  bar;;  endend...@something.foo@something.background.bar 64
    65. 65. Backgroundablelib/something.rbinclude  TorqueBox::Messaging  class  Something    include  Backgroundable    always_background  :foo    def  foo;;  end    def  bar;;  endend...@something.foo@something.background.bar 65
    66. 66. Backgroundablelib/something.rbinclude  TorqueBox::Messaging  class  Something    include  Backgroundable    always_background  :foo    def  foo;;  end    def  bar;;  endend...@something.foo@something.background.bar 66
    67. 67. Backgroundablelib/something.rbinclude  TorqueBox::Messaging  class  Something    include  Backgroundable    always_background  :foo    def  foo;;  end    def  bar;;  endend...@something.foo@something.background.bar 67
    68. 68. Backgroundableapp/models/slow_poke.rbclass  SlowPoke  <  ActiveRecord::Base    def  takes_forever;;  end    def  might_take_awhile;;  endendSlowPoke.always_background  :takes_forever@slowpoke.takes_forever@slowpoke.background.might_take_awhile 68
    69. 69. QueuesTasks  are  built  on  top  of  Queues.    Of  course,  you  may  build  your  own  “MOM”  apps  by  defining  your  own  Queues,  Topics,  and  their  message  Processors  yourself. 69
    70. 70. Queuesconfig/queues.yml/queues/questions:/queues/answers:    durable:  false 70
    71. 71. ProcessorsYou  can  create  a  processor  class  to  receive  messages  from  a  Topic  or  Queue 71
    72. 72. Processorsconfig/messaging.yml/topics/print: PrintHandler/queues/popular: - PopularHandler - AdultObserver: filter: "age >= 18" concurrency: 5/queues/students: PrintHandler: config: color: true 72
    73. 73. Processorsconfig/messaging.yml/topics/print: PrintHandler/queues/popular: - PopularHandler - AdultObserver: filter: "age >= 18" concurrency: 5/queues/students: PrintHandler: config: color: true 73
    74. 74. Processorsconfig/messaging.yml/topics/print: PrintHandler/queues/popular: - PopularHandler - AdultObserver: filter: "age >= 18" concurrency: 5/queues/students: PrintHandler: config: color: true 74
    75. 75. Processorsconfig/messaging.yml/topics/print: PrintHandler/queues/popular: - PopularHandler - AdultObserver: filter: "age >= 18" concurrency: 5/queues/students: PrintHandler: config: color: true 75
    76. 76. Processorsapp/models/print_handler.rbinclude  TorqueBox::Messagingclass  PrintHandler  <  MessageProcessor    def  on_message(body)        puts  "Processing  #{body}  of  #{message}"    end    def  configure(opts)        @color  =  opts[color]    endend 76
    77. 77. Queues  (again) But  how  do  you  send  a   message? 77
    78. 78. Queuesexampleinclude  TorqueBoxreq  =  Messaging::Queue.new  /queues/questionsres  =  Messaging::Queue.new  /queues/answers  Thread.new  do    req.publish  "What  time  is  it?"    puts  res.receive(  :timeout  =>  1000  )end  puts  req.receiveres.publish  Time.now 78
    79. 79. Queuesexampleinclude  TorqueBoxreq  =  Messaging::Queue.new  /queues/questionsres  =  Messaging::Queue.new  /queues/answers  Thread.new  do    req.publish  "What  time  is  it?"    puts  res.receive(  :timeout  =>  1000  )end  puts  req.receiveres.publish  Time.now 79
    80. 80. Queuesexampleinclude  TorqueBoxreq  =  Messaging::Queue.new  /queues/questionsres  =  Messaging::Queue.new  /queues/answers  Thread.new  do    req.publish  "What  time  is  it?"    puts  res.receive(  :timeout  =>  1000  )end  puts  req.receiveres.publish  Time.now 80
    81. 81. Queuesexampleinclude  TorqueBoxreq  =  Messaging::Queue.new  /queues/questionsres  =  Messaging::Queue.new  /queues/answers  Thread.new  do    req.publish  "What  time  is  it?"    puts  res.receive(  :timeout  =>  1000  )end  puts  req.receiveres.publish  Time.now 81
    82. 82. Queues“on  the  fly”include  TorqueBoxqueue  =  Messaging::Queue.new  /queues/fooqueue.create    ...  queue.destroy 82
    83. 83. Topics• behavior  is  different,  but  interface  is   the  same.• all  subscribers  of  a  topic  see  each   message,  but  only  one  subscriber   will  see  any  message  from  a  queue  • use  topics.yml  to  define  topics• use  TorqueBox::Messaging::Topic 83
    84. 84. Schedulingget regular later 84
    85. 85. Jobsapp/jobs/newsletter_sender.rbclass  NewsletterSender      def  run()        subscriptions  =  Subscription.find(:all)        subscriptions.each  do  |e|            send_newsletter(  e  )        end    end  end 85
    86. 86. Jobsconfig/jobs.ymlmonthly_newsletter:    description:  first  of  month    job:  NewsletterSender    cron:  ‘0  0  0  1  *  ?’sandbox:    job:  Sandbox    cron:  ‘*/5  *  *  *  *  ?’ 86
    87. 87. 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# 87
    88. 88. Jobs• More  portable.  What  is  the  first  day   of  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  rails  environment  loaded  and   available. 88
    89. 89. Servicesrun along, lil’ daemon 89
    90. 90. ServicesLong-­running,  non-­web  “daemons”  that  share  the  runtime  environment  and  deployment  lifecycle  of  your  app. 90
    91. 91. Services• Represented  as  a  class  with   optional  initialize(Hash),   start()  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.yml 91
    92. 92. Servicesconfig/services.ymlIrcBot:    server:  freenode.net    channel:  #torquebox    publish:  /topics/ircMyMudServer:SomeOtherService: 92
    93. 93. Servicesapp/{models,etc}/my_service.rbclass  MyService    def  initialize  opts={}        name  =  opts[:publish]        @queue  =  Messaging::Queue.new(name)    end    def  start          Thread.new  {  run  }      end    def  stop          @done  =  true    endend 93
    94. 94. Servicesapp/{models,etc}/my_service.rbclass  MyService    def  initialize  opts={}        name  =  opts[:publish]        @queue  =  Messaging::Queue.new(name)    end    def  start          Thread.new  {  run  }      end    def  stop          @done  =  true    endend 94
    95. 95. Servicesapp/{models,etc}/my_service.rbclass  MyService    def  initialize  opts={}        name  =  opts[:publish]        @queue  =  Messaging::Queue.new(name)    end    def  start          Thread.new  {  run  }      end    def  stop          @done  =  true    endend 95
    96. 96. Servicesapp/{models,etc}/my_service.rbclass  MyService    def  initialize  opts={}        name  =  opts[:publish]        @queue  =  Messaging::Queue.new(name)    end    def  start          Thread.new  {  run  }      end    def  stop          @done  =  true    endend 96
    97. 97. Servicesapp/{models,etc}/my_service.rbclass  MyService    def  run        until  @done            @queue.publish(Time.now)            sleep(1)          end    endend 97
    98. 98. Servicesapp/{models,etc}/my_service.rbclass  MyService    def  run        until  @done            @queue.publish(Time.now)            sleep(1)          end    endend 98
    99. 99. Servicesapp/services/evented_service.rbclass  EventedService    def  initialize  opts={}        @opts  =  opts    end    def  start          Thread.new  {  EventMachine.run  {...}  }    end    def  stop          EventMachine.stop    endend 99
    100. 100. Clusteringless failure faster 100
    101. 101. out-­of-­the-­box• JBoss  provides • session  replication • load-­balanced  messaging• mod_cluster  provides • session  affinity • intelligent  load-­balanced  web • failover 101
    102. 102. JBOSS_CONFTorqueBox  ships  with  two  JBoss  server  configurations:  default  (not  clustered)  and  all  (clustered).  To  enable  clustering...$  export  JBOSS_CONF=all 102
    103. 103. deploy  and  run$  export  JBOSS_CONF=all$  jruby  -­S  rake  torquebox:deploy$  jruby  -­S  rake  torquebox:run 103
    104. 104. mod_clusterA  reverse  proxy  implemented  as  an  Apache  module  with  JBoss  awareness.  Constantly  gathers  load  statistics  and  deployment  availability  for  intelligent  request  distribution. 104
    105. 105. mod_cluster 105
    106. 106. mod_cluster• Dynamic  configuration• Server-­side  load  factor  calculation• Fine-­grained  web  app  lifecycle• AJP  (Apache  JServ  Protocol)  is   optional.  HTTP[S]  is  also  supported. 106
    107. 107. Futurecoming soon 107
    108. 108. Future• Performance  benchmarking  and   optimization• Infinispan  for  ActiveSupport::Cache   and  NoSQL  persistence• JBoss  SSO,  HASingleton,  logging• CDI  injection  of  Java  components  into   Ruby• More  JavaEE  bridged  to  Ruby  where   it  makes  sense,  e.g.  BPM,  Drools,   Transactions,  etc. 108
    109. 109. Resources• http://torquebox.org• #torquebox  on  freenode• https://github.com/torquebox• http://twitter.com/torquebox• http://projectodd.org 109
    110. 110. Thanks!questions? 110
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×