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.

Rails goes SOA

1,126 views

Published on

The slides of my talk at Rails-Konferenz 2009 in Frankfurt/Offenbach about bringing together the ideas of SOA with Rails to handle complexity.

Published in: Technology
  • Ich kann eine Website empfehlen. Er hat mir wirklich geholfen. ⇒ www.WritersHilfe.com ⇐ Zufrieden und beeindruckt.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Be the first to like this

Rails goes SOA

  1. 1. Rails goes SOA Rails-Konferenz 2009 – Frankfurt/Offenbach Dirk Breuer – pkw.de 02. September 2009
  2. 2. View Controller (nur lesend) Model (enthält Business Logik + Daten)
  3. 3. View Controller (nur lesend) Business Logik Model (enthält Business Logik)
  4. 4. View Business (nur lesend) Controller Logik extract Model (Datenhaltung)
  5. 5. Vorteile der Transformation Entwickler erhalten Kontrolle über Source Code zurück Bessere Verständlichkeit für die Fachseite Grafik © by Martin Laksman, 2003
  6. 6. Vorteile der Transformation Entwickler erhalten Kontrolle über Source Code zurück Bessere Verständlichkeit für die Fachseite Bessere Time-to-Market Grafik © by Martin Laksman, 2003
  7. 7. Service-Orientierte Architekturen
  8. 8. View Services (nur lesend) Controller (enthalten Business Logik) Model (Datenhaltung)
  9. 9. How To SOA?
  10. 10. Fahrzeuge Suchen
  11. 11. Fahrzeuge für die Startseite anzeigen
  12. 12. Suchauftrag für Suche anlegen
  13. 13. Benutzer authentifizieren
  14. 14. Statistiken für ein Fahrzeug anzeigen
  15. 15. Statistiken für ein Fahrzeug anzeigen Statistiken Schreiben
  16. 16. get_startpage_cars get_statistics_of_car get_startpage_dealer get_number_of_cars_of_customer get_startpage_teaser get_cars_of_customer search_cars get_number_of_car_images create_temporary_customer get_car_images create_temporary_car delete_car save_temporary_customer delete_customer save_temporary_car get_search_orders_of_customer authenticate_customer delete_search_order add_image_to_car search_cars_by_search_order generate_captcha authenticate_customer verify_captcha authenticate_dealer accept_customer generate_password publish_car send_new_password notify_customer_about_published_car …
  17. 17. Vorteile von SOA Services werden von Fachseite gefunden Fachseite versteht IT besser Fachseite versteht Komplexität besser Fachliche Sicht sehr langlebig, dadurch Services sehr langlebig
  18. 18. Vorteile von SOA Services werden von Fachseite gefunden Fachseite versteht IT besser Fachseite versteht Komplexität besser Fachliche Sicht sehr langlebig, dadurch Services sehr langlebig Grafik © by Martin Laksman, 2003 Langlebigkeit ...?
  19. 19. Langlebigkeit der Datenbank? Änderung von Spalten Änderung des CRM-Systems Anbindung an SAP Zusammenlegung von StartUps
  20. 20. Langlebigkeit der GUI? Änderung der Anordnung von Elementen Änderung von Dialogen Änderung von Texten Redesign der gesamten Plattform
  21. 21. Langlebigkeit von Services Fachseite definiert Geschäftsprozesse Fahrzeuge suchen Benutzer authentifizieren Statistiken schreiben Änderungen auf dieser Ebene sehr viel unwahrscheinlicher
  22. 22. Und was genau ist ein Service Jetzt?! Grafik © by Martin Laksman, 2003
  23. 23. Ein Service ist … … technologie- und plattformunabhängig … dynamische lokalisier- und ausführbar … in sich abgeschlossen … durch eine wohl-definierte und formale Schnittstelle beschrieben … stateless
  24. 24. Basic SOA Service Provider Dienstbeschreibung Dienstimplementierung veröffentlichen binden Service Service Registry Dienstbeschreibung Client finden
  25. 25. Aber kosten diese SOA Lösungen von IBM & Co nicht sehr viel Geld? Grafik © by Martin Laksman, 2003
  26. 26. Aber kosten diese SOA Lösungen von IBM & Co nicht sehr viel Geld? Ja ... Grafik © by Martin Laksman, 2003
  27. 27. Aber kosten diese SOA Lösungen von IBM & Co nicht sehr viel Geld? Ja ... Das können wir uns nicht leisten! Grafik © by Martin Laksman, 2003
  28. 28. SOA ist doch nur ein Konzept. Das können wir auch selbst umsetzen. Grafik © by Martin Laksman, 2003
  29. 29. SOA ist doch nur ein Konzept. Das können wir auch selbst umsetzen. Und zwar passend für uns! Grafik © by Martin Laksman, 2003
  30. 30. + SO A
  31. 31. class SearchService def self.search_cars(search_criteria) # Calling the Car class which is just # a ActiveRecord::Base subclass end end found_cars = SearchService.search_cars(some_criteria)
  32. 32. Aber moment, das sieht class SearchService def self.search_cars(search_criteria) # Calling the Car class which is just # a ActiveRecord::Base subclass end end found_cars = SearchService.search_cars(some_criteria)
  33. 33. class Car < ActiveRecord::Base def self.search(criteria) find(:all, :conditition => criteria) end end found_cars = Car.search(params[:criteria])
  34. 34. class Car < ActiveRecord::Base def self.search(criteria) find(:all, :conditition => criteria) end end found_cars = Car.search(params[:criteria]) Aber ...
  35. 35. Echte Businesslogik ist in der Regel deutlich komplexer Bisher: ActiveRecord::Base = Businesslogik + Daten Jetzt: ActiveRecord::Base = Daten, Service = Businesslogik
  36. 36. Echte Businesslogik ist in der Regel deutlich komplexer Bisher: ActiveRecord::Base = Businesslogik + Daten Jetzt: ActiveRecord::Base = Daten, Service = Businesslogik inkl. einfacher Validierung etc.
  37. 37. Verteilung Such Service Suchauftrag Service Rails Frontend Authentifizierungs Statistic Service Service
  38. 38. Verteilung Such Service ? Suchauftrag Rails Service ? Frontend Authentifizierungs Statistic Service ? Service
  39. 39. Verteilung Such Service ? Suchauftrag Rails Service Thrift-RPC ? Frontend Authentifizierungs Statistic Service ? Service
  40. 40. Thrift-RPC?!? Grafik © by Martin Laksman, 2003
  41. 41. Thrift-RPC RPC-Framework von Facebook entwickelt Mittlerweile Apache Incubator Projekt: http://incubator.apache.org/thrift/ Ziel: Verlässliche und effiziente Kommunikation verteilter Systemkomponenten
  42. 42. Thrift-Architektur Transport Protocol Processor Service-Implementierung
  43. 43. Thrift-Architektur Transport Thrift- Compiler Protocol Processor Thrift- Gem Service-Implementierung
  44. 44. Thrift Service Definition erstellen
  45. 45. Thrift Service Service Stubs Definition generieren erstellen
  46. 46. Thrift Service Service Stubs Service Definition generieren implementieren erstellen
  47. 47. Thrift Service Transport- Service Stubs Service Definition Schicht generieren implementieren erstellen realisieren
  48. 48. Thrift Service Transport- Service Stubs Service Service Definition Schicht generieren implementieren ansprechen erstellen realisieren
  49. 49. Thrift Service Transport- Service Stubs Service Service Definition generieren implementieren Schicht ansprechen realisieren erstellen
  50. 50. Thrift Service-Definition namespace rb UserService enum UserStates { VERIFIED = 1, UNVERIFIED = 2, BLOCKED = 3 } struct User { 1: string firstname, 2: string lastname, 3: i32 age, 4: string email, 5: string username, 6: UserStates state } exception AuthenticationError { 1: string message, 2: list<string> backtrace } service AuthenticationService { User authenticate_user(1:string username, 2:string password) throws (1:AuthenticationError ae) }
  51. 51. Thrift Service-Definition namespace rb UserService enum UserStates { VERIFIED = 1, ✓ Namespaces UNVERIFIED = 2, BLOCKED = 3 } struct User { 1: string firstname, 2: string lastname, 3: i32 age, 4: string email, 5: string username, 6: UserStates state } exception AuthenticationError { 1: string message, 2: list<string> backtrace } service AuthenticationService { User authenticate_user(1:string username, 2:string password) throws (1:AuthenticationError ae) }
  52. 52. Thrift Service-Definition namespace rb UserService enum UserStates { VERIFIED = 1, ✓ Namespaces UNVERIFIED = 2, } BLOCKED = 3 ✓ Enums struct User { 1: string firstname, 2: string lastname, 3: i32 age, 4: string email, 5: string username, 6: UserStates state } exception AuthenticationError { 1: string message, 2: list<string> backtrace } service AuthenticationService { User authenticate_user(1:string username, 2:string password) throws (1:AuthenticationError ae) }
  53. 53. Thrift Service-Definition namespace rb UserService enum UserStates { VERIFIED = 1, ✓ Namespaces UNVERIFIED = 2, } BLOCKED = 3 ✓ Enums struct User { 1: string firstname, ✓ Primitive Datentypen 2: string lastname, 3: i32 age, 4: string email, 5: string username, 6: UserStates state } exception AuthenticationError { 1: string message, 2: list<string> backtrace } service AuthenticationService { User authenticate_user(1:string username, 2:string password) throws (1:AuthenticationError ae) }
  54. 54. Thrift Service-Definition namespace rb UserService enum UserStates { VERIFIED = 1, ✓ Namespaces UNVERIFIED = 2, } BLOCKED = 3 ✓ Enums struct User { 1: string firstname, ✓ Primitive Datentypen 2: string lastname, 3: i32 age, 4: string email, 5: string username, ✓ Komplexe Typen 6: UserStates state } exception AuthenticationError { 1: string message, 2: list<string> backtrace } service AuthenticationService { User authenticate_user(1:string username, 2:string password) throws (1:AuthenticationError ae) }
  55. 55. Thrift Service-Definition namespace rb UserService enum UserStates { VERIFIED = 1, ✓ Namespaces UNVERIFIED = 2, } BLOCKED = 3 ✓ Enums struct User { 1: string firstname, ✓ Primitive Datentypen 2: string lastname, 3: i32 age, 4: string email, 5: string username, ✓ Komplexe Typen 6: UserStates state } ✓ Exceptions exception AuthenticationError { 1: string message, 2: list<string> backtrace } service AuthenticationService { User authenticate_user(1:string username, 2:string password) throws (1:AuthenticationError ae) }
  56. 56. Thrift Service-Definition namespace rb UserService enum UserStates { VERIFIED = 1, ✓ Namespaces UNVERIFIED = 2, } BLOCKED = 3 ✓ Enums struct User { 1: string firstname, ✓ Primitive Datentypen 2: string lastname, 3: i32 age, 4: string email, 5: string username, ✓ Komplexe Typen 6: UserStates state } ✓ Exceptions exception AuthenticationError { ✓ Services 1: string message, 2: list<string> backtrace } service AuthenticationService { User authenticate_user(1:string username, 2:string password) throws (1:AuthenticationError ae) }
  57. 57. Walkthrough: Statistik-Service
  58. 58. namespace rb Pkwde.StatisticsModule struct Statistic { 1:string name, 2:i32 count } service StatisticsService { list<Statistic> statistic_for(1:list<string> element_names), oneway void increment(1:list<string> elements) } $> thrift --gen rb:rails -o ./app/thrift config/statistics_service.thrift app/thrift `-- gen-rb `-- pkwde `-- statistics_module |-- statistics_service.rb |-- statistics_service_constants.rb `-- statistics_service_types.rb
  59. 59. class StatisticsHandler def statistic_for(element_names) Statistic.find_all_by_name(element_names).map do |statistic| Pkwde::StatisticsModule::Statistic.new(:name => statistic.name, :count => statistic.count) end end def increment(elements) elements.each do |element| Statistic.find_or_create_by_name(element).increment!(:count) end end end
  60. 60. Service Provider require 'thrift/server/rack_middleware' ActionController::Dispatcher.middleware.insert_before(Rails::Rack::Metal, Thrift::RackMiddleware, { :processor => Pkwde::StatisticsModule::StatisticsService::Processor.new(StatisticsHandler.new), StatisticsHandler.new :hook_path => "/statistics" })
  61. 61. Service Provider require 'thrift/server/rack_middleware' ActionController::Dispatcher.middleware.insert_before(Rails::Rack::Metal, Thrift::RackMiddleware, { :processor => Pkwde::StatisticsModule::StatisticsService::Processor.new(StatisticsHandler.new), StatisticsHandler.new :hook_path => "/statistics" })
  62. 62. Service Provider require 'thrift/server/rack_middleware' ActionController::Dispatcher.middleware.insert_before(Rails::Rack::Metal, Thrift::RackMiddleware, { :processor => Pkwde::StatisticsModule::StatisticsService::Processor.new(StatisticsHandler.new), StatisticsHandler.new :hook_path => "/statistics" }) Service Client statistics_client = ThriftClient.new(:url => "http://localhost:3000/statistics", :client_class => Pkwde::StatisticsModule::StatisticsService::Client)
  63. 63. Service Provider require 'thrift/server/rack_middleware' ActionController::Dispatcher.middleware.insert_before(Rails::Rack::Metal, Thrift::RackMiddleware, { :processor => Pkwde::StatisticsModule::StatisticsService::Processor.new(StatisticsHandler.new), StatisticsHandler.new :hook_path => "/statistics" }) http://github.com/railsbros/thrift Service Client statistics_client = ThriftClient.new(:url => "http://localhost:3000/statistics", :client_class => Pkwde::StatisticsModule::StatisticsService::Client) http://github.com/railsbros/thrift4rails
  64. 64. Was ist Eigentlich mit einer Lösung die mehr Ruby ist …? Grafik © by Martin Laksman, 2003
  65. 65. Sneak Preview Hoth::Services.define do service :increment_statistics, :params => [[:element]], :returns => nil, :endpoint => :statistics_module service :statistic_for, :params => [[:element_name]], :returns => [:statistic], :endpoint => :statistics_module end Service-Definition
  66. 66. Sneak Preview Hoth::ServiceDeployment.define do service_module :statistics_module do env :test, { :endpoint => Hoth::Endpoint.new(:host => 'localhost', :port => 3000), :mongrel_servers => 2, :mongrel_start_port => 9001 } path "services/search_service" end end Deployment-Definition
  67. 67. Sneak Preview ENV["LOCAL"] = "false" require 'hoth' require 'deployment_definition' require 'service_definition' Hoth::Services.increment_statistics([statistic_object], event) Hoth::Services.statistic_of_cars([23]).inspect Service-Client
  68. 68. ENV["LOCAL"] = "true" require 'hoth' require 'deployment_definition' require 'service_definition' class IncrementStatisticsImpl def self.execute(elements) elements.each do |element| Statistic.find_or_create_by_name(element).increment!(:count) end end end class StatisticForImpl def self.execute(element_names) Statistic.find_all_by_name(element_names) end end app = lambda {|env| [200, {'Content-Type' => 'text/plain'}, ""]} run Hoth::ServiceProvider.new(app) Service-Provider
  69. 69. About Me … Rubyist und Rails-Enthusiast seit Ende 2005 Software-Entwickler bei pkw.de seit 2007 Twitter: @railsbros_dirk GitHub: http://github.com/pkwde Blog: http://railsbros.de
  70. 70. Kann ich das gleiche nicht durch ein gutes OO-Design realisieren? Grafik © by Martin Laksman, 2003
  71. 71. SOA vs. OOP SOA ersetzt OOP nicht! SOA setzt auf einer anderen Ebene an OOP Design Prinzipien finden jedoch keine Anwendung für SOA Fokus auf die Abbildung von Geschäftsprozessen Ein Service kann intern immer noch OOP sein

×