Torquebox 2
Przemysław Wróblewski
Co to jest Torquebox ?
● Torquebox to zmodyfikowany JBoss AS 7, który integruje środowisko JEE ze środowiskiem Rubiego.
● Dostarcza interfejsy Ruby do usług dostarczanych przez server aplikacji
● pozwala uruchamiać Jave i Ruby w tym samym kontenerze aplikacji
● umożliwia szybkie i proste sklastrowanie aplikacji
JRuby• połączenie Ruby i JVM• Java i Ruby mogą się integrować require 'java'java.lang.System.setProperty('key','value')java_import java.util.HashMaphashmap = HashMap.newhashmap['key'] = 'value'
JRuby
Torquebox - co jest w środku ?
Kolejki
Workery - konfiguracjaconfig/torquebox.yml: queues: /queues/raw_offer: durable: false messaging: default_message_encoding: marshal /queues/raw_offer: RawOfferMessageProcessor: concurrency: 18
Workeryclass RawOfferMessageProcessor < TorqueBox::Messaging::MessageProcessor include TorqueBox::Injectors include AirbrakeReportable def on_message(body) out_msg = OfferChecker.new.check body if out_msg queue = inject('/queues/offer') queue.publish(out_msg) end end def on_error(error) notify_airbrake(error, {parameters: {message: @message.decode}}) endend
Backgroundable
class Something def foo sleep 5 endend something = Something.newsomething.foo
standardowa klasa + blokujące wywołanie
Backgroundable
class Something include TorqueBox::Messaging::Backgroundable def foo sleep 5 endend something = Something.newsomething.background.foo
wywołanie nie blokujące
Backgroundable
something = Something.newfuture = something.background.foo future.started?future.complete?future.error?future.result
sprawdz stan zadania nieblokującego
Backgroundable
class Something def foo ... count+=1 future.status=count ... endend
sprawdz stan zadania nieblokującego
something = Something.newfuture = something.background.foofuture.status_changed?future.status #=>42
Cronconfig/torquebox.yml: jobs: data_import: description: "Import danych z importu 2.0" job: DataImportJob cron: '0 10 18 * * ?' singleton: true
Cronapp/jobs/data_import_job.rb: class DataImportJob def initialize dump_directory = File.join(Date.today.to_s(:number)) @importer = DataImporter.new(dump_directory) end def run ... endend
Usługiapp/services/time_machine.rb: class TimeMachine def initialize(opts) @queue=Queue.new(opts['queue']) end def start Thread.new { run } end def stop @done=true end ...end
Usługiconfig/torquebox.yml: services: TimeMachine: config: queue: /queue/time
Resource Injectionapp/controllers/my_contoller.rb: class MyController < ApplicationController include TorqueBox::Injectors def stop # Service defined with a unique name in torquebox.yml the_torque_service = inject( 'service:TimeMachine' ) the_torque_service.stop end end
Resource Injection
inject_cdi(...)Injects CDI resources by literal class name.
inject_queue(...)Injects a messaging queue by literal name.
inject_topic(...)Injects a messaging topic by literal name.
inject_naming(...)Injects JNDI resources by literal name.
inject_msc(...)Injects MSC services by literal name.
inject_service(...)Injects a TorqueBox application service component
metody
Cache
Cache
config/application.rb: module MyApp class Application < Rails::Application ... config.cache_store=:torque_box_store endend
RailsCaching
Cache
include ActiveSupport::Cachemy_cache = TorqueBoxStore.new(:name=>'MyCache', :mode=>:replicated, :sync=>true)my_cache.put('klucz','wartość')my_cache.put_if_absent('klucz','inna wartość')my_cache.replace('klucz','jeszcze inna wartość')Torquebox.transaction do my_cache.remove( 'klucz' )endmy_cache.transaction do my_cache.put_if_absent('klucz','zupełnie inna wartość')end
bezpośredni dostep do własnej przestrzeni
Cache
LocalDomyślny, wszystko jest trzymane w ramach pojedyńczego node'a, odpowiednik trzymania w pamięci ale pozwala na zapewnienie persystencji, daje transakcje
InvalidationDomyślny w trybie clustra, nie wysyla zmian do innych node'ów tylko komunikaty o przedawnieniu klucza. Dobrze sprawuje sie do cacheowania widoków i innych szybkich do odtworzenia wartości
ReplicatedKopiuje zawartość klucza do kazdego node'a, odczyty będą wykonywane już lokalnie
Distributedczyli sharding + replikacja, memcache, redis schowajcie sie :-P
tryby pracy
Cache noSQL data mapperrequire 'dm-core'require 'datamapper/dm-infinispan-adapter'
class Beer include DataMapper::Resource property :id, Serial property :name, String property :desc, Text property :likes, Integer property :created_at, DateTimeend
DataMapper.setup(:default, :adapter=>'infinispan', :persist=>'db/infinispan')DataMapper::Model.raise_on_save_failure = trueDataMapper.finalize
Beer.create(:name=>'Catawba White Zombie Ale', :description=>'A Belgium white ale made with coriander, orange peel, and wheat. This beer is refreshing and tasty with a sweet and shimmering frothy head.', :created_at=>Time.now)beers = Beer.all(:desc.like => "%belgium%", :name.like => "%ale%")
monitoring
monitoring
monitoring
jboss2:8080/monitoring
Torquebox 2http://torquebox.org/
TorqueBox – moc Javy, piękno Rubiego – Marek Goldmann
Wideo: http://video-it.pl/2011/07/torquebox-moc-javy-piekno-rubiego-marek-goldmann/Slajdy: http://www.slideshare.net/marekgoldmann/torquebox-moc-javy-pikno-rubiego
Demo: https://github.com/goldmann/confitura-2011-torquebox-demo