Rails goes SOA

1,074 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
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,074
On SlideShare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
10
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide
  • Einleitung über mich und pkw.de
  • Service Registry: muss nicht immer ein System sein! Kann im ersten Schritt auch nur eine ausgedruckte Liste sein.
  • Inkrementelles Vorgehen!!
  • Suchkriterien mappen nicht ohne weiteres auf Form-Parameter
  • Suchkriterien mappen nicht ohne weiteres auf Form-Parameter
  • ist dabei sehr leichtgewichtig, zB im Vergleich zu SOAP
    -> Dadurch aber auch nicht so mächtig
    -> Für viele Anforderungen aber ausreichend
  • DSL in C-ähnlicher Syntax

    Versionierung der Schnittstelle!!!
  • DSL in C-ähnlicher Syntax

    Versionierung der Schnittstelle!!!
  • DSL in C-ähnlicher Syntax

    Versionierung der Schnittstelle!!!
  • DSL in C-ähnlicher Syntax

    Versionierung der Schnittstelle!!!
  • DSL in C-ähnlicher Syntax

    Versionierung der Schnittstelle!!!
  • DSL in C-ähnlicher Syntax

    Versionierung der Schnittstelle!!!
  • DSL in C-ähnlicher Syntax

    Versionierung der Schnittstelle!!!
  • DSL in C-ähnlicher Syntax

    Versionierung der Schnittstelle!!!
  • DSL in C-ähnlicher Syntax

    Versionierung der Schnittstelle!!!
  • DSL in C-ähnlicher Syntax

    Versionierung der Schnittstelle!!!
  • DSL in C-ähnlicher Syntax

    Versionierung der Schnittstelle!!!
  • DSL in C-ähnlicher Syntax

    Versionierung der Schnittstelle!!!
  • DSL in C-ähnlicher Syntax

    Versionierung der Schnittstelle!!!
  • DSL in C-ähnlicher Syntax

    Versionierung der Schnittstelle!!!
  • DSL in C-ähnlicher Syntax

    Versionierung der Schnittstelle!!!
  • DSL in C-ähnlicher Syntax

    Versionierung der Schnittstelle!!!
  • DSL in C-ähnlicher Syntax

    Versionierung der Schnittstelle!!!
  • DSL in C-ähnlicher Syntax

    Versionierung der Schnittstelle!!!
  • oneway -> Hier noch auf Doku verweisen
  • Hier noch ohne Software-Service-Registry
  • Hier noch ohne Software-Service-Registry
  • Hier noch ohne Software-Service-Registry
  • Hier noch ohne Software-Service-Registry
  • Hier noch ohne Software-Service-Registry
  • Thrift hat ein statisches Typensystem und Ruby ein dynamisches, dass kann zu Problemen führen ...

    Stichwort: Service-Registry
  • 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

    ×