TorqueBoxThe  expressiveness  of  Ruby     The  power  of  Java       Bob  McWhirter        JBoss  Fellow
Bob  McWhirter‣ JBoss  Fellow  at  Red  Hat‣ Founder  of...  ‣ The  Codehaus  ‣ Drools  ‣ TorqueBox  ‣ DeltaCloud  API
but  it’s  a  team
What  is  TorqueBox?TorqueBox  glues  JRuby  to  the  JBoss  Java  Application  Server  (JBoss  AS).
Why  JRuby‣ Real  threads‣ Many  garbage-­collection  options‣ Lots  of  JVM  research‣ Integration  with  Java‣ Fast!
What  is  JBoss  AS?JBoss  AS  is  full  JavaEE  application  server,  providing  web,  caching,  messaging,  clustering, ...
Ruby!APIs!/!Programming!Models                               Java!APIs!/!Programming!Models                               ...
But  Java  is  enterprisey,  while  Ruby  is  agile...!
“Java  is  a  DSL  for  taking  large  XML  files  and  converting  them  to  stack  traces”               Scott  Bellware
One  of  our  mantras:XML  means  we’ve  <failed/>
First  Order  GoalsBe  a  great  traditional  Ruby  environment  ‣ Rack  ‣ Rails  ‣ Sinatra  ‣ Padrino
Second  Order  GoalsBe  better  than  a  traditional  environment: ‣   Services              ‣ Caching ‣   Jobs           ...
First:  web
Your  appmyapp/    config.ru    config/        application.rb        database.yml        torquebox.yml    app/        view...
1  AS,  many  apps                       config/torquebox.ymlapplication:    root:  /path/to/myappweb:    context:  /    h...
Compare  to...                                                                         WEB-­INF/web.xml<?xml  version="1.0...
Make  Love,  not  WARLive,  where  it  sits  on  disk.         No  archive  required.
(caveat)Requires  runtime  reloading  support  in  your  framework,  but  not  redeployment. Rails                Rack::Re...
Works  as  expected,almost  boring              http://www.flickr.com/photos/djbadly/2052098189/
Second  order  goal:services
Daemons!start()          ...time  passes...                               stop()
Example  service                  app/services/my_service.rbclass  MyServer    def  initialize(opts)    end    def  start ...
Service  config                           config/torquebox.ymlservices:    MyService:        some_key:  some_value    MyCr...
singleton?             true Ensures  one  (and  only  one)  instance  is  running  within  the  cluster  at  a  time,  wit...
singleton?  false   (default)
Second  order  goal:scheduled  jobs
cron-­like-­ every  3  hours...-­ the  first  of  each  month...-­ on  Tuesdays...-­ when  the  world  ends...            ...
Job  example                              apps/jobs/my_job.rbclass  MyJob        def  run()        #  your  code  here    ...
Job  config                        config/torquebox.ymljobs:    monthly_reminder:        description:  sends  reminders   ...
Second  order  goal:messaging           messaging                           messaging           (we  really  like  messagi...
Darn  zippy  JMS  broker
Where  to,  my  friend?                          config/torquebox.ymlqueues:    /queues/puppies:    /queues/kittens:      ...
Consumer           Consumer   Consumer           Consumer           Topic                         Queue
Let’s  go!                          arbitrary_app_stuff.rbclass  MyController  <  ApplicationController    include  Torque...
Now  arriving...                app/processors/my_processorinclude  TorqueBox::Messagingclass  MyProcessor  <  MessageProc...
Processor  config                          config/torquebox.ymlmessaging:    /queues/puppies:        MyHandler:           ...
But  that’s  not  all!
What  makes  messaging  special?
Asynchttp://www.flickr.com/photos/photogaby/4129740673/
BackgroundablesGo  asynchronous  without  having  to  think  about  messaging.
Enabling                           my_arbitrary_file.rbclass  User    include  TorqueBox::Messaging::Backgroundable    def...
What?Teaches  your  class  how  to  invoke  methods  across  an  implicit  queue.               Yay  mix-­ins!
Using  explicitly                 my_other_arbitrary_file.rbu  =  User.newu.do_something_slowly()u.background.do_something...
Forcing                           my_arbitrary_file.rbclass  User    include  TorqueBox::Messaging::Backgroundable    alwa...
Using  implicitly             my_other_arbitrary_file.rbu  =  User.newu.do_something_slowly()
The  FUTURE!future  =  user.do_something_slowly()future.started?future.complete?future.error?future.result
Progress!class  User    include  TorqueBox::Backgroundable    always_background  :do_something_slowly    def  do_something...
Queryfuture  =  user.do_something_slowly()future.status_changed?future.status  #  =>  “uploaded”
Second  order  goal:transactions
TransactionsQueue               Database   Infinispan        Your!Code                Topic
[                                                ]          Transactions  Queue               Database         Infinispan ...
XA  Everything  succeeds  or  everything  fails‣ HornetQ  supports  XA‣ Infinispan  supports  XA‣ TorqueBox  makes  Active...
Second  order  goal:caching        and  more
InfinispanNode            Node      Node         NodeItem #1        Item #1    Item #2      Item #3Item #4        Item #2 ...
Replace         memcachedPlaces  Rails  can  use  memcached?Now  you’re  using  Infinispan.
As  an  object-­storeUsable  behind  DataMapper  through  dm-­infinispan-­adapter.
Directly                        my_arbitrary_file.rbmy_cache  =  TorqueBoxStore.new(                          :name=>‘my-­...
Clustered  web  sessions...
Second  order  goal:websockets
to  the  browserStream-­Oriented  Message  Protocol (I  did  say  we  really  really  liked  messaging)
http://www.flickr.com/photos/greencolander/4299692892/ Bare  WebSockets  and  clusters  don’t  get  along.
WebSockets  is  already  frame-­based,  not  streaming...          Use  messaging!
But  directly  exposing  your  JMS  to  the  internet  seems  unwise...        http://www.flickr.com/photos/ell-­r-­brown/...
Stomplets  act  as  a  controller  between  user  and  JMS.
Browser   Stomplet   JMS!Stuff
Example  Stomplet              app/stomplets/my_stomplet.rbclass  MyStomplet    def  on_subscribe(subscriber)    end    de...
Configuration                         config/torquebox.ymlstomp:    stomplets:        animals:            route:  ‘/animal...
JMS  helperssubscribe_to(  subscriber,  jms_dest  )send_to(  jms_dest,  message,  headers={}  )
Second  order  goal:injection
Resource  Injection‣ Inversion  of  control‣ Allows  for  easier  testing‣ Inject  non-­Ruby  things
Injectables‣ Services‣ Queues  &  Topics‣ Java  CDI  components
Destinationsinject(  ‘/queues/kittens’  ).publish(...)inject(  ‘/topics/puppies’  ).publish(...)
CDI                    MyJavaThing.javapackage  com.mycorp;;@ApplicationScopedpublic  class  MyJavaThing  {    public  voi...
CDI                      my_arbitrary_file.rbinject(  com.mycorp.MyJavaThing  ).frob()
Clustering
There  is  no  cluster  (noun),but  things  can  cluster  (verb).
Clusterstuff‣ Web  sessions‣ Web  load-­balancing‣ Caches‣ Messaging  destinations‣ HA  coordination
JGroupsMany  discovery  and  communication  options.‣ Multicast‣ Rendezvous‣ S3                              except       ...
mod_cluster     httpd!+!mod_clusterAS           AS            AS
performance
Throughput1208040 0                  40min      TorqueBox      Unicorn      Passenger                          Higher  is ...
Latency  65s  16s   4s   1s256ms64ms                       40min        TorqueBox        Unicorn        Passenger         ...
CPU  Usage80604020 0                 40min     TorqueBox     Unicorn     Passenger                         Lower  is  bett...
Free  Memory7gb6gb5gb4gb3gb2gb1gb  0                  40min      TorqueBox      Unicorn      Passenger                    ...
Management
Managing  groups  of  servers  is  orthogonal  to  the  clustering  of  servers.
API                         Domain!Controller                 API                          API      Host!Controller       ...
Ecosystem
BackstageDashboard  to  monitor  and  control  Ruby  components.With  a  RESTful  API.
StompBoxGit-­based  application  deployment  straight  to  your  server.
TorqueSpecRSpec  enhancements  for  integration  testing.Start  TorqueBox  &  deploy  apps  are  part  of  your  specs.In-...
Cloudrific!
‣   Ruby‣   Java‣   PHP      openshift.redhat.com‣   Python‣   Perl
‣ Multi-­tenant  machines‣ High  density  (let  OS  swap)‣ Git-­based  deployment‣ Constrained  to  achieve  density‣ SELi...
Resources‣ http://torquebox.org/‣ http://github.com/torquebox/torquebox‣ #torquebox  on  Freenode‣ @torquebox  on  Twitter...
http://www.flickr.com/photos/21496790@N06/5065834411/
Hey,  thanks  for  having  me!                   http://www.flickr.com/photos/stevendepolo/4582437563/
TorqueBox at DC:JBUG - November 2011
Upcoming SlideShare
Loading in...5
×

TorqueBox at DC:JBUG - November 2011

2,271

Published on

Presentation about TorqueBox to the DC:JBUG in November, 2011.

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,271
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
30
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

TorqueBox at DC:JBUG - November 2011

  1. 1. TorqueBoxThe  expressiveness  of  Ruby The  power  of  Java Bob  McWhirter JBoss  Fellow
  2. 2. Bob  McWhirter‣ JBoss  Fellow  at  Red  Hat‣ Founder  of... ‣ The  Codehaus ‣ Drools ‣ TorqueBox ‣ DeltaCloud  API
  3. 3. but  it’s  a  team
  4. 4. What  is  TorqueBox?TorqueBox  glues  JRuby  to  the  JBoss  Java  Application  Server  (JBoss  AS).
  5. 5. Why  JRuby‣ Real  threads‣ Many  garbage-­collection  options‣ Lots  of  JVM  research‣ Integration  with  Java‣ Fast!
  6. 6. What  is  JBoss  AS?JBoss  AS  is  full  JavaEE  application  server,  providing  web,  caching,  messaging,  clustering,  failover,  etc.
  7. 7. Ruby!APIs!/!Programming!Models Java!APIs!/!Programming!Models Message Processors Polyglot WebSockets InjectionSinatra Rails Jobs STOMP POJO REST Servlet Rack Daemons Tasks Spring JMS JavaEE JRuby!Component!Deployers!&!Gems Java!Enterprise!Services JBoss Web Messaging Infinispan Cache TorqueBox HornetQ Transactions Core Quartz Security TorqueBox Core PicketLink JRuby with JIT Managed Services Container Java Virtual Machine
  8. 8. But  Java  is  enterprisey,  while  Ruby  is  agile...!
  9. 9. “Java  is  a  DSL  for  taking  large  XML  files  and  converting  them  to  stack  traces” Scott  Bellware
  10. 10. One  of  our  mantras:XML  means  we’ve  <failed/>
  11. 11. First  Order  GoalsBe  a  great  traditional  Ruby  environment ‣ Rack ‣ Rails ‣ Sinatra ‣ Padrino
  12. 12. Second  Order  GoalsBe  better  than  a  traditional  environment: ‣ Services ‣ Caching ‣ Jobs ‣ WebSockets ‣ Messaging ‣ HA/Failover ‣ Transactions
  13. 13. First:  web
  14. 14. Your  appmyapp/    config.ru    config/        application.rb        database.yml        torquebox.yml    app/        views/        controllers/        models/
  15. 15. 1  AS,  many  apps config/torquebox.ymlapplication:    root:  /path/to/myappweb:    context:  /    host:  www.myapp.comenvironment:    RAILS_ENV:  production    MAIL_HOST:  mail.myapp.com
  16. 16. Compare  to... WEB-­INF/web.xml<?xml  version="1.0"  encoding="UTF-­8"?><web-­app  version="2.5"          xmlns="http://java.sun.com/xml/ns/javaee"        xmlns:xsi="http://www.w3.org/2001/XMLSchema-­instance"        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee  http://java.sun.com/xml/ns/javaee/web-­app_2_5.xsd">  <context-­param>      <param-­name>mail.host</param-­name>      <param-­value>mail.myapp.com</param-­value>  </context-­param>  <servlet>      <display-­name>Servlet1</display-­name>      <servlet-­name>Servlet1</servlet-­name>      <servlet-­class>test.Servlet1</servlet-­class>  </servlet>  <servlet-­mapping>      <servlet-­name>Servlet1</servlet-­name>      <url-­pattern>/Servlet1</url-­pattern>  </servlet-­mapping>  <welcome-­file-­list>      <welcome-­file>index.html</welcome-­file>  </welcome-­file-­list></web-­app>
  17. 17. Make  Love,  not  WARLive,  where  it  sits  on  disk. No  archive  required.
  18. 18. (caveat)Requires  runtime  reloading  support  in  your  framework,  but  not  redeployment. Rails                Rack::Reloader
  19. 19. Works  as  expected,almost  boring http://www.flickr.com/photos/djbadly/2052098189/
  20. 20. Second  order  goal:services
  21. 21. Daemons!start() ...time  passes... stop()
  22. 22. Example  service app/services/my_service.rbclass  MyServer    def  initialize(opts)    end    def  start    end    def  stop    endend
  23. 23. Service  config config/torquebox.ymlservices:    MyService:        some_key:  some_value    MyCriticalService:        singleton:  true
  24. 24. singleton? true Ensures  one  (and  only  one)  instance  is  running  within  the  cluster  at  a  time,  with  failover.
  25. 25. singleton? false (default)
  26. 26. Second  order  goal:scheduled  jobs
  27. 27. cron-­like-­ every  3  hours...-­ the  first  of  each  month...-­ on  Tuesdays...-­ when  the  world  ends... http://www.flickr.com/photos/spine/2408967576/
  28. 28. Job  example apps/jobs/my_job.rbclass  MyJob        def  run()        #  your  code  here    endend
  29. 29. Job  config config/torquebox.ymljobs:    monthly_reminder:        description:  sends  reminders        job:  MyJob        cron:  ‘0  0  0  1  *  ?’        singleton:  true    file_cleaner:        description:  clean  files  on  node        job:  FileCleaner        cron:  ‘5  *  *  *  *  ?’
  30. 30. Second  order  goal:messaging messaging messaging (we  really  like  messaging)
  31. 31. Darn  zippy  JMS  broker
  32. 32. Where  to,  my  friend? config/torquebox.ymlqueues:    /queues/puppies:    /queues/kittens:        durable:  falsetopics:    /topics/memes:
  33. 33. Consumer Consumer Consumer Consumer Topic Queue
  34. 34. Let’s  go! arbitrary_app_stuff.rbclass  MyController  <  ApplicationController    include  TorqueBox::Injectors      def  index        @queue  =  inject(  ‘/queues/puppies’  )        @queue.publish(  “Oh,  puppies!”  )    endend
  35. 35. Now  arriving... app/processors/my_processorinclude  TorqueBox::Messagingclass  MyProcessor  <  MessageProcessor    def  initialize(opts)    end    def  on_message(body)        #  your  code  here.    endend
  36. 36. Processor  config config/torquebox.ymlmessaging:    /queues/puppies:        MyHandler:            concurrency:  5            config:                some_key:  some_value    /queues/kittens:        MyOtherHandler:            singleton:  true
  37. 37. But  that’s  not  all!
  38. 38. What  makes  messaging  special?
  39. 39. Asynchttp://www.flickr.com/photos/photogaby/4129740673/
  40. 40. BackgroundablesGo  asynchronous  without  having  to  think  about  messaging.
  41. 41. Enabling my_arbitrary_file.rbclass  User    include  TorqueBox::Messaging::Backgroundable    def  do_something_slowly()        upload_over_300baud_modem()    endend
  42. 42. What?Teaches  your  class  how  to  invoke  methods  across  an  implicit  queue. Yay  mix-­ins!
  43. 43. Using  explicitly my_other_arbitrary_file.rbu  =  User.newu.do_something_slowly()u.background.do_something_slowly()
  44. 44. Forcing my_arbitrary_file.rbclass  User    include  TorqueBox::Messaging::Backgroundable    always_background  :do_something_slowly    def  do_something_slowly()        upload_over_300baud_modem()    endend
  45. 45. Using  implicitly my_other_arbitrary_file.rbu  =  User.newu.do_something_slowly()
  46. 46. The  FUTURE!future  =  user.do_something_slowly()future.started?future.complete?future.error?future.result
  47. 47. Progress!class  User    include  TorqueBox::Backgroundable    always_background  :do_something_slowly    def  do_something_slowly        upload_over_modem()        future.status  =  “uploaded”        alert_authorities        future.status  =  “alerted”    endend
  48. 48. Queryfuture  =  user.do_something_slowly()future.status_changed?future.status  #  =>  “uploaded”
  49. 49. Second  order  goal:transactions
  50. 50. TransactionsQueue Database Infinispan Your!Code Topic
  51. 51. [ ] Transactions Queue Database Infinispan Your!Code TopicXA  distributed,  multi-­resource  transaction
  52. 52. XA Everything  succeeds  or  everything  fails‣ HornetQ  supports  XA‣ Infinispan  supports  XA‣ TorqueBox  makes  ActiveRecord   support  XA,  if  your  database  does.
  53. 53. Second  order  goal:caching and  more
  54. 54. InfinispanNode Node Node NodeItem #1 Item #1 Item #2 Item #3Item #4 Item #2 Item #3 Item #4 Replicated  &  Distributed
  55. 55. Replace   memcachedPlaces  Rails  can  use  memcached?Now  you’re  using  Infinispan.
  56. 56. As  an  object-­storeUsable  behind  DataMapper  through  dm-­infinispan-­adapter.
  57. 57. Directly my_arbitrary_file.rbmy_cache  =  TorqueBoxStore.new(                          :name=>‘my-­cache’,                          :mode=>:replicated                      )my_cache.put(...)my_cache.get(...)
  58. 58. Clustered  web  sessions...
  59. 59. Second  order  goal:websockets
  60. 60. to  the  browserStream-­Oriented  Message  Protocol (I  did  say  we  really  really  liked  messaging)
  61. 61. http://www.flickr.com/photos/greencolander/4299692892/ Bare  WebSockets  and  clusters  don’t  get  along.
  62. 62. WebSockets  is  already  frame-­based,  not  streaming... Use  messaging!
  63. 63. But  directly  exposing  your  JMS  to  the  internet  seems  unwise... http://www.flickr.com/photos/ell-­r-­brown/4686613540/
  64. 64. Stomplets  act  as  a  controller  between  user  and  JMS.
  65. 65. Browser Stomplet JMS!Stuff
  66. 66. Example  Stomplet app/stomplets/my_stomplet.rbclass  MyStomplet    def  on_subscribe(subscriber)    end    def  on_unsubscribe(subscriber)    end    def  on_message(stomp_message,  session)    endend
  67. 67. Configuration config/torquebox.ymlstomp:    stomplets:        animals:            route:  ‘/animals/:type’            class:  MyStomplet
  68. 68. JMS  helperssubscribe_to(  subscriber,  jms_dest  )send_to(  jms_dest,  message,  headers={}  )
  69. 69. Second  order  goal:injection
  70. 70. Resource  Injection‣ Inversion  of  control‣ Allows  for  easier  testing‣ Inject  non-­Ruby  things
  71. 71. Injectables‣ Services‣ Queues  &  Topics‣ Java  CDI  components
  72. 72. Destinationsinject(  ‘/queues/kittens’  ).publish(...)inject(  ‘/topics/puppies’  ).publish(...)
  73. 73. CDI MyJavaThing.javapackage  com.mycorp;;@ApplicationScopedpublic  class  MyJavaThing  {    public  void  frob()  {  ...}}
  74. 74. CDI my_arbitrary_file.rbinject(  com.mycorp.MyJavaThing  ).frob()
  75. 75. Clustering
  76. 76. There  is  no  cluster  (noun),but  things  can  cluster  (verb).
  77. 77. Clusterstuff‣ Web  sessions‣ Web  load-­balancing‣ Caches‣ Messaging  destinations‣ HA  coordination
  78. 78. JGroupsMany  discovery  and  communication  options.‣ Multicast‣ Rendezvous‣ S3  except   eat: (Cav netQ)‣ File Hor
  79. 79. mod_cluster httpd!+!mod_clusterAS AS AS
  80. 80. performance
  81. 81. Throughput1208040 0 40min TorqueBox Unicorn Passenger Higher  is  better Trinidad
  82. 82. Latency 65s 16s 4s 1s256ms64ms 40min TorqueBox Unicorn Passenger Lower  is  better Trinidad
  83. 83. CPU  Usage80604020 0 40min TorqueBox Unicorn Passenger Lower  is  better Trinidad
  84. 84. Free  Memory7gb6gb5gb4gb3gb2gb1gb 0 40min TorqueBox Unicorn Passenger Higher  is  better Trinidad
  85. 85. Management
  86. 86. Managing  groups  of  servers  is  orthogonal  to  the  clustering  of  servers.
  87. 87. API Domain!Controller API API Host!Controller Host!ControllerAPI APIAS AS AS AS AS AS
  88. 88. Ecosystem
  89. 89. BackstageDashboard  to  monitor  and  control  Ruby  components.With  a  RESTful  API.
  90. 90. StompBoxGit-­based  application  deployment  straight  to  your  server.
  91. 91. TorqueSpecRSpec  enhancements  for  integration  testing.Start  TorqueBox  &  deploy  apps  are  part  of  your  specs.In-­container  testing,  too!
  92. 92. Cloudrific!
  93. 93. ‣ Ruby‣ Java‣ PHP openshift.redhat.com‣ Python‣ Perl
  94. 94. ‣ Multi-­tenant  machines‣ High  density  (let  OS  swap)‣ Git-­based  deployment‣ Constrained  to  achieve  density‣ SELinux  to  secure  tenants
  95. 95. Resources‣ http://torquebox.org/‣ http://github.com/torquebox/torquebox‣ #torquebox  on  Freenode‣ @torquebox  on  Twitter‣ The  tall  guy  up  front
  96. 96. http://www.flickr.com/photos/21496790@N06/5065834411/
  97. 97. Hey,  thanks  for  having  me! http://www.flickr.com/photos/stevendepolo/4582437563/
  1. A particular slide catching your eye?

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

×