Design und Implementierung eines generischen QoS
Transcrição
Design und Implementierung eines generischen QoS
Fachhochschule Wiesbaden Fachbereich Design Informatik Medien Studiengang Allgemeine Informatik Diplomarbeit zur Erlangung des akademischen Grades Diplom-Informatiker/in (FH) Design und Implementierung eines generischen QoS-Proxys für SOA Dienste vorgelegt von Michael Frey am 08. Dezember 2008 Referent: Prof. Dr. Kröger Korreferent: Dipl.-Inform. (FH), M.Sc. Markus Schmid II Erklärung Ich versichere, dass ich die Diplomarbeit selbstständig verfasst und keine anderen als die angegebenen Hilfsmittel benutzt habe. Wiesbaden, 08.12.2008 Michael Frey Hiermit erkläre ich mein Einverständnis mit den im Folgenden aufgeführten Verbreitungsformen dieser Diplomarbeit: Verbreitungsform Einstellung der Arbeit in die Bibliothek der FHW Veröffentlichung des Titels der Arbeit im Internet Veröffentlichung der Arbeit im Internet Wiesbaden, 08.12.2008 ja nein √ √ √ Michael Frey III IV Inhaltsverzeichnis 1 Einleitung 1 2 Grundlagen 5 2.1 Web-Service-Agreement-Protokoll . . . . . . . . . . . . . . . . . . . . . 5 2.1.1 Einleitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2.1.2 Architektur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 2.1.2.1 Struktur eines Agreements . . . . . . . . . . . . . . . 8 2.1.2.2 Struktur eines Agreement Templates . . . . . . . . . . 15 2.1.2.3 Agreement-Zustände . . . . . . . . . . . . . . . . . . 16 2.1.3 Quality-of-Service-Erweiterung . . . . . . . . . . . . . . . . . . 17 2.1.4 Beispiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 Service Component Architecture . . . . . . . . . . . . . . . . . . . . . . 20 2.2.1 Einleitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 2.2.2 Architektur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 2.2.3 Beispiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 2.2.4 Apache Tuscany SCA . . . . . . . . . . . . . . . . . . . . . . . 33 Queueing-Strategien . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 2.3.1 Einleitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 2.3.2 Strategien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 2.3.2.1 Multi Band Priority Queueing . . . . . . . . . . . . . . 36 2.3.2.2 Stochastic Fairness Queueing . . . . . . . . . . . . . . 37 2.3.2.3 Weighted Fair Queuing . . . . . . . . . . . . . . . . . 38 2.3.2.4 Class Based Queueing . . . . . . . . . . . . . . . . . . 39 2.3.2.5 Leaky Bucket . . . . . . . . . . . . . . . . . . . . . . 39 2.3.2.6 Hierarchical Token Bucket . . . . . . . . . . . . . . . 40 2.2 2.3 V 3 Analyse 41 3.1 Anforderungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 3.1.1 Integration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 3.1.2 Queueing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 3.1.3 Monitoring und Konfiguration . . . . . . . . . . . . . . . . . . . 44 Integration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 3.2.1 Erweiterung der SCA . . . . . . . . . . . . . . . . . . . . . . . . 45 3.2.2 Erweiterung von Tuscany . . . . . . . . . . . . . . . . . . . . . 49 3.2.3 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . 56 Queueing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 3.3.1 Untersuchung der Queueing-Strategien . . . . . . . . . . . . . . 56 3.3.2 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . 58 Monitoring und Konfiguration . . . . . . . . . . . . . . . . . . . . . . . 59 3.4.1 Java Management Extensions . . . . . . . . . . . . . . . . . . . 60 3.4.2 Monitoring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 3.4.2.1 Kenngrößen . . . . . . . . . . . . . . . . . . . . . . . 62 3.4.2.2 Instrumentierung . . . . . . . . . . . . . . . . . . . . . 63 3.4.3 Konfiguration . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 3.4.4 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . 66 3.2 3.3 3.4 4 Design 67 4.1 Architekturüberblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 4.2 Queueing-Subsystem . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 4.2.1 Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 4.2.2 Beschreibung der Klassen . . . . . . . . . . . . . . . . . . . . . 71 4.2.3 Beispiel: Weighted-Fair-Queueing-Algorithmus . . . . . . . . . . 75 Monitoring-Subsystem . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 4.3.1 Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 4.3.2 Beschreibung der Klasse . . . . . . . . . . . . . . . . . . . . . . 77 WS-Agreement-Subsystem . . . . . . . . . . . . . . . . . . . . . . . . . 80 4.4.1 Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 4.4.2 Beschreibung der Klasse . . . . . . . . . . . . . . . . . . . . . . 81 Konfigurationssubsystem . . . . . . . . . . . . . . . . . . . . . . . . . . 81 4.3 4.4 4.5 VI 4.6 4.7 4.8 5 4.5.1 Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 4.5.2 Konfiguration des QoS-Proxys . . . . . . . . . . . . . . . . . . . 83 4.5.2.1 Initialisierung . . . . . . . . . . . . . . . . . . . . . . 83 4.5.2.2 Management . . . . . . . . . . . . . . . . . . . . . . . 85 4.5.3 Beschreibung der Klassen . . . . . . . . . . . . . . . . . . . . . 85 4.5.4 Ablauf der Kommunikation . . . . . . . . . . . . . . . . . . . . 91 Integrationssubsystem . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 4.6.1 Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 4.6.2 Beschreibung der Klassen . . . . . . . . . . . . . . . . . . . . . 93 Proxy-Subsystem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 4.7.1 Anpassung einer SCA-Anwendung . . . . . . . . . . . . . . . . 95 4.7.2 Initialisierung der Subsysteme . . . . . . . . . . . . . . . . . . . 96 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 Implementierung 101 5.1 Umgebung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 5.2 Namenskonventionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 5.3 Logging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 5.4 Queueing-Subsystem . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 5.5 5.6 5.7 5.8 5.9 5.4.1 Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 5.4.2 Beschreibung der Implementierung . . . . . . . . . . . . . . . . 104 Monitoring-Subsystem . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 5.5.1 Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 5.5.2 Beschreibung der Implementierung . . . . . . . . . . . . . . . . 107 WS-Agreement-Subsystem . . . . . . . . . . . . . . . . . . . . . . . . . 108 5.6.1 Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 5.6.2 Beschreibung der Implementierung . . . . . . . . . . . . . . . . 109 Konfigurationsubsystem . . . . . . . . . . . . . . . . . . . . . . . . . . 110 5.7.1 Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 5.7.2 Beschreibung der Implementierung . . . . . . . . . . . . . . . . 111 Integrationssubsystem . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 5.8.1 Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 5.8.2 Beschreibung der Implementierung . . . . . . . . . . . . . . . . 113 Proxy-Subsystem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 5.10 Implementierungsaufwand . . . . . . . . . . . . . . . . . . . . . . . . . 118 5.11 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 VII 6 Bewertung 123 6.1 Bewertung der Architektur . . . . . . . . . . . . . . . . . . . . . . . . . 123 6.2 Bewertung der Leistungsfähigkeit . . . . . . . . . . . . . . . . . . . . . 124 6.2.1 Versuchsaufbau . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 6.2.2 Auswertung der Messungen . . . . . . . . . . . . . . . . . . . . 125 6.2.3 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . 126 7 Zusammenfassung 127 8 Literaturverzeichnis 131 A Abkürzungen 137 B Messwerttabellen für den QoS-Proxy 141 C Inhalt des Datenträgers 143 VIII Abbildungsverzeichnis 2.1 Sequenzdiagramm: Agreement Creation Process . . . . . . . . . . . . . . 8 2.2 Agreement Zustände aus Sicht des Initiators . . . . . . . . . . . . . . . . 16 2.3 Beziehung von Component und Implementation (nach [BBB+ 07]) . . . . 24 2.4 SCA Service Symbol (nach [BBB+ 07]) . . . . . . . . . . . . . . . . . . . 27 2.5 SCA Reference Symbol (nach [BBB+ 07]) . . . . . . . . . . . . . . . . . 29 2.6 SCA Component Diagramm (nach [BBB+ 07]) . . . . . . . . . . . . . . . 29 2.7 Tuscany-SCA-Java-Architektur (nach [Fou08]) . . . . . . . . . . . . . . 34 2.8 Tuscany-SCA-Contribution-Modell (nach [Fou08]) . . . . . . . . . . . . 35 2.9 Graphische Repräsentation der Begriffe der Bedientheorie . . . . . . . . 37 2.10 Multi Band Priority Queueing . . . . . . . . . . . . . . . . . . . . . . . 37 2.11 Stochastic Fairness Queueing . . . . . . . . . . . . . . . . . . . . . . . . 38 2.12 Weighted Fair Queuing . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 3.1 Anwendungsfalldiagramm: Berücksichtigung QoS-Anforderungen . . . . 42 3.2 Anwendungsfalldiagramm: Umsetzung QoS-Anforderungen . . . . . . . . 42 3.3 Anwendungsfalldiagramm: Service Level Management . . . . . . . . . . 43 3.4 Calculator Service Component . . . . . . . . . . . . . . . . . . . . . . . 48 3.5 Calculator Service Component mit QoS-Proxy Component . . . . . . . . 49 3.6 Tuscany-SCA-Runtime-Wire-Modell (nach [Fou08]) . . . . . . . . . . . . 50 3.7 Integration Policy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 3.8 Integration Proxy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 3.9 Integration Proxy mit Nachrichten-Queue . . . . . . . . . . . . . . . . . 55 3.10 Integration Proxy mit Thread-Queue . . . . . . . . . . . . . . . . . . . . 55 3.11 Java-Management-Extension-Architektur . . . . . . . . . . . . . . . . . 60 3.12 Instrumentierung von Apache Tuscany . . . . . . . . . . . . . . . . . . . 63 3.13 Kommunikation zwischen QoS-Proxy, WSAG4J und einem Client . . . . . 65 IX 3.14 Remote-Method-Invocation-Architektur (nach [Sun04]) . . . . . . . . . . 66 4.1 Grobarchitektur des QoS-Proxy . . . . . . . . . . . . . . . . . . . . . . . 67 4.2 Klassendiagramm: Überblick Queueing-Subsystem . . . . . . . . . . . . 70 4.3 Klassendiagramm: Item . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 4.4 Klassendiagramm: Queue . . . . . . . . . . . . . . . . . . . . . . . . . . 72 4.5 Klassendiagramm: QueueStatistic . . . . . . . . . . . . . . . . . . . . . 73 4.6 Klassendiagramm: ItemList . . . . . . . . . . . . . . . . . . . . . . . . . 73 4.7 Klassendiagramm: Strategy . . . . . . . . . . . . . . . . . . . . . . . . . 74 4.8 Klassendiagramm: LeakyBucket . . . . . . . . . . . . . . . . . . . . . . 74 4.9 Klassendiagramm: Weighted-Fair-Queueing-Algorithmus . . . . . . . . . 75 4.10 Sequenzdiagramm: Bearbeitung eines Interceptors . . . . . . . . . . . . 77 4.11 Klassendiagramm: Statistic . . . . . . . . . . . . . . . . . . . . . . . . . 78 4.12 Klassendiagramm zur QoS-Proxy-WSAG4J Kommunikation . . . . . . . . 81 4.13 Überblick über das Konfigurationssubsystem . . . . . . . . . . . . . . . 82 4.14 Klassendiagramm: ICallback und Callback . . . . . . . . . . . . . . . . 86 4.15 Klassendiagramm: ServiceClass . . . . . . . . . . . . . . . . . . . . . . 86 4.16 Klassendiagramm: ServiceLevelAgreement . . . . . . . . . . . . . . . . 87 4.17 Klassendiagramm: ServiceLevelAgreementList . . . . . . . . . . . . . . 88 4.18 Klassendiagramm: ServiceLevelAgreementFile . . . . . . . . . . . . . . 88 4.19 Klassendiagramm: ConfigurationFile . . . . . . . . . . . . . . . . . . . 89 4.20 Klassendiagramm: ConfigurationFile . . . . . . . . . . . . . . . . . . . 89 4.21 Klassendiagramm: Manager . . . . . . . . . . . . . . . . . . . . . . . . 90 4.22 Sequenzdiagramm: Kommunikation mit WSAG4J-System/QoS-Proxy . . . 92 4.23 Klassendiagramm: ProxyPolicyProcessor . . . . . . . . . . . . . . . . . 93 4.24 Klassendiagramm: ProxyPolicyInterceptor . . . . . . . . . . . . . . . . . 95 4.25 Klassendiagramm: Proxy . . . . . . . . . . . . . . . . . . . . . . . . . . 97 4.26 Sequenzdiagramm: Berücksichtigung QoS-Anforderungen . . . . . . . . 100 6.1 Aufbau der Versuche für die Leistungsbewertung . . . . . . . . . . . . . 125 X Tabellenverzeichnis 3.1 Bewertung der Queueing-Strategien . . . . . . . . . . . . . . . . . . . . 58 3.2 Berechnung der Kenngrößen im QoS-Proxy . . . . . . . . . . . . . . . . 64 5.1 Implementierungsaufwand sortiert nach Subsystemen . . . . . . . . . . . 119 6.1 Mittelwerte der Versuch 1 bis 3 . . . . . . . . . . . . . . . . . . . . . . . 126 B.1 Messwerte für Versuch 1 . . . . . . . . . . . . . . . . . . . . . . . . . . 141 B.2 Messwerte für Versuch 2 . . . . . . . . . . . . . . . . . . . . . . . . . . 141 B.3 Messwerte für Versuch 3 . . . . . . . . . . . . . . . . . . . . . . . . . . 142 XI XII Verzeichnis der Quellcodes 2.1 Agreement-XML-Schema . . . . . . . . . . . . . . . . . . . . . . . . . . 8 2.2 AgreementContextType-XML-Schema . . . . . . . . . . . . . . . . . . . 9 2.3 AgreementRoleType-XML-Schema . . . . . . . . . . . . . . . . . . . . . 9 2.4 TermCompositorType-XML-Schema . . . . . . . . . . . . . . . . . . . . 10 2.5 ServiceDescriptionTermType-XML-Schema . . . . . . . . . . . . . . . . 11 2.6 ServiceReferenceTermType-XML-Schema . . . . . . . . . . . . . . . . . 11 2.7 ServicePropertiesType-XML-Schema . . . . . . . . . . . . . . . . . . . . 11 2.8 Variable-XML-Schema . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.9 GuaranteeTermType-XML-Schema . . . . . . . . . . . . . . . . . . . . . 12 2.10 ServicelLevelObjective-XML-Schema . . . . . . . . . . . . . . . . . . . 13 2.11 Business-Value-List-XML-Schema . . . . . . . . . . . . . . . . . . . . . 13 2.12 Penalty-XML-Schema . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 2.13 Preference-XML-Schema . . . . . . . . . . . . . . . . . . . . . . . . . . 14 2.14 Template-XML-Schema . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 2.15 Item-XML-Schema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 2.16 QoS-XML-Schema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 2.17 Webservice-Agreement-Beispiel . . . . . . . . . . . . . . . . . . . . . . 19 2.18 Property-XML-Schema . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 2.19 Implementation-XML-Schema . . . . . . . . . . . . . . . . . . . . . . . 23 2.20 Component-Type-XML-Schema . . . . . . . . . . . . . . . . . . . . . . . 24 2.21 ConstrainingType-XML-Schema . . . . . . . . . . . . . . . . . . . . . . 24 2.22 Binding-XML-Schema . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 2.23 Interface-Java-XML-Schema . . . . . . . . . . . . . . . . . . . . . . . . 26 2.24 Service-XML-Schema . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 2.25 Wire-XML-Schema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 XIII 2.26 Reference-XML-Schema . . . . . . . . . . . . . . . . . . . . . . . . . . 28 2.27 Component-XML-Schema . . . . . . . . . . . . . . . . . . . . . . . . . . 29 2.28 Composite-XML-Schema . . . . . . . . . . . . . . . . . . . . . . . . . . 30 2.29 SCA-Interface-XML-Schema . . . . . . . . . . . . . . . . . . . . . . . . 31 2.30 SCA-Interface-Java-XML-Schema . . . . . . . . . . . . . . . . . . . . . 32 2.31 Calculator Composite . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 3.1 Beispiel-composite mit JDKLoggingPolicy . . . . . . . . . . . . . . . 51 3.2 Beispiel-defintions.xml der JDKLoggingPolicy . . . . . . . . . . . 52 4.1 QoS-Proxy-XML-Schema der Konfigurationsdatei . . . . . . . . . . . . . 83 4.2 XML-Schema der Service-Level-Agreement-Datei . . . . . . . . . . . . . 84 4.3 Beispiel: Auszug aus der Datei definitions.xml . . . . . . . . . . . 94 4.4 Beispiel: Angepasste composite-Datei einer SCA-Anwendung . . . . . 96 5.1 Beispiel: Konfigurationsdatei für log4j . . . . . . . . . . . . . . . . . . . 102 5.2 Konfiguration: StAXArtifactProcessor-Datei . . . . . . . . . . . . . . . . 114 5.3 Konfiguration: ProxyPolicyProviderFactory-Datei . . . . . . . . . . . . . 115 5.4 definitions.xml-Datei des QoS-Proxys . . . . . . . . . . . . . . . 116 5.5 Konfiguration: SCADefinitionsProvider-Datei . . . . . . . . . . . . . . . 116 5.6 Logging: Initialisierung des QoS-Proxys . . . . . . . . . . . . . . . . . . 118 5.7 Logging: Bearbeiten einer Web-Service-Anfragen . . . . . . . . . . . . . 120 5.8 Logging: Wartende Web-Service-Anfragen . . . . . . . . . . . . . . . . . 121 XIV Vorwort Diese Diplomarbeit entstand im Labor für Verteilte Systeme an der Fachhochschule Wiesbaden. Ich möchte mich hiermit bei Herrn Prof. Dr. Kröger sowie bei Herrn Schmid für die hervorragende Unterstützung und Betreuung während der Erstellung dieser Arbeit bedanken. Ein besonderer Dank gilt meiner Familie, die während des gesamten Studiums immer hinter mir stand und mir sowohl finanziell als auch moralisch den Rücken frei gehalten hat. Wiesbaden, im Dezember 2008 Michael Frey XV XVI Kapitel 1 Einleitung Im Zuge der Globalisierung unterliegen Unternehmen neuen Anforderungen in der Geschäftswelt. Neue Märkte und Mitbewerber erfordern eine Transformation von Geschäftsprozessen auf IT- und TK-Technologien. Ziel der Transformation ist die Nutzung der Spezialisierungs-, Rationalisierungs- und Anpassungsmöglichkeiten dieser Technologien zur Effizienzsteigerung [Kö07]. Realisiert wird diese Entwicklung durch den Einsatz unternehmensweiter verteilter Anwendungen. Diese Anwendungen werden auch als Geschäftsanwendungen bezeichnet. Zu den Anforderungen an Geschäftsanwendungen gehören die Integration in bereits im Unternehmen existierende Systeme, Flexibilität bei der Abbildung von Geschäftsprozessen und Interoperabilität mit den Systemen kooperierender Unternehmen. Mit der zunehmenden Durchdringung von Unternehmen mit Geschäftsanwendungen und der Integration unterschiedlicher Geschäftsprozesse in Geschäftsanwendungen steigt die Anzahl der an einer Anwendung beteiligten Anwendungskomponenten. Restrukturierungen, Unternehmenszukäufe und Verkäufe von Unternehmensteilen erfordern die Anpassung der bestehenden Software und erhöhen die Komplexität der gesamten Softwarearchitektur. Viele Unternehmen tendieren mittlerweile dazu, im Rahmen der Kostensenkung den Betrieb und das Management von Geschäftsanwendungen, an externe Dienstleister auszulagern. Dieser Prozess wird auch als Outsourcing bezeichnet. Eine Umsetzungsansatz für diese Anforderungen bietet das Modell der Serviceorientierten Architektur (SOA) [Erl07]. Das Modell beschreibt ein Paradigma für die Strukturierung und Nutzung von verteilter Funktionalität, die von unterschiedlichen Benutzern verantwortet wird. Bestehende Geschäftsanwendungen und ihre Schnittstellen werden in Dienste gekapselt. Die Dienste einer SOA bieten damit standardisierte, plattform- und programmiersprachenunabhängige Schnittstellen. 1 Kapitel 1. Einleitung Vorteil von SOA-basierten Anwendungen ist die eindeutige Spezifikation von Schnittstellen. SOA-basierte Geschäftsanwendungen erleichtern das Outsourcing, da durch die Spezifikation von Schnittstellen eine klare Trennung in Dienste vorgenommen werden kann. Die Trennung in Dienste ist auch für große Unternehmen interessant, deren Anwendungen unter Umständen verteilt in verschieden Abteilungen laufen. Geschäftsanwendungen sind kritisch für den Unternehmenserfolg und erfordern damit vertragliche Zusicherungen zwischen einem Unternehmen und einem Outsourcing-Dienstleister oder zwischen einem Unternehmen und seinen Abteilungen. Für ein Kunden sind dabei nicht-funktionale Anforderungen wie Zusicherungen an die Dienstgüte (Quality of Service, QoS) [Tan02] von besonderer Bedeutung. Über die Dienstgüte eines Dienstes lassen sich unterschiedliche Dienstgüteklassen definieren. Je höher die Anforderungen an einen Dienst, desto höher die Wertigkeit der Dienstgüteklasse. Outsourcing-Dienstleister oder Unternehmen können zwischen verschiedenen Kunden eines Dienstes unterscheiden und erhalten ein Abrechnungsmodell auf Basis von Dienstgüteklassen für einen Dienst. Die wenigsten Implementierungen unterstützen jedoch Zusicherungen an die Dienstgüte einer Geschäftsanwendung. Das Anpassen einer bestehenden SOA-Anwendung um eine Dienstgütefunktionalität kann als zu aufwendig betrachtet werden. Wünschenswert wäre eine generische Lösung für unterschiedliche Dienste. Eine solche Lösung soll sich transparent integrieren lassen um die Schnittstellen gegenüber einem Nutzer zu erhalten. Ein solcher generische und transparente QoS-Proxy erfordert keine Anpassung an einer Geschäftsanwendung und keine Anpassung am System des Teilnehmers. Das Ziel dieser Arbeit ist der Entwurf und die Implementierung eines generischen QoSProxys für SOA-Dienste. Der QoS-Proxy sollte generisch implementiert werden um eine Kombination mit beliebigen SOA-basierten Anwendungen zu erleichtern. Weiterhin sollen verschiedene Priorisierungsstrategien auf Ihre Eignung zur Umsetzung von Dienstgütekriterien untersucht werden und in dem QoS-Proxy integriert werden. Um die Integration des QoS-Proxys in eine bestehende SLM-Umgebung zu erleichtern, solle das Monitoring und die Konfiguration über eine einheitliche Schnittstelle erfolgen. Im folgenden Kapitel wird in grundlegende Technologien eingeführt. Zunächst wird detailliert die Web-Service-Agreement-Spezifikation betrachtet. Im Anschluß wird die Architektur der Service Component Architecture vorgestellt. Das Kapitel endet mit einer kurze Einführung in Begriffe der Bedientheorie und stellt unterschiedliche QueueingStrategien vor. In Kapitel 3 werden zunächst die Anforderungen an einen generischen QoS-Proxy formuliert. Auf Grundlage der Anforderungen wird die Service Component Architecture 2 Kapitel 1. Einleitung auf mögliche Ansätze zur Integration des QoS-Proxys untersucht. Weiterhin werden die im Grundlagenkapitel vorgestellten Queueing-Strategien auf ihre Tauglichkeit zur Umsetzung von Dienstgüteeigenschaften analysiert. Das Kapitel endet mit einer Betrachtung von möglichen Ansätzen zum Monitoring und der Konfiguration des Proxys. Diese Betrachtung schließt das Definieren von Kenngrößen und Identifizieren von Instrumentierungspunkten im Entwurf der Architektur ein. Aufbauend auf der Analyse beschreibt Kapitel 4 einen Entwurf der Architektur des QoSProxys. Zunächst wird dabei aus den im vorherigen Kapitel beschriebenen Anforderungen eine Grobarchitektur formuliert und einzelne Subsysteme identifiziert. Die einzelnen Subsysteme werden nach einer Bottom-Up-Strategie beschrieben. Das Kapitel endet mit einer Zusammenfassung in der ein in der Analyse vorgestellter Anwendungsfall das Zusammenspiel der einzelnen Subsysteme verdeutlicht. In Kapitel 5 wird die verwendete Entwicklungsumgebung und Werkzeuge vorgestellt. Im Anschluß werden die Implementierungsdetails der zuvor entworfenen Subsysteme betrachtet. Kapitel 6 beginnt mit einer architekturellen Bewertung der Implementierung des QoSProxys. Nach der ersten Bewertung wird das Messmodell einer leistungsorientierten Bewertung vorgestellt und entsprechende Messungen durchgeführt. Die Arbeit endet mit einer zusammenfassenden Bewertung und stellt nächste mögliche Implementierungsschritte vor und gibt einen Ausblick auf mögliche weitere Entwicklungen im Bereich Quality of Service für Service-orientierte Architekturen. 3 Kapitel 1. Einleitung 4 Kapitel 2 Grundlagen 2.1 2.1.1 Web-Service-Agreement-Protokoll Einleitung Aufgrund wirtschaftlichen Drucks sind viele Unternehmen gezwungen Kosten einzusparen. Dienstleistungen, die nicht Teil der Kernkompetenzen eines Unternehmens sind, werden ausgelagert. Besonders das Auslagern von IT-Dienstleistungen an Drittanbieter ist zu beobachten [Deb04]. Mit der Auslagerung von Diensten und Teilprozessen an externe Dienstleister enstehen Anforderungen, die in einem vertraglichen Rahmen festgehalten werden müssen. Mit den Jahren haben sich verschiedene Verfahren für die Umsetzung von IT-Service-Management herausgebildet. Diese Strategien werden in der IT Infrastructure Library (ITIL)1 zusammengefasst. Einen Rahmen für das vertragliche Erfassen von Anforderungen an einen Dienst und Teilprozesse bietet das Dienstgütemanagement (Service Level Management, SLM) [BVP06, Lew99]. Das SLM ist Teil der Service-Delivery-Sepzifikation der ITIL [GC01]. Die Service-Delivery-Spezifikation ist verantwortlich für den strategischen Teil des ITGeschäftes einer Firma und stellt IT-Services durch planende und steuernde Prozesse sicher. SLM beschäftigt sich mit der Einhaltung von Dienstgütevereinbarungen. Dienstgütevereinbarungen werden formal in Service Level Agreements (SLAs) zwischen Anbieter und Nutzer eines Services vereinbart. Das SLA, als vertragliches Rahmenwerk, besteht aus 1 Homepage der ITIL: http://www.itil-officialsite.com/home/home.asp 5 2.1. Web-Service-Agreement-Protokoll Kapitel 2. Grundlagen Dienstgüteparametern, die in Form von SLA-Parametern spezifiziert werden. Um die Einhaltung der SLAs festzustellen, muss das System überwacht werden. Für die technische Überwachung sind insbesondere Dienstgüteparameter relevant, welche sich auf die Verfügbarkeit und Performanz eines Services beziehen. Beispiele für solche Parameter sind der Durchsatz und die Antwortzeit eines Services. Der Durchsatz beschreibt, wieviele Anfragen innnerhalb einer bestimmten Zeitspanne verarbeitet werden. Die Antwortzeit wird definiert als die Zeit, die ein Service benötigt, um die Anfrage eines Clients zu beantworten. In sogenannten Service Level Objectives (SLOs) werden zulässige Wertebereiche für diese Dienstgüteparameter definiert. Neben der Pflege und ständige Verbesserung der mit einem Kunden vereinbarten IT-Services, gehört zu den Aufgaben des SLMs, die definierten SLA-Parameter und ihre SLOs permanent zu überwachen. Die technische Grundlage für die Realisierung von SLM bildet daher eine Management-Infrastruktur. Mit WS-Agreement soll im folgenden Abschnitt eine Spezifikation vorgestellt werden, die einen Teilansatz für die technische Umsetzung von SLM bietet. 2.1.2 Architektur Web Services Agreement (WS-Agreement) ist eine Spezifikation des Open Grid Forums (OGF)1 und definiert ein Web-Service-basiertes Protokoll zur Aushandlung von Vereinbarungen (Agreements) zwischen zwei Partnern [ACD+ 07]. Ein verwandter Ansatz zur technischen Umsetzung findet sich in HPs Open-View-Internet-Services-Anwendung2 , die mit Hilfe der Web Service Management Language ausgedrückte Dienstgüteanforderungen überwacht [SMS+ 02]. Inhalt der WS-Agreement-Spezifikation sind die zur Kommunikation nötigen XML-Schemata und die Beschreibung von Operationen zur Verwaltung des Lebenszyklus von SLAs. SLAs werden in der Regel zwischen einem Anbieter von Services (Service Provider) und einem möglichen Nutzer der Services (Service Consumer) getroffen. Ursprünglich für den Grid-Kontext entwickelt, erlaubt die flexible Architektur, die Spezifikation auch außerhalb dieses Bereiches einzusetzen. Der vorliegende Abschnitt stellt die Architektur näher vor und führt in verschiedene Begriffe ein. Darauf aufbauend wird die Struktur der XMLDokumente beschrieben. Im Anschluss werden die möglichen Zustände zur Lebenszeit eines Agreements betrachtet. Abschließend wird eine Quality-of-Service-Erweiterung für WS-Agreement, die im Labor für Verteilte Systeme3 der FH Wiesbaden entwickelt wurde, 1 Homepage des Open Grid Forums: http://www.ggf.org/ Homepage von HP Internet Services: http://openview.hp.com/products/ovis/index.html 3 Homepage des Labors für Verteilte Systeme: http://wwwvs.informatik.fh-wiesbaden.de 2 6 Kapitel 2. Grundlagen 2.1. Web-Service-Agreement-Protokoll vorgestellt und ein Beispiel-Agreement mit der Erweiterung präsentiert. Zur besseren Abstraktion unterscheidet WS-Agreement zwischen einem Agreement und dem Service Layer. Der Agreement Layer offeriert eine Web-Services-Schnittstelle zum Erzeugen, Beobachten und Verwalten von Agreements. Der Service Layer repräsentiert den Service innerhalb der Architektur. Innerhalb der Architektur von WS-Agreement unterscheidet man zwischen verschiedenen Teilnehmer-Rollen. Neben dem Service Consumer und Service Provider existiert der Initiator. Der Initiator erzeugt und verwaltet in Bezug auf die Verfügbarkeit eines Services die Agreements eines Services. Dabei ist die Rolle des Initiators nicht auf den Service Provider oder den Service Consumer festgelegt. Grundlage der Kommunikation sind unterschiedliche XML-Dokumente, die zwischen den Teilnehmern ausgetauscht werden: • Agreement Ein Agreement beschreibt die Beziehungen zwischen Teilnehmern. Gegenstand des Agreements ist die Nutzung eines Services auf Basis der im Agreement getroffenen Vereinbarungen. Das Agreement beinhaltet Eigenschaften zur Identifikation und Nutzung eines Services, sowie nicht-funktionale Eigenschaften eines Services, wie Performanz oder Verfügbarkeit. • Template (Agreement Template) Das Agreement Template ist in der Struktur weitestgehend identisch zum Agreement, enthält aber zusätzlich Informationen zur Erzeugung eines Agreements und bietet meist mehrere Alternativen an. • Offer (Agreement Offer) Ein Agreement Offer enthält Bedingungen, zu denen ein Initiator bereit ist, ein Agreement einzugehen. Der Agreement Creation Process beschreibt den Prozess zum Erzeugen eines Agreements und ist in Abbildung 2.1 dargestellt. Die Kommunikation zwischen den Teilnehmern erfolgt auf der Basis von Web Services. Ein Initiator (Service Consumer) fordert von einem Service Provider eine Liste von Agreement Templates zu einem Service an. Aus den Templates wählt der Initiator geeignete Parameter aus und erzeugt ein Offer. Der Initiator sendet der Offer an den Service Provider, der diesen prüft. Ist der Offer für den Responder akzeptabel, so erzeugt er ein Agreement. Für den Fall eines inakzeptablen Offers teilt der Service Provider dem Initiator mit dass der Offer abgelehnt wurde. 7 2.1. Web-Service-Agreement-Protokoll Kapitel 2. Grundlagen : ServiceConsumer : ServiceProvider 1: getTemplates() 2: createOfferFromTemplate() 3: sendOffer() 4: offerIsValid() alt [if offer is valid] 5: sendAgreement() [else] 6: sendCancellation() Abbildung 2.1: Sequenzdiagramm: Agreement Creation Process 2.1.2.1 Struktur eines Agreements Ein Agreement besteht aus verschiedenen Elementen, wie sie im Agreement-XMLSchema in Quellcode 2.1 dargestellt sind. 1 <wsag:Agreement AgreementId="xs:string"> 2 <wsag:Name>xs:string</wsag:Name> ? 3 <wsag:AgreementContext>wsag:AgreementContextType</wsag:AgreementContext> 4 <wsag:Terms>wsag:TermCompositorType</wsag:Terms> 5 </wsag:Agreement> Quellcode 2.1: Agreement-XML-Schema Der Name des Agreements wird über das Element Name festgelegt. Innerhalb des Elementes AgreementContext werden allgemeine Daten zum Agreement beschrieben. Die Bedingungen eines Agreements werden mit dem Element Terms ausgedrückt und in Service Terms und Guarantee Terms unterschieden. Service Terms geben Informationen über einen Service. Guarantee Terms enthalten Zusicherungen von Eigenschaften an einen Service, der in den Service Terms beschrieben wird. 8 Kapitel 2. Grundlagen 2.1. Web-Service-Agreement-Protokoll Context Das Element AgreementContextType, beschrieben in Quellcode 2.2, enthält Informationen zu den Teilnehmern, die Lebensdauer des Agreement und optional eine Referenz auf das Template, aus dem das Agreement hervorgegangen ist. 1 <wsag:Context xs:anyAttribute> 2 <wsag:AgreementInitiator>xs:anyType</wsag:AgreementInitiator> ? 3 <wsag:AgreementResponder>xs:anyType</wsag:AgreementResponder> ? 4 <wsag:ServiceProvider>wsag:AgreementRoleType</wsag:ServiceProvider> 5 <wsag:ExpirationTime>xs:DateTime</wsag:ExpirationTime> ? 6 <wsag:TemplateId>xs:string</wsag:TemplateId> ? 7 <wsag:TemplateName>xs:string</wsag:TemplateName> ? 8 <xs:any/> * 9 </wsag:Context> Quellcode 2.2: AgreementContextType-XML-Schema In den Elementen AgreementInitiator und AgreementResponder werden die Teilnehmer des Agreement Creation Requests, Initiator und Agreement Responder, definiert. Das Element ServiceProvider identifiziert den Service Provider. Der Inhalt des Elementes muss vom Typ AgreementRoleType sein. In Quellcode 2.3 ist die Definition des Typs AgreementRoleType dargestellt. Zulässige Werte für den AgreementRoleType sind AgreementInitiator oder AgreementResponder. Über das Element ExpirationTime wird ein Zeitpunkt festgelegt, ab dem ein Agreement nicht mehr gültig ist. Jedes Template hat eine eindeutige ID und einen Namen. Die ID wird im Element TemplateID und der Name im Element TemplateName vergeben. 1 <xs:simpleType name="AgreementRoleType"> 2 <xs:restriction base="xs:string"> 3 <xs:enumeration value="AgreementInitiator"/> 4 <xs:enumeration value="AgreementResponder"/> 5 </xs:restriction> 6 </xs:simpleType> Quellcode 2.3: AgreementRoleType-XML-Schema Terms Bedingungen eines Agreements werden in Form sogenannter Terms ausgedrückt. Ein Agreement kann dabei aus beliebig vielen Terms bestehen. Bedingungen werden in Service Terms und Guarantee Terms unterschieden. Service Terms stellen Informationen zur 9 2.1. Web-Service-Agreement-Protokoll Kapitel 2. Grundlagen Verfügung, die zur Instanziierung oder Identifikation eines Service benötigt werden. Der Service Term besteht aus: • Service Description Term Der Service Description Term (SDT) beschreibt die Funktionalität oder Teile der Funktionalität eines Services. • Service Reference Adressen von Ressourcen werden innerhalb von SOAP als Endpoint Reference (EPR) bezeichnet. Die Service Reference verweist auf den Service und stellt eine EPR oder andere Metadaten zur Verfügung, unter der der Service erreicht werden kann. • Service Properties Die Service Properties bieten die Möglichkeit, messbare Eigenschaften wie Antwortzeit oder Durchsatz eines Service zu definieren. Guarantee Terms beschreiben die Zusicherungen an Dienstgüteeigenschaften, die über einen Service in den Service Terms getroffen wurden. Quellcode 2.4 zeigt das XMLSchema für das Element TermCompositorType. Mit den logischen Operationen AND, OR und XOR können TermCompositorTypes miteinander kombiniert werden. Die logischen Operationen werden mit den Elementen All, OneOrMore und ExactlyOne beschrieben. 1 <wsag:Terms> 2 <wsag:All> 3 { 4 <wsag:All>wsag:TermCompositorType</wsag:All> | 5 <wsag:OneOrMore>wsag:TermCompositorType</wsag:OneOrMore> | 6 <wsag:ExactlyOne>wsag:TermCompositorType</wsag:ExactlyOne> | 7 <wsag:ServiceDescriptionTerm>wsag:ServiceDescriptionTermType</ wsag:ServiceDescriptionTerm> | 8 <wsag:ServiceReference>wsag:ServiceReferenceType</wsag:ServiceReference> | 9 <wsag:ServiceProperties>wsag:ServicePropertiesType</wsag:ServiceProperties> | 10 <wsag:GuaranteeTerm>wsag:GuaranteeTermType</wsag:GuaranteeTerm> 11 } + 12 </wsag:All> 13 </wsag:Terms> Quellcode 2.4: TermCompositorType-XML-Schema 10 Kapitel 2. Grundlagen 2.1. Web-Service-Agreement-Protokoll Service Terms Jeder Service Term verfügt über die Attribute Name und ServiceName. Mit dem Attribut Name wird ein Name für den Term vergeben. Das Attribut ServiceName referenziert den zugehörigen Service. Das XML-Schema für ein ServiceDescriptionTermType wird in Quellcode 2.5 beschrieben. Über das Element any kann eine zusätzliche Beschreibung für den Service hinterlegt werden. Die Art der Beschreibung ist unabhängig von WS-Agreement und kann damit in einer anderen, anwendungsspezifischen Sprache beschrieben werden. 1 <wsag:ServiceDescriptionTerm wsag:Name="xs:string" wsag:ServiceName="xs:string"> 2 <xs:any>...</xs:any> 3 </wsag:ServiceDescriptionTerm> Quellcode 2.5: ServiceDescriptionTermType-XML-Schema In Quellcode 2.6 ist das XML-Schema für das Element ServiceReferenceTermType aufgeführt. Das Element any referenziert auf den Service. Die Darstellung ist abhängig von der Anwendung. Beispielsweise kann im Falle einer Webservice-Anwendung eine EPR im any-Element abgelegt werden. 1 <wsag:ServiceReference wsag:Name="xs:string" wsag:ServiceName="xs:string"> 2 <xs:any>...</xs:any> 3 </wsag:ServiceReference> Quellcode 2.6: ServiceReferenceTermType-XML-Schema Die Dienstgüteeigenschaften eines Service werden in den Service Properties definiert. Dienstgüteeigenschaften werden genutzt, um Service Level Objectives auszudrücken. Quellcode 2.7 gibt einen Überblick über das Element ServicePropertiesType. Innerhalb eines ServiceProperty-Elementes werden Dienstgüteeigenschaften in einem VariableSet-Element abgelegt. Ein VariableSet besteht aus mehreren Variable-Elementen, wie sie in Quellcode 2.8 dargestellt sind. Das Attribut Name eines Variable-Elementes vergibt einen Namen für die Eigenschaft. Das Element Metric definiert eine messbare Einheit für die Dienstgüte-Eigenschaft. 1 <wsag:ServiceProperties wsag:Name="xs:string" wsag:ServiceName="xs:string"> 2 <wsag:VariableSet>wsag:VariableSetType</wsag:VariableSet> 3 </wsag:ServiceProperties> Quellcode 2.7: ServicePropertiesType-XML-Schema 11 2.1. Web-Service-Agreement-Protokoll Kapitel 2. Grundlagen Mit dem Element Location wird eine strukturelle Referenz auf Eigenschaften eines Service gesetzt. XPath [BBC+ 07b] ist eine Abfragesprache, mit deren Hilfe es möglich ist, Teile eines XML-Dokumentes zu adressieren. Neben einem einfachen Pfadnamen, wie beispielsweise einem Netzwerkpfad, kann zwischen dem Location-Element ein XPath-Ausdruck stehen, der sich auf ein Element des Templates bezieht. Eine Menge von Variable-Elementen kann mit dem Element Variables gruppiert werden. 1 <wsag:Variable wsag:Name="xs:string" wsag:Metric="xs:URI"> 2 <wsag:Location>xs:anyType</wsag:Location> 3 </wsag:Variable> Quellcode 2.8: Variable-XML-Schema Guarantee Terms Die Guarantee Terms definieren die Zusicherungen an einen Service, der in den Service Terms beschrieben wurde. Quellcode 2.9 zeigt das GuaranteeTermType-XMLSchema. Ein GuaranteeTerm besitzt die Attribute Name und Obligated. Das Attribut Name legt den Namen des Guarantee Term fest. Ein Guarantee Term kann von verschiedenen Teilnehmern eingefordert werden. Das Attribut Obligated legt fest, von welchem Teilnehmer, Service Provider oder Service Consumer, der Guarantee Term eingefordert wird. Ein GuaranteeTerm beinhaltet verschiedene XMLElemente. Zu den Elementen gehören ServiceScope, QualifyingConditions, ServiceLevelObjectives und BusinessValues. Der ServiceScope enthält eine Liste von Services, auf die die Zusicherungen zutreffen. Die QualifyingConditions ermöglichen es, Rahmenbedingungen für ein ServiceLevelObjective zu setzen, wie einen Zeitpunkt, an dem ein ServiceLevelObjective zutreffen muss. Das ServiceLevelObjective besteht aus Zusicherungen von Eigenschaften aus den Service Terms. 1 <wsag:GuaranteeTerm Name="xs:string" Obligated="wsag:ServiceRoleType"> 2 <wsag:ServiceScope ServiceName="xs:string">xs:any</wsag:ServiceScope> * 3 <wsag:QualifyingCondition>...</wsag:QualifyingCondition> ? 4 <wsag:ServiceLevelObjective>...</wsag:ServiceLevelObjective> 5 <wsag:BusinessValueList>...</wsag:BusinessValueList> 6 </wsag:GuaranteeTerm> Quellcode 2.9: GuaranteeTermType-XML-Schema 12 Kapitel 2. Grundlagen 2.1. Web-Service-Agreement-Protokoll Ein ServiceLevelObjective besteht nach dem Schema in Quellcode 2.10 aus einem KeyPerformanceIndicator (KPI) oder einem CustomServiceLevel. Der KPI definiert ein SLO in Form eines Zielwertes. Dienstgüteeigenschaften wie Durchsatz oder Verfügbarkeit sind geeignete Zielwerte. In der aktuellen Spezifikation von WS-Agreement wird der KPI außer durch ein einfaches XML-Schema, das nur aus den Elementen Name und Target besteht, nicht näher spezifiziert. Der Inhalt des CustomServiceLevel ist frei gestaltbar und erlaubt es, ein eigenes XML-Schema für SLOs zu definieren. Ein SLO besitzt ein oder mehrere Business Values. 1 <wsag:ServiceLevelObjective> 2 <wsag:KPITarget></wsag:KPITarget> | 3 <wsag:CustomServiceLevel>...</wsag:CustomServiceLevel> 4 </wsag:ServiceLevelObjective> Quellcode 2.10: ServicelLevelObjective-XML-Schema Ein Business Value repräsentiert einen Wert für ein SLO oder den Teil eines SLO. Quellcode 2.11 zeigt das Business-Value-List-XML-Schema. Zu den Elementen einer Business Value List gehören die Elemente Importance, Penalty, Reward, Preference und CustomBusinessValue. In vielen Fällen werden die SLOs eines Services nicht gleich wichtig sein. Daher definiert das Element Importance eine relative Wichtigkeit zu einem SLO. Der Service Provider kann auf der Grundlage des ImportanceElementes Kompromisse zwischen verschiedenen Zusicherungen treffen. Die Wichtigkeit wird der Einfachheit halber in Form eines Integer-Wertes ausgedrückt. Die Elemente Reward und Penalty erlauben es, Belohnungen und Strafen für das Erfüllen oder Nichterfüllen von Service Level Objectives zu definieren. 1 <wsag:BusinessValueList> 2 <wsag:Importance>xs:integer</wsag:Importance> ? 3 <wsag:Penalty></wsag:Penalty> * 4 <wsag:Reward></wsag:Reward> * 5 <wsag:Preference></wsag:Preference> ? 6 <wsag:CustomBusinessValue>...</wsag:CustomBusinessValue> * 7 </wsag:BusinessValueList> Quellcode 2.11: Business-Value-List-XML-Schema Das XML-Schema für das Reward-Element wird in der aktuellen WS-AgreementSpezifikation nicht näher beschrieben. In Quellcode 2.12 ist das XML-Schema für das Penalty-Element aufgeführt. Das Penalty-Element beinhaltet die Elemente AssesmentInterval, ValueUnit und ValueExpr. 13 2.1. Web-Service-Agreement-Protokoll Kapitel 2. Grundlagen 1 <wsag:Penalty> 2 <wsag:AssesmentInterval> 3 <wsag:TimeInterval>xs:duration</wsag:TimeInterval> | 4 <wsag:Count>xs:positiveInteger</wsag:Count> 5 </wsag:AssesmentInterval> 6 <wsag:ValueUnit>xs:string</wsag:ValueUnit> ? 7 <wsag:ValueExpr>xs:any</wsag:ValueExpr> 8 </wsag:Penalty> Quellcode 2.12: Penalty-XML-Schema Über das Element AssesmentInterval wird der Zeitrahmen festgelegt, in dem eine Strafe angewendet wird. Kindelemente des AssesmentInterval sind die Element TimeInterval und Count. Der Zeitrahmen der Strafe wird über das Element TimeInterval in Form von zeitlichen Einheiten wie Tage, Wochen oder Monate festgelegt. Alternativ lässt sich der Zeitrahmen mit dem Element count abhängig von der Anwendung in Form der Anzahl der Service-Aufrufe beschreiben. Die Einheit der Strafe wird im Element ValueUnit definiert. Das Element ValueExpr bestimmt den Wert der Strafe. Mit dem Preference-Element kann eine Liste von feingranularen Business Values für verschiedene Wahlmöglichkeiten definiert werden. Jedes Preference-Element muss einem SDT zugeordnet werden. In Quellcode 2.13 ist das Preference-XML-Schema dargestellt. Die Elemente ServiceTermReference und Utility sind Kindelemente des Preference-Elementes. Beide Elemente können beliebig oft in einem Preference-Element erscheinen. Die ServiceTermReference referenziert einen Service Term. Das Utility-Element definiert den Nutzen, der beim Erreichen des zugehörigen SLOs entsteht. 1 <wsag:Preference> 2 <wsag:ServiceTermReference>xs:string</wsag:ServiceTermReference> * 3 <wsag:Utility>xs:float</wsag:Utility> * 4 </wsag:Preference> Quellcode 2.13: Preference-XML-Schema Im CustomBusinessValue-Element können anwendungsspezifische Business Values definiert werden. Die aktuelle WS-Agreement-Spezifikation macht keine näheren Angaben zum Inhalt und Aufbau des CustomBusinessValue-Elementes. 14 Kapitel 2. Grundlagen 2.1.2.2 2.1. Web-Service-Agreement-Protokoll Struktur eines Agreement Templates Das Template entspricht in der Struktur dem Agreement. Zusätzlich zum Agreement beinhaltet das Template sogenannte Creation Constraints. Der Agreement Offer entspricht in der Struktur dem Agreement Template. Basierend auf einem Template erzeugt ein Initiator ein Offer. Der Offer orientiert sich an dem Template und nutzt die Auswahlmöglichkeiten der Terms und Creation Constraints. In Quellcode 2.14 ist das XML-Schema für ein Template dargestellt. Ein Creation Constraint definiert optionale Einschränkungen für die Erzeugung eines Agreements. Das CreationConstraintElement besitzt zwei Kindelemente, Item und Constraint. Das Item-Element spezifiziert den Teil eines Agreements, der in einem Agreement Offer vorhanden sein muss. Zusätzlich werden darin die zulässigen Werte für diesen Teil definiert. Allgemeine Einschränkungen, die sich nicht auf Element eines Agreements beziehen, werden über das Element Constraint gesetzt. Die Spezifikation von WS-Agreement lässt offen, in welcher Form eine Einschränkung innerhalb eines Constraint-Elementes beschrieben werden muss. 1 <wsag:Template TemplateId="xs:string"> 2 <wsag:Name>xs:string</wsag:Name> ? 3 <wsag:AgreementContext>wsag:AgreementContextType</wsag:AgreementContext> 4 <wsag:Terms>wsag:TermCompositorType</wsag:Terms> 5 <wsag:CreationConstraints> 6 <wsag:Item>...</wsag:Item> * 7 <wsag:Constraint>...</wsag:Constraint> * 8 </wsag:CreationConstraints> ? Quellcode 2.14: Template-XML-Schema In Quellcode 2.15 ist das XML-Schema für ein Item zu sehen. Der Name, der über das Attribut Name vergeben wird, muss eindeutig sein. Das Element Location definiert eine strukturelle Referenz, wie sie bereits beschrieben wurde. Die Einschränkungen für ein Item werden im Kindelement ItemConstraint gesetzt. Ein ItemConstraint besteht aus den Elementen restriction, group, all, choice und sequence. Im Element restriction wird mit dem im XML-Namensraum definierten simpleRestrictionModel-Typ eine Einschränkung definiert. Die Elemente group, all, choice, sequence und any ermöglichen es, auf ein Element des entsprechenden oder eines verwandten XML-Types einzuschränken. 1 <wsag:Item Name="xs:string"> 2 <wsag:Location>xs:anyType</wsag:Location> 15 2.1. Web-Service-Agreement-Protokoll Kapitel 2. Grundlagen 3 <wsag:ItemConstraint> 4 <xs:restriction>xs:simpleRestrictionModel<xs:restriction> ? 5 <xs:group>xs:groupRef</xs:group> ? 6 <xs:all>xs:all</xs:all> ? 7 <xs:choice>xs:explicitGroup</xs:choice> ? 8 <xs:sequence>xs:explicitGroup</xs:sequence>? 9 </wsag:ItemConstraint> 10 <xs:any>any#other</xs:any> * 11 </wsag:Item> Quellcode 2.15: Item-XML-Schema 2.1.2.3 Agreement-Zustände Agreements und Terms haben zur Laufzeit unterschiedliche Zustände, die überwacht werden können. Ziel ist es, die Einhaltung eines Agreements sicherzustellen. In Abbildung 2.2 sind die möglichen Zustände für ein Agreement aus der Sicht eines Initiators dargestellt. Der Zustand Pending signalisiert, dass ein Agreement Offer gestellt aber weder Offer Received Rejected Pending Observed Terminated Completed Abbildung 2.2: Agreement Zustände aus Sicht des Initiators akzeptiert noch abgelehnt wurde. Wurde ein Agreement Offer gestellt und akzeptiert, so befindet sich das erzeugte Agreement im Zustand Observed. Ein Agreement Offer, der im Zustand Pending akzeptiert wurde, geht ebenfalls in den Zustand Observed über. Wird ein Agreement Offer im Zustand Pending vom System abgelehnt, so ist der Folgezustand Rejected. Der Zustand Rejected geht direkt über in den Endzustand. 16 Kapitel 2. Grundlagen 2.1. Web-Service-Agreement-Protokoll Zieht der Agreement Initiator sein Agreement Offer zurück oder leitet eine Terminierungsoperation ein, während im Zustand Pending der Agreement Offer noch geprüft wird, so geht der Offer in den Zustand Terminated über. Der Zustand Terminated führt in den Endzustand. Leitet der Agreement Initiator eine Termination-Operation ein, während das Agreement im Zustand Observed ist, so geht das Agreement vom Zustand Observed in Terminated über. Der Zustand Completed signalisiert, dass ein Agreement Offer angenommen und genehmigt wurde und alle Aktivitäten, die mit dem Agreement verbunden sind, erledigt wurden. 2.1.3 Quality-of-Service-Erweiterung Im Labor für Verteilte Systeme der Fachhochschule Wiesbaden wurde eine Erweiterung entwickelt, die ein XML-Schema für das ServiceLevelObjective-Element CustomServiceLevel implementiert. Die Erweiterung wurde in WSAG4J, einer WSAgreement-Implementierung des Fraunhofer Institiuts, integriert. Mit dem XML-Schema ist es nun möglich, Quality-of-Service-Bedingungen als Service Level Objective zu setzen. Quellcode 2.16 stellt das XML-Schema vor. Das XML-Schema erlaubt es, mit den logischen Operatoren AND und OR die Parameter throughput (Durchsatz) und responseTime (Antwortzeit) zu setzen und Alternativen auszudrücken. Das Schema ist um zusätzliche Parameter erweiterbar. In Zeile 3 wird ein abstraktes Element mit dem Namen qosElement definiert. Alle weiteren Elemente in dem XML-Schema sind Erweiterungen dieses Elementes. Das Element and besteht aus zwei Kindelementen, die vom abstrakten Typ qosElement sein können (Zeile 7 bis 9). Zeile 13 bis 21 beschreibt das Element or, welches wie das and-Element aus zwei Kindelementen vom Typ qosElement besteht (Zeile 16 bis 18). Mit dem Element responseTime in Zeile 22 wird die Antwortzeit als qosElement beschrieben. Das Element besitzt die Attribute unit, variable und max. Das Attribut unit definiert die Einheit, in der ein Wert im Attribut max angegeben wird. Mit dem Attribut variable wird eine Variable in den Terms referenziert. Das Element throughput wird in Zeile 31 bis 41 definiert und enthält wie die responseTime die Attribute unit, variable und max. Zusätzlich hat das Element noch ein weiteres Attribut mit dem Namen min, welches erlaubt, eine untere Schranke für einen Durchsatz zu definieren. 1 <?xml version="1.0" encoding="UTF-8"?> 2 <xs:schema targetNamespace="http://vs.cs.fh-wiesbaden.de/agreement/" xmlns:xs="http:// www.w3.org/2001/XMLSchema" xmlns:qos="http://vs.cs.fh-wiesbaden.de/agreement/" elementFormDefault="qualified" attributeFormDefault="unqualified"> 17 2.1. Web-Service-Agreement-Protokoll Kapitel 2. Grundlagen 3 <xs:complexType name="qosElement" abstract="true"/> 4 <xs:complexType name="and"> 5 <xs:complexContent> 6 <xs:extension base="qos:qosElement"> 7 <xs:sequence minOccurs="2" maxOccurs="2"> 8 <xs:element name="qosElement" type="qos:qosElement"/> 9 </xs:sequence> 10 </xs:extension> 11 </xs:complexContent> 12 </xs:complexType> 13 <xs:complexType name="or"> 14 <xs:complexContent> 15 <xs:extension base="qos:qosElement"> 16 <xs:sequence minOccurs="2" maxOccurs="2"> 17 <xs:element name="qosElement" type="qos:qosElement"/> 18 </xs:sequence> 19 </xs:extension> 20 </xs:complexContent> 21 </xs:complexType> 22 <xs:complexType name="responseTime"> 23 <xs:complexContent> 24 <xs:extension base="qos:qosElement"> 25 <xs:attribute name="unit" type="xs:string" use="required"/> 26 <xs:attribute name="variable" type="xs:string" use="required"/> 27 <xs:attribute name="max" type="xs:float" use="optional" default="0"/> 28 </xs:extension> 29 </xs:complexContent> 30 </xs:complexType> 31 <xs:complexType name="throughput"> 32 <xs:complexContent> 33 <xs:extension base="qos:qosElement"> 34 <xs:attribute name="unit" type="xs:string" use="required"/> 35 <xs:attribute name="variable" type="xs:string" use="required"/> 36 <xs:attribute name="min" use="optional"/> 37 <xs:attribute name="max" use="optional" default="0"/> 38 </xs:extension> 39 </xs:complexContent> 40 </xs:complexType> 41 <xs:element name="qos" type="qos:qosElement"/> 42 </xs:schema> Quellcode 2.16: QoS-XML-Schema 2.1.4 Beispiel Als Grundlage für das Beispiel wird ein Taschenrechner-Webservice (Calculator Webservice) gewählt. Hierbei will ein Initiator ein SLA über den Taschenrechner-Webservice abschließen. In Quellcode 2.17 ist das vollständige Agreement Template zu sehen. Das Agreement Template ist in einem SOAP Envelope eingebettet (Zeile 1). Der SOAP Header definiert in Zeile 2 bis 10 den Sender und Empfänger der Nachricht, die Message ID 18 Kapitel 2. Grundlagen 2.1. Web-Service-Agreement-Protokoll und die Operation, die ausgeführt wird. Im Body des SOAP Envelopes befindet sich das eigentliche Agreement-Template-Dokument (Zeile 11 bis 47). Der Name des Templates ist qosTemplate und der des Agreements calculatorAgreement (Zeile 13). In Zeile 14 ist zu sehen, dass das Context-Element leer ist. Die Service Description Terms (Zeile 17) beschreiben den Service. Der Name des Service ist calculatorService. In den Service Properties werden die Service Level Objectives definiert (Zeile 18). Für den Taschenrechner-Webservice sind die SLOs throughput und responseTime verfügbar (Zeile 20 und 21). Die SLOs müssen im Variable Set gesetzt werden, damit im CustomServiceLevel-Element darauf referenziert werden kann. Der Service Provider bietet für den Taschenrechner-Webservice einen Durchsatz von mindestens 100 und maximal 150 Requests per Minute (Anfragen pro Minute) (Zeile 28) oder eine maximale Antwortzeit von 100 Milisekunden (Zeile 29). Die Oder-Verknüpfung wird über das or Element in Zeile 27 realisiert. 1 <soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa=" 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 http://www.w3.org/2005/08/addressing"> <soapenv:Header> <wsa:To>http://www.w3.org/2005/08/addressing/anonymous</wsa:To> <wsa:ReplyTo> <wsa:Address>http://www.w3.org/2005/08/addressing/none</wsa:Address> </wsa:ReplyTo> <wsa:MessageID>urn:uuid:9981F5FE2453F04D7A12149997859152</wsa:MessageID> <wsa:Action>http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/ GetResourcePropertyRequest</wsa:Action> <wsa:RelatesTo wsa:RelationshipType="http://www.w3.org/2005/08/addressing/reply"> uuid:6abcbec1-1ccd-1854-b065-36bb8564ffc2</wsa:RelatesTo> </soapenv:Header> <soapenv:Body> <wsrf-rp:GetResourcePropertyResponse xmlns:tns="http://handler.server.wsag.graap.ogf .org" xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2"> <wsag:Template wsag:AgreementId="calculatorAgreement" wsag:TemplateId="qosTemplate " xmlns:wsag="http://schemas.ggf.org/graap/2007/03/ws-agreement"> <Context xmlns="http://schemas.ggf.org/graap/2007/03/ws-agreement"/> <Terms xmlns="http://schemas.ggf.org/graap/2007/03/ws-agreement"> <All> <ServiceDescriptionTerm NS1:ServiceName="calculatorService" xmlns:NS1="http: //schemas.ggf.org/graap/2007/03/ws-agreement"></ServiceDescriptionTerm> <ServiceProperties> <VariableSet> <Variable NS1:Metric="rpm" NS1:Name="throughput" xmlns:NS1="http:// schemas.ggf.org/graap/2007/03/ws-agreement"/> <Variable NS1:Metric="ms" NS1:Name="responseTime" xmlns:NS1="http:// schemas.ggf.org/graap/2007/03/ws-agreement"/> </VariableSet> </ServiceProperties> <GuaranteeTerm NS1:Name="termName" xmlns:NS1="http://schemas.ggf.org/graap /2007/03/ws-agreement"> 19 2.2. Service Component Architecture 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 Kapitel 2. Grundlagen <ServiceLevelObjective> <CustomServiceLevel> <qos xmlns="http://vs.cs.fh-wiesbaden.de/agreement/" xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance" xsi:type="or"> <qosElement max="150" min="100" unit="rpm" variable="throughput" xsi:type="throughput"/> <qosElement max="100.0" unit="ms" variable="responseTime" xsi:type ="responseTime"/> </qos> </CustomServiceLevel> </ServiceLevelObjective> </GuaranteeTerm> </All> </Terms> <Terms xmlns="http://schemas.ggf.org/graap/2007/03/ws-agreement"> <All> <ServiceReference> <Location>http://sample.org:8080/calculatorService</Location> </ServiceReference> </All> </Terms> <CreationConstraints xmlns="http://schemas.ggf.org/graap/2007/03/ws-agreement"/> <CreationConstraints xmlns="http://schemas.ggf.org/graap/2007/03/ws-agreement"/> </wsag:Template> </wsrf-rp:GetResourcePropertyResponse> </soapenv:Body> </soapenv:Envelope> Quellcode 2.17: Webservice-Agreement-Beispiel 2.2 2.2.1 Service Component Architecture Einleitung Die Service Component Architecture (SCA) beschreibt ein Modell zum Entwurf von Anwendungen, basierend auf Konzepten von Service-Oriented Architectures (SOA). Grundlegende Idee der Service Component Architecture ist die Trennung von Implementierung und Zusammenfügung (Assembly) der einzelnen Komponenten. Anforderungen an eine Geschäftsanwendung werden durch das Zusammensetzen verschiedener Services erfüllt. Eine solche Anwendung wird auch als Composite Application bezeichnet. Neben der Nutzung neuer Funktionalität ist es möglich, bereits bestehende Funktionalität aus anderen Composite Applications wiederzuverwenden. Verwandte Formate sind Java Business Integration (JBI) von Sun Microsystems und das Windows Communication Foundation (WCF) Framework der Firma Microsoft. Die Organization for the Advance- 20 Kapitel 2. Grundlagen 2.2. Service Component Architecture ment of Structured Information Standards (OASIS)1 , welche die Spezifikationen veröffentlicht, arbeitet zur Zeit mit den beteiligten Mitgliedern an einer Standardisierung der Service Component Architecture. 2.2.2 Architektur Das Assembly Model [BBB+ 07] der SCA beschreibt zwei verschiedene Modelle. Das erste Modell definiert das Zusammenfügen von eng und lose gekoppelten Diensten. Das zweite Modell beschreibt, wie Dienste um sicherheitsrelevante Funktionen, wie Authentifizierung und Transaktionen, erweitert werden. Die Struktur einer SCA-Anwendung wird in einer XML-Datei, der composite-Datei, festgelegt. Eine SCA-Anwendung kann dabei aus mehreren composites bestehen. Das Assembly Model beinhaltet eine Reihe von Artefakten (Artifacts), die den Aufbau einer SCA-Anwendung in Form von composites beschreiben. Im Folgenden werden die verschiedene Artefakte kurz vorgestellt: • policy Regeln werden innerhalb der SCA über das policy-Element realisiert. • implementation Das implementation-Element legt fest, in welcher Technologie die Geschäftsfunktionalität einer Anwendung implementiert wird. • interface Das interface-Element definiert die Geschäftsfunktionalität einer Anwendung. • property Das property-Element ermöglicht es, extern konfigurierbare Eigenschaften einer implementation zu definieren. • component Eine component ist die konfigurierte Instanz einer implementation. Die component bietet und nutzt services. • service Das service-Element beschreibt die extern verfügbaren Schnittstellen einer Anwendung. 1 Homepage der OASIS Arbeitsgemeinschaft: http://www.oasis-open.org/ 21 2.2. Service Component Architecture Kapitel 2. Grundlagen • reference Abhängigkeiten einer implementation werden über ein reference-Element realisiert. • binding Um den Zugriffsmechanismus eines service- oder reference-Elementes zu beschreiben wird das binding-Element verwendet. • wire Mit Hilfe des wire-Elements werden service- und reference-Elemente miteinander verknüpft. Mit Hilfe der Verknüpfung können service- und reference-Elemente miteinander kommunizieren. • composite Eine composite gruppiert die aufgeführten Elemente logisch in einer XMLDatei. Die aufgeführten Elemente sollen im folgenden näher erläutert werden und einen Überblick über den Aufbau einer SCA-Anwendung vermitteln. Anhand eines Beispiels wird darauffolgend der Zusammenhang zwischen den Elementen verdeutlicht. SCA Domain Eine SCA Domain repräsentiert einen Menge von Services, die zusammen eine Geschäftsfunktionalität zur Verfügung stellen. Spezifiziert wird in einer SCA Domain die Instanziierung, Konfiguration und Verknüpfung einer Menge von components, verteilt auf eine oder mehrere composite-Dateien. Eine SCA Domain besteht damit aus einer Reihe von services, references, wires und components. Policies Policies erlauben es, Regeln für bestimmte Elemente einer SCA-Anwendung zu definieren. Elemente, auf die Policies anwendbar sind, verfügen über die Attribute require und policySet. Das Attribut require beschreibt die Regel, die angewendet wird, während policySet eine Liste von Regeln repräsentiert. Die Regeln werden üblicherweise in einer bekannten Form, wie zum Beispiel WS-Policy Assertions, ausgedrückt. Policies werden im SCA Policy Framework [BBC+ 07a] beschrieben. 22 Kapitel 2. Grundlagen 2.2. Service Component Architecture Properties Ein property-Element repräsentiert eine extern konfigurierbare Eigenschaft einer implementation. Eine implementation besitzt keine, eine oder mehrere property-Elemente. In Quellcode 2.18 ist das XML-Schema für ein property-Element abgebildet. Jedes property-Element besitzt ein Attribut name, type oder element, many und mustSupply. Über das Attribut name wird ein Name für die property vergeben. Eine property hat einen Datentyp, der ein XML-Schema-Typ (type) oder einem XML-Element (element) entspricht. Mit dem Attribut many wird festgelegt, ob die property nur aus einem einzelnen Wert oder aus einer Vielzahl von Werten besteht. Über das Attribut mustSupply wird festgelegt, ob die property implementiert werden muss. 1 <property name="xs:NCName" (type="xs:QName" | element="xs:QName") 2 many="xs:boolean"? mustSupply="xs:boolean"?>* 3 default-property-value? 4 </property> Quellcode 2.18: Property-XML-Schema Implementation Eine implementation stellt die Geschäftsfunktionalität eines Service innerhalb einer service-orientierten Anwendung zur Verfügung. Unterstützt wird eine Vielzahl von verschiedenen Sprachen und Frameworks wie Java, C++, XSLT, BPEL oder Spring. Eine implementation wird durch ein implementation-Element beschrieben, wie es in Quellcode 2.19 dargestellt ist. Um zwischen unterschiedlichen implementationTypen zu unterscheiden, wird das XML-Element um den Namen des Typs erweitert, zum Beispiel implementation.java oder implementation.bpel. 1 <implementation requires="list of xs:QName"? policySets="list of xs:QName"?/>?* Quellcode 2.19: Implementation-XML-Schema Als konfigurierbare Bestandteile einer implementation werden services, references und properties in der SCA zum component-Typ zusammengefasst. In Abbildung 2.3 ist die Beziehung zwischen dem component-Typ, component und implementation dargestellt. Die properties und references einer Implementierung werden in der component, die eine entsprechende implementation 23 2.2. Service Component Architecture Kapitel 2. Grundlagen nutzt, konfiguriert. Der component-Typ wird durch Analyse der implementation Abbildung 2.3: Beziehung von Component und Implementation (nach [BBB+ 07]) oder durch eine componentType-Datei bestimmt. Bei der Analyse wird der vorhandene Quelltext der Implementierung nach Annotationen durchsucht. Annotation entsprechen Anmerkungen im Quelltext, vergleichbar mit dem Konzept von Annotations in Java. Für implementation-Typen, deren Quelltext nicht analysiert werden kann, weil die Sprache oder das Framework Elemente wie Annotationen nicht kennt, werden entsprechende Informationen in der componentType-Datei, mit der Dateiendung *.componentType, hinterlegt. Die componentType-Datei besteht dabei aus einem Element componentType. Das componentType-Element, in Quellcode 2.20, kann service-, reference- oder property-Elemente enthalten. Das Attribut constrainingType ermöglicht es, Einschränkungen für einen componentType zu definieren. 1 <componentType xmlns="http://www.osoa.org/xmlns/sca/1.0" constrainingType="QName"?> 2 ... 3 </componentType> Quellcode 2.20: Component-Type-XML-Schema Ein constrainingType definiert services, references und properties, die implementiert werden müssen. In Quellcode 2.21 ist das XML-Schema für ein constrainingType dargestellt. 1 <?xml version="1.0" encoding="ASCII"?> 2 <constrainingType xmlns="http://www.osoa.org/xmlns/sca/1.0" targetNamespace="xs:anyURI"? 24 Kapitel 2. Grundlagen 2.2. Service Component Architecture 3 name="xs:NCName" requires="list of xs:QName"?> 4 ... 5 </constrainingType> Quellcode 2.21: ConstrainingType-XML-Schema Ein constrainingType-Element besteht aus keinem, einem oder mehreren service-, reference- oder properties-Elementen. Das Attribut name definiert einen Namen für den constrainingType. Der vergebene Name wird im constrainingType-Attribut der component referenziert. Über das Attribut targetNamespace wird auf einen Namensraum für den constrainingType verwiesen. Binding Um Zugriffsmechanismen in einer SCA-Anwendung zu beschreiben, wird das bindingElement verwendet. Dabei wird das binding-Element von services und references genutzt. Eine reference nutzt ein binding, um den Zugriffsmechanismus zu beschreiben, der nötig ist, um den Service aufzurufen, mit dem sie verknüpft ist. Ein service nutzt das binding, um zu beschreiben, wie ein Client einen Service aufzurufen hat. Ein binding wird durch ein binding-Element definiert, wie es in Quellcode 2.22 abgebildet ist. 1 <binding uri="xs:anyURI"? name="xs:QName"? requires="list of xs:QName"? 2 policySets="list of xs:QName"?/>* Quellcode 2.22: Binding-XML-Schema Für eine reference definiert das Attribut uri die Ziel-URI der reference. Im Fall eines service beschreibt das Attribut die URI relativ zu einer component, die den Service innerhalb einer SCA Domain zur Verfügung stellt. Im Attribut name wird optional ein Name für das binding definiert. Die Service Component Architecture unterstützt unterschiedliche bindings wie Webservices oder Enterprise Java Beans (EJBs). Zusätzlich existiert die Möglichkeit, das SCA Framework um eigene bindings zu erweitern. Interface Geschäftsfunktionen werden durch ein interface definiert. Die in einem interface beschriebene Geschäftsfunktion wird von einem service angeboten und von einer 25 2.2. Service Component Architecture Kapitel 2. Grundlagen component durch eine reference genutzt. Ein interface kann bidirektional sein. Besitzt ein Service Operationen, die an beiden Enden der Service-Kommunikation bereitgestellt werden müssen, so spricht man von einem bidirektionalen Service. Ein Beispiel für einen bidirektionalen Service wäre ein Service, der von einem Client ein Callback Interface erwartet, das bei verschiedenen Service Requests aufgerufen wird. 1 <interface.java interface="NCName" ... /> Quellcode 2.23: Interface-Java-XML-Schema Ein interface besteht aus ein oder mehreren Operationen, wobei jede Operation keine, eine oder mehrere Request Messages und Response Messages besitzt. In Quellcode 2.23 ist das XML-Schema für das Java-interface dargestellt. Im Fall eines Javainterface wird für das Attribut interface die Implementierung in Form einer JavaDatei im Attribut angegeben. Zur Zeit unterstützt die SCA neben Java, WSDL 1.1 portTypes und WSDL 2.0 Interfaces. Der Bezeichner java würde im Fall eines WSDL portTypes durch wsdl ersetzt werden, also interface.wsdl lauten. Weiterhin existiert die Möglichkeit, das SCA Framework um eigene interface-Typen zu erweitern. Service Ein service beschreibt die extern verfügbaren Service-Schnittstellen einer implementation. Üblicherweise wird ein service durch eine component innerhalb eines composite oder durch eine reference, definiert durch ein composite, zur Verfügung gestellt. Letztere Variante erlaubt es, einen service mit einer neuen Adresse und beziehungsweise oder mit einem neuen binding wiederzuverwenden. Jedes serviceElement wird jeweils durch ein interface-Element beschrieben. In Quellcode 2.24 wird das XML-Schema für ein service-Element vorgestellt. 1 <service name="xs:NCName" promote="xs:anyURI" requires="list of xs:QName"? 2 policySets="list of xs:QName"?>* 3 <interface/>? 4 <binding uri="xs:anyURI"? name="xs:QName"? requires="list of xs:QName" 5 policySets="list of xs:QName"?/>* 6 <callback>? 7 <binding uri="xs:anyURI"? name="xs:QName"? requires="list of xs:QName"? 8 policySets="list of xs:QName"?/>+ 9 </callback> 10 </service> Quellcode 2.24: Service-XML-Schema 26 Kapitel 2. Grundlagen 2.2. Service Component Architecture Das Attribut name vergibt einen Namen für den service. Mit dem Attribut promote wird der offerierte service benannt, wobei der Wert der Form <component-name> /<service-name> entsprechen muss. Das interface-Element definiert die Ge- Service Abbildung 2.4: SCA Service Symbol (nach [BBB+ 07]) schäftsfunktionalität oder einen Teil der Geschäftsfunktionalität, die durch den service angeboten wird. Das callback-Element erlaubt es, optional einen Callback für den service zu definieren, wobei ein callback-Element aus beliebig vielen bindingElementen besteht. Abbildung 2.4 zeigt die graphische Repräsentierung eines service innerhalb einer SCA-Anwendung. Wire Um die Kommunikation zwischen einer reference und einem service zu ermöglichen, existiert in der SCA das Konzept der wire-Elemente. Innerhalb eines composite wird eine reference mit einem service über ein wire verbunden. Ein wireElement leitet damit Aufrufe von Operationen an die jeweils angebundene andere Komponente weiter. Um ein wire zu erzeugen, existieren die folgenden Möglichkeiten: • Über die Definition einer Zielkomponente im Attribut target im referenceElement • Mit dem Autowire-Mechanismus werden reference und service-Elemente automatisch verknüpft. Der Autowire-Mechanismus durchsucht das composite nach einem service interface, das mit einem reference interface übereinstimmt. Autowire muss explizit über das Attribut autowire innerhalb eines composite aktiviert werden. • Über das Element wire, wie es in Quellcode 2.25 abgebildet ist. 1 <wire source="xs:anyURI" target="xs:anyURI" />* Quellcode 2.25: Wire-XML-Schema 27 2.2. Service Component Architecture Kapitel 2. Grundlagen Das Attribut source definiert die Quellkomponente, target die Zielkomponente. Reference Eine reference repräsentiert die Abhängigkeit einer implementation von dem service einer anderen implementation. Jede reference innerhalb einer SCAAnwendung muss zu mindestens einem service der Anwendung aufgelöst werden. Eine reference wird durch das XML-Element reference beschrieben, wie es in Quellcode 2.26 dargestellt ist. 1 <reference name="xs:NCName" target="list of xs:anyURI"? promote="list of xs:anyURI" 2 wiredByImpl="xs:boolean"? multiplicity="0..1 or 1..1 or 0..n or 1..n"? 3 requires="list of xs:QName"? policySets="list of xs:QName"?>* 4 <interface/>? 5 <binding uri="xs:anyURI"? name="xs:QName"? requires="list of xs:QName" 6 policySets="list of xs:QName"?/>* 7 <callback>? 8 <binding uri="xs:anyURI"? name="xs:QName"? requires="list of xs:QName"? 9 policySets="list of xs:QName"?/>+ 10 </callback> 11 </reference> Quellcode 2.26: Reference-XML-Schema Der Name der Reference wird durch das Attribute name festgelegt. Im Attribut multiplicity wird definiert, mit wievielen wires man die Reference verbinden kann. Das Attribut promote identifiziert den offerierten Service der reference, wobei der Wert der Form <component-name>/<reference-name> entsprechen muss. Mit Hilfe des Attributes wiredByImpl wird optional festgelegt ob eine implementation die reference dynamisch verknüpft. Ist der Wert des Attributes true, so wird das Ziel der reference zur Laufzeit durch die Implementierung bstimmt. Eine reference kann zusätzlich ein Callback mit dem Element callback definieren, wobei eine variable Anzahl von binding-Elementen innerhalb des Elementes den Zugriff auf den Callback definiert. Das folgende Bild 2.5 ist die graphische Repräsentierung einer reference innerhalb einer SCA-Anwendung. Component Ein weiteres Element in der SCA ist die component. Alle components innerhalb eines composite bilden die Geschäftslösung. Eine component nutzt und offeriert services und repräsentiert eine konfigurierte Instanz einer implementation. Die 28 Kapitel 2. Grundlagen 2.2. Service Component Architecture Reference Abbildung 2.5: SCA Reference Symbol (nach [BBB+ 07]) component wird als Element innerhalb einer composite definiert, dabei kann ein component-Element aus keinem, einem oder mehrere implementation-, reference- oder service-Elementen bestehen. In Quellcode 2.27 ist das XML Schema für ein component-Element zu sehen. 1 <component name="xs:NCName" autowire="xs:boolean"? requires="list of xs:QName"? 2 policySets="list of xs:QName"? constrainingType="xs:QName"?>* 3 ... 4 </component> Quellcode 2.27: Component-XML-Schema Das Attribut name legt den Namen der component fest. Das Attribut autowire definiert, ob references mit zugehörigen services automatisch verbunden werden. Abbildung 2.6 zeigt die grafische Repräsentation einer component. Abbildung 2.6: SCA Component Diagramm (nach [BBB+ 07]) 29 2.2. Service Component Architecture Kapitel 2. Grundlagen Composite Ein composite gruppiert logisch die Elemente einer SCA-Anwendung und ist die grundlegendste Einheit im Entwurf einer solchen Anwendung. Es besteht dabei aus components, services, references und wires, die diese verbinden, und properties, die es ermöglichen, components zu konfigurieren. Eine composite kann eine Implementierung einer component sein, was bedeutet, dass höherschichtige composites components besitzen, die durch andere composites implementiert werden. Eine composite wird in einer Datei mit der Endung *.composite abgelegt. Quellcode 2.28 stellt das XML-Schemata einer composite vor. 1 <composite xmlns="http://www.osoa.org/xmlns/sca/1.0" targetNamespace="xs:anyURI" 2 name="xs:NCName" local="xs:boolean"? autowire="xs:boolean"? constrainingType="QName"? 3 requires="list of xs:QName"? policySets="list of xs:QName"?> 4 <include name="xs:QName"/>* 5 ... 6 </composite> Quellcode 2.28: Composite-XML-Schema Mit dem Attribut name wird ein Name für das composite festgelegt. Teile einer SCAAnwendung können verteilt auf verschiedenen Nodes laufen. Um dieses Verhalten zu unterbinden, existiert das Attribut local. Das Attribut constrainingTyp erlaubt es, Einschränkungen für eine composite zu definieren, wie es bereits im Abschnitt 2.2.2 beschrieben wurde. Zusätzlich ist es möglich, components einer anderen composite Datei durch das Element include einzubinden. Contribution Eine SCA-Anwendung kann von verschiedenen Komponenten abhängig sein. Für eine SCA-Anwendung könnte das ein composite oder eine componentType-Datei, für einen BPEL-Prozess eine Workflow-Beschreibung sein. Das Assembly Model beschreibt, wie diese XML-Dokumente und andere Komponenten über einen Erweiterungsmechanismus in eine SCA Domain integriert werden können. Erweiterungen, sogenannte contributions, werden über ein eigenes Paketformat in eine SCA-Anwendung eingebunden. Zusätzlich ist es möglich, Erweiterungen auch über andere Formate wie ein einfaches Verzeichnis, ein OSGi Bundle oder auch eine JAR-Datei einzubinden. Ein Format für eine Erweiterung sollte mindestens die folgenden Anforderungen erfüllen: 30 Kapitel 2. Grundlagen 2.2. Service Component Architecture • eine Datei sca-contribution.xml zur Verfügung stellen, die die lauffähigen composites der Erweiterung enthält, • ein Verzeichnis in der Wurzel der Hierarchie mit dem Namen META-INF, • die Komponenten des Paketes müssen für eine SCA-Umgebung hierarchisch abbildbar sein. Erweiterung der Architektur Die SCA kann um eigene interface-, implementation- und binding-Typen erweitert werden. Grundlage des Erweiterungsmodells ist das XML-Schema-Konzept von substitution groups, wie sie in [FW04] beschrieben werden. Das Konzept der substitution groups erlaubt es, XML-Elemente durch andere XMLElemente zu ersetzen. Für eine substitution group wird ein head-Element definiert, das ersetzt werden kann. Im SCA-Namensraum werden drei substitution-group-head-Elemente definiert und zwar jeweils für interface-, implementation- und binding-Typen. Die in der SCA definierten Typen für interface, implementation und binding nutzen wiederum selbst substitution-grouphead-Elemente. In Quellcode 2.29 ist das XML-Schema für ein Interface zu sehen. In Zeile 8 wird ein abstraktes Element definiert, das vom Typ Interface ist und den Namen interface trägt. 1 2 3 4 5 6 7 8 9 10 <?xml version="1.0" encoding="UTF-8"?> <!-- (c) Copyright SCA Collaboration 2006 --> <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.osoa.org/xmlns/sca/1.0" xmlns:sca="http://www.osoa.org/xmlns/sca/1.0" elementFormDefault="qualified"> ... <element name="interface" type="sca:Interface" abstract="true"/> <complexType name="Interface"/> ... </schema> Quellcode 2.29: SCA-Interface-XML-Schema Der Typ wird in Zeile 9 definiert. Im Quellcode 2.30 ist dargestellt, wie das Element interface.java implementiert wurde. Das Element interface.java in Zeile 5 ersetzt das head-Element sca:interface. Die Definition des Typs sca:JavaInterface ist in Zeile 7 bis 13 abgebildet. Ein interface.java besteht demnach aus einem Attribut interface, das angegeben werden muss (Zeile 10). 31 2.2. Service Component Architecture Kapitel 2. Grundlagen 1 <?xml version="1.0" encoding="UTF-8"?> 2 <schema xmlns="http://www.w3.org/2001/XMLSchema" 3 targetNamespace="http://www.osoa.org/xmlns/sca/1.0" 4 xmlns:sca="http://www.osoa.org/xmlns/sca/1.0"> 5 <element name="interface.java" type="sca:JavaInterface" 6 substitutionGroup="sca:interface"/> 7 <complexType name="JavaInterface"> 8 <complexContent> 9 <extension base="sca:Interface"> 10 <attribute name="interface" type="NCName" use="required"/> 11 </extension> 12 </complexContent> 13 </complexType> 14 </schema> Quellcode 2.30: SCA-Interface-Java-XML-Schema Die Erweiterung für implementation- und binding-Typen folgt dem gleichen Prinzip. Eigene Erweiterungen für die SCA müssen in einem anderen namespace erfolgen. Zum gegenwärtigen Zeitpunkt lässt das Assembly Model offen, wie eigene Erweiterungen in eine SCA-Laufzeitumgebung integriert werden. 2.2.3 Beispiel Als Beispiel für eine SCA-Anwendung wird an dieser Stelle ein TaschenrechnerWebservice vorgestellt. Der Taschenrechner-Webservice entspricht dem im vorherigen Abschnitt 2.1.4 vorgestellten Service. In Quellcode 2.31 ist das vollständige Composite für den Taschenrechner zu sehen. In Zeile 4 wird eine Schnittstelle für den Taschenrechner definiert, über die ein Client den Taschenrechner in Form eines Webservice aufrufen kann. In Zeile 9 ist die component CalculatorServiceComponent definiert, welche die Funktionalität des Taschenrechners zur Verfügung stellt. Die arithmetischen Grundrechnarten werden als references angegeben und werden damit von anderen composites implementiert. Das interface in Zeile 5 definiert die Schnittstellen für den Taschenrechner, während in Zeile 10 die Implementierung für das interface zu finden ist. Alle arithmetischen Grundrechenarten werden als Webservice implementiert und aufgerufen, wie es in Zeile 13 am binding.ws-Element zu sehen ist. Das Attribut uri des binding.ws-Element definiert die aufzurufende URL für den Webservice. 1 <composite xmlns="http://www.osoa.org/xmlns/sca/1.0" targetNamespace="http://sample" 2 xmlns:sample="http://sample" name="Calculator"> 3 4 <service name="CalculatorService" promote="CalculatorServiceComponent"> 32 Kapitel 2. Grundlagen 2.2. Service Component Architecture 5 <interface.java interface="calculator.CalculatorService" /> 6 <binding.ws/> 7 </service> 8 9 <component name="CalculatorServiceComponent"> 10 <implementation.java class="calculator.CalculatorServiceImpl"/> 11 <reference name="addService" promote=""> 12 <interface.java interface="calculator.AddService" /> 13 <binding.ws uri="http://localhost:8080/sample-add-ws-webapp/AddService"/> 14 </reference> 15 <reference name="subtractService" promote=""> 16 <interface.java interface="calculator.SubtractService" /> 17 <binding.ws uri="http://localhost:8080/sample-sub-ws-webapp/SubtractService"/> 18 </reference> 19 <reference name="multiplyService" promote=""> 20 <interface.java interface="calculator.MultiplyService" /> 21 <binding.ws uri="http://localhost:8080/sample-mult-ws-webapp/MultiplyService"/> 22 </reference> 23 <reference name="divideService" promote=""> 24 <interface.java interface="calculator.DivideService" /> 25 <binding.ws uri="http://localhost:8080/sample-div-ws-webapp/DivideService"/> 26 </reference> 27 </component> 28 </composite> Quellcode 2.31: Calculator Composite 2.2.4 Apache Tuscany SCA Das Apache-Tuscany-SCA-Projekt, das eine Implementierung der SCA-Spezifikation 1.0 zur Verfügung stellt, soll im vorliegenden Abschnitt vorgestellt werden. Diese Diplomarbeit ist Teil des Projektes Selbstmanagement am Beispiel Service-orientierter Architekturen1 des Labors für Verteilte Systeme der FH Wiesbaden. Teile des Projektes wurden bereits erfolgreich mit Apache Tuscany SCA realisiert. Darauf aufbauend soll Apache Tuscany SCA Grundlage der Implementierung dieser Diplomarbeit sein. Das Apache-Tuscany-SCA-Projekt (Tuscany) unterteilt sich in die Unterprojekte SCA Java, SCA PHP und SCA Native. SCA Java und SCA PHP stellen Implementierungen der Spezifikation in Java und PHP zur Verfügung. Das SCA-Native-Projekt ist eine in C++ implementierte SCA-Umgebung, die es erlaubt, component-Implementierungen in C++, Ruby und Python zu entwickeln. Abbildung 2.7 fasst die Komponenten graphisch zusammen und repräsentiert das Architekturmodell von Tuscany. Die SCA-Laufzeitumgebung und -Schnittstellen zur Erwei1 Homepage des Projektes ”Selbstmanagement am Beispiel Service-orientierter Architekturen”: http://wwwvs.informatik.fh-wiesbaden.de/projekte/selfman.html 33 2.2. Service Component Architecture Kapitel 2. Grundlagen terung befinden sich in der Core-Komponente in Tuscany. Die Core-Komponente ist so aufgebaut, dass sie in einer Vielzahl von verschiedenen Umgebungen lauffähig ist. Beispielsweise ist es möglich, Tuscany in einem Web Container, als Java-Anwendung oder als Java-EE-Anwendung in einem Applikationsserver zu betreiben. Diese Umgebungen werden über das Hosting-Platform-Modul bereitgestellt. Erweiterungen werden über das Extension-Modul in Tuscany eingebunden. Mit Hilfe des Extension-Modul, kann Tuscany um neue Typen wie implementation-, binding- und interface-Typen erweitert werden. Weitere Erweiterungsmöglichkeiten sind Schnittstellen zum Umgang mit Daten (Data Binding), wie beispielsweise JAXB. Die in der SCA-Spezifikation definierte API wird über ein seperate Komponente, dem SCA-Spec-API-Modul, zur Verfügung gestellt. Seit Mai 2008 ist das Apache- Abbildung 2.7: Tuscany-SCA-Java-Architektur (nach [Fou08]) Tuscany-Projekt ein offizielles Projekt der Apache Software Foundation. Erweiterungen für SCA werden über das Tuscany Contribution Modell (Abbildung 2.8) eingebunden. Das Contribution Modell integriert Erweiterungen über zwei Erweiterungspunkte (Extension Points). Zum einen der PackageProcessorExtensionPoint und zum anderen der ArtifactProcessorExtensionPoint. Der PackageProcessorExtensionPoint verarbeitet Erweiterungen, die als JAR oder als Datei/Verzeichnis vorliegen. Formate wie WSDL, XSD, Composite, BPEL oder Java-Klassen werden über den ArtifactProcessorExtensionPoint verarbeitet. Der Package Processor durchsucht die zu installierende Erweiterung und erzeugt eine Liste von 34 Kapitel 2. Grundlagen 2.3. Queueing-Strategien Abbildung 2.8: Tuscany-SCA-Contribution-Modell (nach [Fou08]) sogenannten artifacts, die verarbeitet werden müssen. Ein eigener PackageProcessor, der Formate wie EAR, WAR oder ZIP unterstützt, muss sich an der Package Processor Extension registrieren. Über den Artifact Processor werden die artifacts verarbeitet. Eigene Artifact Processors müssen sich an der Artifact Processor Extension registrieren. Der Artifact Processor wird für jedes artifact in zwei Phasen aufgerufen. In der ersten, lesenden Phase wird ein Modell erzeugt, dass das artifact repräsentiert. Dabei ruft der SCA Contribution Service für jeden registrierten Artifact Processor eine entsprechende Methode auf. In der zweiten Phase werden Referenzen auf andere Modells aufgelöst, eine solche Referenz kann beispielsweise eine WSDL-Datei oder eine andere Klasse sein. Nach der zweiten Phase sind alle artifacts verarbeitet und bereit für das Deployment in eine SCA Domain. 2.3 2.3.1 Queueing-Strategien Einleitung Um komplexe Vorgänge in realen Systemen untersuchen zu können, werden häufig Modelle benötigt, die eine quantitative und qualitative Beschreibung der Systeme erlauben 35 2.3. Queueing-Strategien Kapitel 2. Grundlagen [TG05, Hof00]. Von besonderer Bedeutung ist dabei die Möglichkeit, Systemreaktionen zu beurteilen. Ein solches Modell wird durch die Bedientheorie bereitgestellt. Begriffe aus der Bedientheorie erlauben es, Queueing-Strategien (Warteschlangen-Strategien) unabhängig von der konkret implementierten Technologie zu betrachten. • Auftrag Ein Auftrag ist eine Einheit zur Bearbeitung. • Bedienzeit Die Bedienzeit entspricht der Zeitdauer für die reine Bearbeitung eines Auftrags durch ein System. • Antwortzeit/Verweilzeit Die Antwortzeit beschreibt die Zeitdauer vom Eintreffen eines Auftrags bis zur Fertigstellung. • Wartezeit Die Wartezeit entspricht der Antwortzeit abzüglich der Bedienzeit. • Durchsatz Der Druchsatz entspricht der Anzahl der Aufgaben, die von einem System pro Zeiteinheit erledigt wurden. • Warteraum Wird ein Auftrag nicht direkt bearbeitet, so verbleibt er in einem Warteraum. • Quelle Als Quelle wird das System definiert, das einen Auftrag erteilt. Abbildung 2.9 stellt die graphische Repräsentation einiger der voher aufgeführten Begriffe vor. Queueing-Strategien sind von zentraler Bedeutung zur Umsetzung von Quality-ofService-Anforderungen [Tan07]. Im Folgenden werden verschiedene Queueing-Strategien des Linux 2.6 Kernels1 vorgestellt. 2.3.2 Strategien 2.3.2.1 Multi Band Priority Queueing Der Multi-Band-Priority-Queueing-Algorithmus (MBPQ-Algorithmus) ist eine Erweiterung des Priority-Queuing-Algorithmus (PQ-Algorithmus) [Knu98]. Im MBPQ-Algorith1 Homepage des Linux Kernel Projekts: http://www.kernel.org/pub/linux/kernel/v2.6/ 36 Kapitel 2. Grundlagen Klassifizierung Auftrag 2.3. Queueing-Strategien System/Bedienungsstation Warteraum Erledigter Auftrag Ankünfte Abgänge Abbildung 2.9: Graphische Repräsentation der Begriffe der Bedientheorie mus werden Queues mit unterschiedlichen Prioritäten zu Bändern zusammengefasst und nach einem FIFO-Prinzip abgearbeitet. Jedes Band wird nach einem Round-RobinVerfahren bearbeitet. In Abbildung 2.10 ist der Algorithmus dargestellt. Der MPBQAlgorithmus versucht, Nachteile des PQ-Algorithmus abzuschwächen. Liegen für eine Queue mit hoher Priorität viele Aufträge vor, so kann das bei einem PQ-Algorithmus dazu führen, dass Queues mit Aufträgen mit niedriger Priorität nie bearbeitet werden. Man spricht auch davon, dass Aufträge verhungern (starvation). Durch das Zusammenfassen von Queues zu einem Band wird sichergestellt, dass Aufträge von mehreren unterschiedlichen Quellen berücksichtigt werden, allerdings wird damit nicht sichergestellt, dass Aufträge aus anderen Bändern nicht verhungern. Band Klassifizieren der Aufträge Bedienungsstation ... Abgänge Ankünfte Abbildung 2.10: Multi Band Priority Queueing 2.3.2.2 Stochastic Fairness Queueing Der Fairness-Queueing-Algorithmus (FQ-Algorithmus) sortiert Aufträge einer Quelle in jeweils eine eigene Queue ein. Die Queues werden nach dem FIFO-Prinzip abgearbeitet. Aufträge werden nach einem Round-Robin-Verfahren bearbeitet. Pro Queue wird immer genau ein Auftrag entnommen. Der FQ-Algorithmus versucht damit, jeder Quelle den gleichen Anteil an der Gesamtbandbreite zuzusichern. Mit dem FQ-Algorithmus ergibt sich allerdings ein Ungleichgewicht bei unterschiedlich großen Aufträgen. Große Aufträge, also Aufträge die mehr Bearbeitungszeit in Anspruch 37 2.3. Queueing-Strategien Kapitel 2. Grundlagen nehmen, werden vom FQ-Algorithmus indirekt durch eine längere Bearbeitungszeit bevorzugt. Der Stochastic-Fairness-Queueing-Algorithmus (SFQ-Algorithmus) [McK90] versucht, dieses Ungleichgewicht einzuschränken, indem der Algorithmus Aufträge einer Quelle in unterschiedliche Queues ablegt. Die Klassifizierung erfolgt dabei durch eine Hash-Funktion. Parameter der Hash-Funktion sind Eigenschaften von Aufträgen. Durch den Einsatz der Hash-Funktion ist es möglich, dass mehrere Aufträge einer Quelle in die gleiche Queue abgelegt werden. Um dies zu vermeiden, ändert sich der Hash-Algorithmus einer SFQ-Implementierung innerhalb eines Zeitraums mehrmals. Die Queues werden, wie auch beim FQ-Algorithmus, nach einem Round-Robin-Verfahren abgearbeitet. Abbildung 2.11 zeigt das Prinzip des SFQ-Algorithmus. Eingehende Aufträge werden nach einer Hash-Funktion klassifiziert und in verschiedene Queues abgelegt. Die unterschiedlichen Aufträge sind mit unterschiedlichen Farben markiert. Klassifizieren der Aufträge durch eine Hash Funktion Bedienungsstation Abgänge Ankünfte Abbildung 2.11: Stochastic Fairness Queueing 2.3.2.3 Weighted Fair Queuing Der Weighted-Fair-Queueing-Algorithmus (WFQ-Algorithmus) oder auch WeightedRound-Robin-Algorithmus erweitert den FQ-Algorithmus (vergleiche 2.3.2.2) um Gewichte [DKS89, PG93]. Jeder Auftrag wird anhand seiner Priorität in eine Queue abgelegt. Jede Queue i verfügt über ein Gewicht wi das einem Anteil vom Gesamtgewicht entspricht. Das Gesamtgewicht entspricht der Bearbeitungsrate. Über das Gewicht wird damit einer Queue eine entsprechende Bearbeitungszeit zugesichert. In Abbildung 2.12 ist ein Beispiel für den WFQ-Algorithmus dargestellt. Das Beispiel besteht aus vier Queues. Jede Queue ist ein Gewicht (w1, w2, w3 und w4) zugeordnet. Nimmt man an dass pro Gewicht ein Auftrag verarbeitet werden kann, so kann die erste Queue vier Aufträge, die zweite drei Aufträge, die dritte zwei Aufträge und die letzte Queue einen Auftrag bearbeiten, bevor die Queue wieder von vorne anfängt 38 Kapitel 2. Grundlagen 2.3. Queueing-Strategien w1 = 4 Klassifizieren der Aufträge nach Priorität w2 = 3 Bedienungsstation w3 = 2 Abgänge Ankünfte w4 = 1 Abbildung 2.12: Weighted Fair Queuing 2.3.2.4 Class Based Queueing Der Class-Based-Queueing-Algorithmus (CBQ-Algorithmus) [FJ95] klassifiziert eingehende Aufträge und legt sie und in einer baumartigen Hierarchie ab. Die Wurzel des Baumes definiert die Gesamtbandbreite. Alle Nachfahren der Wurzel besitzen Anteile an der Gesamtbearbeitungsrate. Die Summe aller Anteile ist nicht größer als die Gesamtbearbeitungsrate. Über die Anteile wird eine Priorität für Aufträge einer Quelle ausgedrückt. Nutzt ein Blatt die ihm zugesicherte Bearbeitungsrate nicht, so kann sich ein anderes Blatt auf der gleichen Ebene Teile der Bearbeitungsrate ausleihen. Benötigt das beliehene Blatt seine Bearbeitungsrate wieder, so wird die Bearbeitungsrate an das Blatt zurückgegeben. Der Algorithmus sieht vor, dass die Blätter des Baumes von unterschiedlichen Scheduling-Algorithmen bearbeitet werden, allerdings nutzt der CBQ-Algorithmus im Linux Kernel nur eine einzigen Algorithmus und zwar den WFQ-Algorithmus. 2.3.2.5 Leaky Bucket Stellt man sich einen Eimer mit einem Loch vor, so lässt sich beobachten, dass egal in welcher Geschwindigkeit man Wasser in den Eimer gießt, das Wasser in einer konstanten Rate r abfließt. Ist der Eimer voll, läuft überschüssiges Wasser über den Rand des Eimers und geht verloren. Das gleiche Konzept kann auf Aufträge angewendet werden und heißt Leaky-Bucket-Algorithmus (LB-Algorithmus, Algorithmus des undichten Eimers) [Tur02]. Der LB-Algorithmus besteht aus einem Bucket (Eimer), der bis zu n Aufträge aufnehmen kann. Jeder Auftrag benötigt einen Token, um bearbeitet zu werden. Treffen mehr Aufträge ein als der Bucket aufnehmen kann, so werden Aufträge verworfen. Token werden in einer Rate von r Token erzeugt. Ist der Bucket mit weniger als n Aufträgen gefüllt, so werden die neu erzeugten Token zu den bestehenden Tokens hinzugefügt. Da in einem Bucket 39 2.3. Queueing-Strategien Kapitel 2. Grundlagen maximal n Aufträge und damit auch n Token verfügbar sind, beträgt die Burst-Größe n Aufträge. Die Burst-Größe beschreibt die maximale Anzahl der Aufträge die innerhalb eines Zeitintervalls ohne Verzögerung bearbeitet werden können. Es können pro Zeitintervall, mit der Dauer t, maximal rt + n Token zur Verfügung gestellt und damit Aufträge verarbeitet werden. Über die Erzeugungsrate der Token lässt sich die Durchschnittsrate, mit der Aufträge verarbeitet werden, regulieren. 2.3.2.6 Hierarchical Token Bucket Der Hierarchical-Token-Bucket-Algorithmus (HTB-Algorithmus) [VMSE+ 04] ist eine Erweiterung des LB-Algorithmus. Eingehende Aufträge werden klassifiziert und in eine baumartige Struktur abgelegt. Die Klassifizierung erfolgt auf Basis von Filterfunktionen. Eine Klasse entspricht einem Knoten im Baum. Jede Klasse besitzt eine zugesicherte Bandbreite AR (Assured Rate), eine obere Bandbreite CR (Ceil Rate), eine Priorität P und ein Quantum Q. Das Quantum bestimmt die Menge der Tokens, die ein Blatt sich von seinem Vorfahren leihen kann. Die Priorität definiert die Wichtigkeit einer Klasse innerhalb des Baumes. Die aufgeführten Parameter werden über ein Programm einmalig von einem Anwender konfiguriert. Die Blätter werden mit dem Deficit-Round-Robin Verfahren (DRR-Algorithmus), beginnend mit der niedrigsten Ebene im Baum, abgearbeitet. Der DRR-Algorithmus berücksichtigt unterschiedlich große Aufträge [SV95]. Jeder Queue im DRR wird eine Anzahl übertragbarer Einheiten (deficit count) zugestanden. Ist der zu bearbeitende Auftrag kleiner als der deficit count, so wird der Auftrag bearbeitet und der deficit count um die Größe des Auftrags dekrementiert. Ist der Auftrag zu groß, so wird der deficit count um den Wert eines festgelegten Quantums erhöht. Nach mehreren Durchläufen wird der deficit count die Größe des wartenden Auftrags erreicht haben. Der deficit count leerer Queues wird stets auf Null gesetzt. Innerhalb einer Ebene arbeitet der Algorithmus die Blätter nach Priorität ab. Verbraucht ein Auftrag in einem Blatt seine zugesicherte Bandbreite (AR), muss es sich Bandbreite von seinem Vorfahren leihen. Erreicht das Blatt die obere Bandbreite (CR) sortiert sie Aufträge in eine Queue ein, solange bis Tokens verfügbar sind. Die Ausgangsbandbreite wird anhand der Priorität einer Klasse geteilt. Klassen mit einer hohen Priorität können sich mehr Anteile der Bandbreite sichern als Klassen mit einer niedrigen Priorität. 40 Kapitel 3 Analyse Aktuelle Web-Service-Anwendungen berücksichtigen Dienstgüteanforderungen wenig bis gar nicht. In einigen speziellen Fällen ist es möglich, über zusätzliche Sprachen in einer festen Anwendungsumgebung Dienstgüteanforderungen zu formulieren und zu überwachen. Unabhängig von einer solchen festen Anwendungsumgebung soll ein generischer QoS-Proxy für Web Services entwickelt werden, der Dienstgüteanforderungen an Web Services umsetzt. Im vorliegenden Kapitel werden Anforderungen herausgearbeitet und auf mögliche Lösungsansätze untersucht, die zu einem Entwurf der Architektur führen. 3.1 Anforderungen Das Ziel des QoS-Proxys ist es, Dienstgüteanforderungen (QoS-Anforderungen) an Web Services umzusetzen. Abbildung 3.1 modelliert das Ziel als Anwendungsfalldiagramm. Ein Client ruft einen Web Service mit dem Anwendungsfall Web Service Request auf. Der Web Service Request wird unter Berücksichtigung des Anwendungsfalls QoS-Anforderungen an Web Service Request umsetzen ausgeführt. Verantwortlich für das Umsetzen der QoS-Anforderungen ist der Proxy. Im Anwendungsfalldiagramm wird über die Erweiterungsbeziehung angedeutet, dass eine bestehende Web-Service-Anwendung um eine Komponente erweitert wird. Der Proxy soll leicht in eine Web-Service-Anwendung integrierbar sein. Vorteile der leichten Integrierbarkeit sind das einfache Hinzufügen und Entfernen der Proxy-Komponente und das Vermeiden unnötiger Anpassungen am Quelltext der Anwendung. Der Anwendungsfall QoS-Anforderungen an Web Service Request umsetzen lässt sich 41 3.1. Anforderungen Kapitel 3. Analyse Web Service Request <<include>> Proxy Client QoS-Anforderungen an Web Service Request umsetzen Abbildung 3.1: Anwendungsfalldiagramm: Berücksichtigen von QoS-Anforderungen an Web Services als Anwendungsfalldiagramm modellieren. In Abbildung 3.2 ist das Diagramm dargestellt. Akteure sind der Proxy und der Queueing-Algorithmus. Der Proxy klassifiziert den eingehenden Web Service Request auf Grundlage von Dienstgüteparametern. Die Dienstgüteparameter werden über eine zu definierende Schnittstelle, angedeutet durch den Anwendungsfall Bestimmen der QoS-Anforderungen, ermittelt. Je nach Priorität des Requests wird der Web Service Request in eine Queue abgelegt. Es existieren eine Reihe von Queues, die unterschiedliche Dienstgüteklassen repräsentieren. Der QueueingAlgorithmus arbeitet die Queues nach einer festgelegten Strategie ab. Nachdem der Web Service Request in der Queue abgearbeitet wurde, wird er vom Proxy weitergeleitet. Der Klassifizieren der Web Service Requests <<include>> Einsortieren in Queue Bestimmen der QoS-Anforderung en Bearbeiten der Queue Proxy Queueing-Strategie Weiterleiten des Web Service Requests Abbildung 3.2: Anwendungsfalldiagramm: Umsetzen von QoS-Anforderungen an Web Services Anwendungsfall Bestimmen der QoS-Anforderungen lässt sich in einem weiterem Anwendungsfalldiagramm, in Abbildung 3.3 dargestellt, modellieren. Der Proxy soll von außen über eine definierte Schnittstelle erreichbar sein. Die Schnittstelle soll es erlau- 42 Kapitel 3. Analyse 3.1. Anforderungen Vereinbaren eines SLA zu einem Service SLA Server Einhalten der SLAs Client Abfragen von SLAs zu einem Service Proxy Abbildung 3.3: Anwendungsfalldiagramm: Service Level Management ben, den Proxy zu konfigurieren und die Queueing-Strategie festzulegen. Die Konfiguration des Proxys kann implizit über ein SLA erfolgen, das ein Client mit einem SLA-Server vereinbart hat. Die im SLA enthaltenen SLOs definieren die Parameter, die der Proxy für einen Service einhalten muss. Damit definieren die SLOs Richtwerte nach denen der Proxy arbeitet. Eine weitere Schnittstelle für Statistiken soll Informationen über den Betrieb des Proxys liefern. Vorrangiges Ziel der Statistik-Schnittstelle ist es, den Erfolg der Proxy-Strategie zu überprüfen. Apache Tuscany soll als Rahmen für Web-Service-Anwendungen genutzt werden. Bestehende Web-Service-Anwendungen können leicht in eine Tuscany-Anwendung umgewandelt werden. Der QoS-Proxy soll mit der bereits im vorherigen Anwendungsfall angedeuteten Funktionalität in eine SCA-Anwendung beziehungsweise Tuscany integriert werden. Für die Integration stehen verschiedene Ansätze zur Verfügung, die in den spätereren Abschnitten diskutiert werden. Die einzelnen Anforderungsbereiche lassen sich in die folgenden Punkte zusammenfassen. 3.1.1 Integration Grundlegende Idee der SCA, wie in Kapitel 2.2 erläutert, ist die Trennung von Implementierung und dem Zusammenfügen der Komponenten einer Anwendung während der Entwicklung. Darauf aufbauend soll der Proxy als Komponente leicht zu einer SCAAnwendung hinzugefügt, aber auch entfernt werden können. Mögliche Ansätze zur Erweiterung der SCA wurden in Kapitel 2.2 vorgestellt und sollen für die Analyse berücksichtigt werden. 43 3.1. Anforderungen 3.1.2 Kapitel 3. Analyse Queueing In Kapitel 2.3 wurden verschiedene Queueing-Strategien vorgestellt. Die Vor- und Nachteile der einzelnen Queueing-Strategien sollen betrachtet und auf ihre Eignung zur Umsetzung von Dienstgüteanforderungen untersucht werden. 3.1.3 Monitoring und Konfiguration Das Monitoring des QoS-Proxys erlaubt es, zur Laufzeit Abläufe im Proxy zu untersuchen und zu beobachten. Notwendige Anpassungen sollen über eine Konfigurationskomponente erfolgen. Monitoring In Kapitel 2.1 wurde eine QoS-Erweiterung für WS-Agreement vorgestellt. Mit Hilfe der Erweiterung können die Dienstgüteeigenschaften Durchsatz und Antwortzeit für einen Service beschrieben werden. Beide Eigenschaften sind von verschiedenen Faktoren abhängig. Um sicherzustellen, dass vereinbarte SLAs nicht verletzt werden, muss der Proxy instrumentiert werden. Im Rahmen der Analyse sollen Kenngrößen für den Proxy bestimmt und Instrumentierungspunkte im Proxy herausgearbeitet werden. Konfiguration Parameter des Proxys sollen über eine einheitliche Schnittstelle konfigurierbar sein. Mit Hilfe der Schnittstelle sollen Queueing-Strategien festgelegt und ausgetauscht werden können. Zusätzlich ist die Konfigurations-Schnittstelle für die Bestimmung der Dienstgüteanforderungen verantwortlich. Intern verfügt der Proxy über verschiedene Queues unterschiedlicher Dienstgüteklassen. Verschiedene Clients, mit unterschiedlichen SLAs können in der gleichen Queue bearbeitet werden. Eine beliebig hohe Anzahl von Dienstgüteklassen ist zu vermeiden, um die Effektivität des QoS-Proxy nicht einzuschränken. Im Folgenden sollen für die vorangegangenen Anforderungen mögliche Lösungsansätze untersucht werden, die zum Entwurf eines QoS-Proxys führen. 44 Kapitel 3. Analyse 3.2 3.2. Integration Integration Zu den grundlegendsten Anforderungen gehört die Integration des QoS-Proxys in Tuscany. Von besonderer Bedeutung ist dabei eine möglichst einfache Einbindung in eine bestehende Tuscany-Installation und ein leichtes Hinzufügen und Entfernen in eine SCAAnwendung. Der Proxy soll auch in späteren Versionen von Tuscany integrierbar sein unter der Vorausetzung, dass der Kern der Tuscany-Architektur nicht zu großen Änderungen unterworfen wird. Zu den Integrationsanforderungen des QoS-Proxys zählt die Möglichkeit, Web Service Requests mitzuverfolgen und zu beeinflussen. Es existieren verschiedene Ansätze zur Integration eines QoS-Proxys in Tuscany. Im Rahmen der Architektur der SCA wurden in Abschnitt 2.2 mehrere Erweiterungsmöglichkeiten vorgestellt. Weiterhin bietet Tuscany unabhängig von der Architektur der SCA eigene Integrationsansätze. In den nachfolgenden Abschnitten sollen die unterschiedlichen Ansätze auf ihre Fähigkeit zur Integration eines QoS-Proxys in Tuscany untersucht werden. 3.2.1 Erweiterung der SCA Die SCA lässt sich um eigene binding-, implementation- oder interfaceTypen erweitern. Zusätzlich ergibt sich mit dem contribution-Mechanismus die Möglichkeit, funktionale Abhängigkeiten einer SCA-Anwendung auszulagern. Integriert in Tuscany wird eine contribution über die in 2.2.4 vorgestellten Erweiterungspunkte. Tuscany arbeitet intern mit einem Metadaten-Konzept, das in einem Model (Modell) beschrieben wird. Jeder neue Typ muss Methoden zur Erzeugung des Modells zur Verfügung stellen. Instanzen werden in Tuscany üblicherweise nach der Fabrikmethode erzeugt [Blo08]. In einem ersten Schritt werden die Erweiterungsmöglichkeiten über die verschiedenen SCA-Elemente untersucht. Im weiteren wird der Ansatz, den Proxy als contribution zu implementieren, betrachtet. Grundlage der Analyse bildet die Präsentation eines Tuscany-Entwicklers [Fen08] und die Untersuchung des Tuscany-Quelltextes. Realisierung als binding-, implemenation- oder interface-Typ Entscheidend für die Integration eines QoS-Proxys in ein SCA-Element ist die Möglichkeit, Web Service Requests mitzuverfolgen und zu beeinflussen. Dabei sollte der QoS- 45 3.2. Integration Kapitel 3. Analyse Proxy die eigentlichen Aufgaben des SCA-Elementes ergänzen und keinesfalls verfremden. Im Folgenden werden die neuen möglichen Elemente aufgeführt und kurz vorgestellt: • binding.proxy Ein binding-Element beschreibt einen Zugriffsmechanismus für service- und reference-Elemente einer Anwendung. Der Typ binding.proxy-Typ würde auf dem Element binding.ws aufbauen und damit bereits über das Element auf Web-Service-basierte Anwendungen einschränken. • implementation.proxy Ein implementation-Typ definiert die Technologie in der eine oder Teile einer Anwendung implementiert werden. Als Grundlage für einen eigenen implementation.proxy-Typ müsste ein bestehendes implementationElement verändert werden und um die Proxy-Funktionalität ergänzt werden. • interface.proxy Ein interface definiert die Geschäftsfunktionalität einer Anwendung. Der interface.proxy-Typ setzt voraus das ein zugehöriger Typ implementation.proxy existiert. Grundlage für diese Verknüpfung ist die Definition durch den implementation-Typ und die Realisierung durch einen interface-Typ. In der SCA ist es nicht möglich unterschiedliche Konstellationen mit implementation-/interface-Typen zu bilden. Das binding.proxy-Element bietet den vielversprechensten Ansatz, da es nur auf einen Zugriffsmechanismus einschränkt, allerdings hat das Element keine eigentliche Logik, da es im Grunde nur die Information zum Aufruf eines service- oder reference-Elementes bietet. Sowohl das implementation.proxy- als auch das interface.proxy-Element verletzen die Anforderung an einen generischen Proxy. Beide Elemente müssten jede durch ein implementation-Element in Tuscany verfügbare Technologie unterstützen, um nicht auf ein implementation-Element einzuschränken. Unabhängig von bereits festgestellten Nachteilen sollen für die einzelnen Typen, die nötigen Implementierungsschritte betrachtet werden um festzustellen, ob in einem der vorgestellten Elemente die Möglichkeit besteht, Einfluss auf Web-Service-basierte Aufrufe zu nehmen. Um einen neues SCA-Element in Tuscany zu integrieren, sind eine Reihe von verschiedenen Schritten notwendig. Zu diesen Schritten gehört: 46 Kapitel 3. Analyse 3.2. Integration • Erweiterung der zum Element zugehörigen Interfaces. • Implementierung einer Klasse zum Lesen, Schreiben und Verarbeiten der Modelldaten. • Implementierung der Logik des neuen Elements in Provider- und Factory-Klassen. • Registrieren der Komponenten in Tuscany. Aus der Analyse der notwendigen Implementierungsschritte ergibt sich kein Ansatz für ein neues Element Web Service Requests entgegenzunehmen und zu bearbeiten. Der einzig mögliche Ansatzpunkt für jedes Element bilden die Klassen, die die Logik des Elementes implementieren. Keine für die Logik verantwortlichen Klassen eines Elementes bieten die Möglichkeit, Einfluss auf Web Service Requests zu nehmen. Weiterhin stimmt inhaltlich keines der untersuchten Elemente mit dem Aufgaben eines QoS-Proxys überein. Keines der untersuchten Elemente eignet sich damit zur Integration des Proxys in die SCA. Realisierung als contribution Mit Hilfe einer contribution werden funktionale Abhängigkeiten einer SCA-Anwendung in ein definiertes Format ausgelagert. Eine contribution kann dabei verschiedene XML-Dokumente oder auch eine komplette SCA-Anwendung beinhalten. Der QoSProxy würde als contribution implementiert werden, die über die in 2.2.4 vorgestellten Erweiterungspunkte in Tuscany integriert wird. Die Funktionalität des Proxys würde dabei als SCA-Anwendung modelliert werden. Eine SCA-Anwendung, auf die das Dienstgütemanagement angewendet wird, muss angepasst werden. Die Aufrufe der SCA-Anwendung müssen auf die durch den Proxy definierten reference-Elemente umgesetzt werden. Die Umsetzung geschieht unter anderem durch das Anpassen der composite-Datei. Daraus ergibt sich allerdings auch das Problem, dass nicht sichergestellt werden kann, ob die reference-Schnittstelle des Proxys derart generisch ist, dass das Dienstgütemanagement ohne Probleme immer umgesetzt werden kann. Betrachtet man das Beispiel in 3.5, so ist ersichtlich, dass der CalculatorService abhängig von den vier aufgeführten reference-Elementen ist. Abbildung 3.5 stellt die Integration des Proxys in eine bestehende Anwendung, als weitere Component, vor. Unabhängig von der Problematik einer generischen Schnittstelle muss der Quelltext des Proxys für jede neue Anwendung angepasst werden, da die Aufrufe an einen Web Service für jede Anwendung unterschiedlich sind. Die contribution 47 3.2. Integration Kapitel 3. Analyse Abbildung 3.4: Calculator Service Component bietet bisher den interessantesten Ansatz, scheitert allerdings an den Rahmenbedingungen der SCA. Der Proxy lässt sich damit nicht als contribution implementieren. Für die weitere Analyse sollte die Möglichkeit betrachtet werden, die contribution als Container-Format zu verwenden. Die contribution bietet ein Schnittstelle zur Integration in Tuscany. Zusammenfassung Keine der bisher vorgestellten Möglichkeiten eignet sich zur Integration des QoS-Proxy in eine SCA-Anwendung. Der binding-Typ bietet den einfachsten Ansatz zur Integration, da er es erlaubt, auf Web Services als Zugriffsmechanismus einzugrenzen. Sowohl der implementation- als auch der interface-Typ eignen sich nicht für die Integration des Proxys, da für jede implementation- und interface-Technologie ein eigener Proxy entworfen werden müsste. Der generischen Ansatz des Proxys wird mit dieser Einschränkung verletzt. Der Ansatz, den Proxy als contribution zu implementieren, scheitert an den Rahmenbedingungen der SCA-Architektur. 48 Kapitel 3. Analyse 3.2. Integration Abbildung 3.5: Calculator Service Component mit QoS-Proxy Component 3.2.2 Erweiterung von Tuscany Das Apache-Tuscany-SCA-Runtime-Wire-Modell beschreibt den Vorgang der Integration und Konfiguration einer SCA-Anwendung in eine SCA Domain. In Abbildung 3.6 ist das Modell dargestellt. Die Integration und Konfiguration erfolgen in Form einer oder mehrerer composite-Dateien. Ein composite wird erst nach seiner Konfiguration in der SCA Domain aktiviert. In einem ersten Schritt wird das composite verarbeitet, um Interaktionen zur Laufzeit zu vereinfachen. Metadaten werden nach dem promote-Attribut von services und references zusammengefasst. Im reduzierten Modell sind nun alle Informationen auf der Ebene von components verfügbar. Der nächste Schritt verarbeitet alle Elemente unterhalb der composite-Hierarchie. Zu den Elementen gehören component-implementation, reference- und service-bindings. Die Elemente werden konfiguriert, um sie anschließend mit components und externen Services zu verknüpfen (wire-Mechanismus). Im vorletzten Schritt werden references und services einer component über entsprechende bindings verknüpft. Die zur Laufzeit existierende Verknüpfung (runtime-wire) besteht aus einer Reihe von invocation chains (Aufrufketten), die in einzelne Operationen unterteilt sind. Jede Aufrufkette besteht dabei aus einer Menge von invokers 49 3.2. Integration Kapitel 3. Analyse Runtime Wire Invocation Chain Invocation Chain Runtime Component I I Runtime Component I Service Reference SCA Binding SCA Binding Callback Invocation Chain Callback Invocation Chain I I I Abbildung 3.6: Tuscany-SCA-Runtime-Wire-Modell (nach [Fou08]) und interceptors. Ein invoker stellt die Aufruflogik für binding-Protokolle und implementation-Technologien zur Verfügung. Ein interceptor ist ein besonderer Typ von invoker, der zusätzliche Logik und Funktionalität bereitstellt. Das kann beispielsweise die Umwandlung von Daten oder eine Art Transaktionskontrolle sein. Für ausgehende Aufrufe wird eine Verknüpfung für eine component reference über ein entsprechendes binding realisiert. Für eingehende Aufrufe wird eine Verknüpfung für ein component service über eine entsprechende implementation erzeugt. Ein callback wire (Callback-Verknüpfungen) wird mit einem component service verknüpft um den Aufruf eines services als Callback zu realisieren. Der letzte Schritt ist der Start des composites. Dabei werden die start()-Methoden des ImplementationProvider, ReferenceBindingProvider und ServiceBindingProvider aufgerufen. Am Ende sind components, component references und component services initialisiert und bereit, miteinander zu interagieren. In [BBC+ 07a] wird das Policy Framework der SCA beschrieben. Über die Attribute requires und policySet werden Policies in die SCA integriert. Das Attribut requires benennt die entsprechende Policy, während das Attribut policySet eine Liste von Regeln für die Policy repräsentiert. Tuscany bietet mehrere nach dem Policy Framework implementierte Beispiele für SCA Policy. Eine der angebotenen Policys ist die JDKLoggingPolicy. Der nächste Abschnitt soll die Möglichkeit der Integration des QoS-Proxy als Policy-Erweiterung am Beispiel der JDKLoggingPolicy untersuchen. 50 Kapitel 3. Analyse 3.2. Integration Realisierung als Policy-Erweiterung Die Policy JDKLoggingPolicy ermöglicht es, Aufrufe von services und references zu protokollieren. Die Protokollierung wird über das Setzen des Attributes require aktiviert. Als Beispiel dient der bereits in Abschnitt 2.2.3 vorgestellte TaschenrechnerService. In Quellcode 3.1 ist ein Auszug aus der composite-Datei des TaschenrechnerServices abgebildet. Für die reference-Elemente addService und subtractService wird die Policy explizit über das Attribute requires eingebunden. 1 <composite xmlns="http://www.osoa.org/xmlns/sca/1.0" targetNamespace="http://sample" 2 xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.0" xmlns:sample="http://sample" 3 name="Calculator"> 4 5 <service name="CalculatorService" promote="CalculatorServiceComponent"> 6 <interface.java interface="calculator.CalculatorService" /> 7 <binding.ws/> 8 </service> 9 10 <component name="CalculatorServiceComponent"> 11 <implementation.java class="calculator.CalculatorServiceImpl"/> 12 <reference name="addService" promote="" requires="tuscany:logging"> 13 <interface.java interface="calculator.AddService" /> 14 <binding.ws uri="http://localhost:8080/sample-add-ws-webapp/AddService"/> 15 </reference> 16 <reference name="subtractService" promote="" requires="tuscany:logging"> 17 <interface.java interface="calculator.SubtractService" /> 18 <binding.ws uri="http://localhost:8080/sample-sub-ws-webapp/SubtractService"/> 19 </reference> 20 ... 21 </component> 22 </composite> Quellcode 3.1: Beispiel-composite mit JDKLoggingPolicy Zusätzlich existiert eine Datei definitions.xml, in der sich Einstellungen für die Policy befinden. In Quellcode 5.4 ist ein Teil der Datei dargestellt. Über das Element intent wird der Name der Policy vergeben. Im Element constrains wird eine Einschränkung auf einen Typ der SCA gesetzt. Im Beispiel wird auf den Typ sca:implementation.java eingeschränkt. Eine kurze Beschreibung der Policy findet sich im Element description. Das policySet-Element definiert eine Reihe von konkreten Policies, auf die ein implementation- oder binding-Typ angewandt wird. Das Attribut provides bestimmt den Bezug auf das intent-Element. Innerhalb des policySet-Elementes befindet sich das Element jdkLogger, welches es erlaubt ein Log-Level einzustellen. 51 3.2. Integration Kapitel 3. Analyse 1 <?xml version="1.0" encoding="ASCII"?> 2 <definitions xmlns="http://www.osoa.org/xmlns/sca/1.0" 3 targetNamespace="http://tuscany.apache.org/xmlns/sca/1.0" 4 xmlns:sca="http://www.osoa.org/xmlns/sca/1.0" 5 xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.0" xmlns:pol="PolicyExample"> 6 7 <intent name="logging" constrains="sca:implementation.java"> 8 <description> 9 All messages to and from this implementation must be logged 10 </description> 11 </intent> 12 ... 13 <policySet name="JDKLoggingPolicy" provides="tuscany:logging" 14 appliesTo="sca:implementation.java" 15 xmlns="http://www.osoa.org/xmlns/sca/1.0"> 16 <tuscany:jdkLogger name="PolicyExample"> 17 <logLevel>FINER</logLevel> 18 </tuscany:jdkLogger> 19 </policySet> 20 </definitions> Quellcode 3.2: Beispiel-defintions.xml der JDKLoggingPolicy Die Implementierung der JDKLoggingPolicy besteht aus den folgenden Dateien: • JDKLoggingPolicyDefinitionsProvider Die Klasse JDKLoggingPolicyDefinitionsProvider lädt die Policyeigene Datei definitions.xml. In der Datei befindet sich ein intentElement das die JDKLoggingPolicy beschreibt und auf den Typ implementation.java einschränkt. Die Klasse implementiert das Interface SCADefinitionsProvider. Der SCADefinitionsProvider ist verantwortlich für das Laden der Datei und das Erzeugen eines SCA Definition Models. • JDKLoggingImplementationPolicyProvider Die Klasse implementiert das Interface PolicyProvider für eine implementation. Das Interface enthält zwei Methoden createInterceptor() und getPhase(). Die erste Methode erzeugt einen Interceptor für eine Operation, die zweite Methode legt fest, in welcher Phase der Interceptor hinzugefügt werden soll. • JDKLoggingPolicyInterceptor Die Klasse JDKLoggingPolicyInterceptor realisiert den Interceptor. Der Interceptor ist eine Art Vermittler zwischen dem Client und einem entsprechendem Ziel. 52 Kapitel 3. Analyse 3.2. Integration • JDKLoggingPolicy Die Klasse implementiert Policies, die als Parameter für Axis 2, einer SOAP Engine, angewandt werden können. • JDKLoggingPolicyProcessor Um XML-Dateien auszuwerten, implementieren Teile von Tuscany einen eigenen StAXArtifactProcessor. Die Klasse JDKLoggingPolicyProcessor implementiert den StAXArtifactProcessor für die JDKLoggingPolicy. Die Klasse wertet die Datei definitions.xml einer SCA-Anwendung aus, in der unter anderem das Log-Level eingestellt wird. • JDKLoggingPolicyProviderFactory In der Klasse JDKLoggingPolicyProviderFactory werden die Policy Provider für die Typen implementation, service und binding definiert. • JDKLoggingReferencePolicyProvider Die Klasse JDKLoggingReferencePolicyProvider implementiert das Interface PolicyProvider für eine reference. • JDKLoggingServicePolicyProvider Wie auch die Klasse JDKLoggingReferencePolicyProvider implementiert die Klasse das Interface PolicyProvider, allerdings für einen service. Von zentraler Bedeutung ist die Klasse JDKLoggingPolicyInterceptor, die den Interceptor der Policy implementiert. Der Interceptor der Policy wird in die bestehende Aufrufkette einer SCA-Anwendung integriert (vergleiche Abbildung 3.7). Alle Web Service Requests passieren den Interceptor der Policy. Der Interceptor kann alle Aufrufe mitverfolgen und auf eine Konsole ausgeben oder in eine Log-Datei schreiben. Für den Fall der JDKLoggingPolicy wird die Funktionalität durch die Anpassung der compositeDateien einer SCA-Anwendung und das Erzeugen einer zusätzlichen Datei mit Informationen über das Log Level und der Policy bereitgestellt. Aus der Analyse der JDKLoggingPolicy ergeben sich eine Reihe von interessanten Ansätzen zur Integration des QoS-Proxys mit der SCA. Die in Bild 3.8 angedeutete Einbettung des QoS-Proxy in die Aufrufkette erlaubt es, Web Service Requests auszuwerten. Diese Auswertung ist die Grundlage für das Queueing. Zum anderen existiert mit dem StAXArtifactProcessor die Möglichkeit, eine Konfiguration aus einer XMLDatei nach einem bekannten Schema auszuwerten. Jeder Interceptor implementiert eine 53 3.2. Integration Kapitel 3. Analyse Invocation Chain MSG MSG MSG MSG Policy MSG Nachricht in der Invocation Chain Invoker/Interceptor in der Invocation Chain Interceptor der JDKLoggingPolicy in der Invocation Chain Abbildung 3.7: Integration Policy Abbildung 3.8: Integration Proxy Methode getNext(). Über diese Methode wird eine Nachricht, im Bild durch die weiße Box an den Pfeilen angedeutet, an den nächsten Interceptor in der Aufrufkette weitergereicht. Ein erster Ansatz ist es, die Nachrichten des vorhergehenden Interceptors in eine Queue einzusortieren und diese nach einem entsprechenden Algorithmus, zur Sicherung von Dienstgüte-Eigenschaften, abzuarbeiten. Aus diesem Ansatz ergibt sich das folgende Bild 3.9. Das Ablegen von Nachrichten in eine Queue und die damit verzögerte Bearbeitung führt unter Umständen zu Problemen. Der Queueing-Algorithmus arbeitet seine Pakete in der Queue unabhängig von dem zugrunde liegenden Protokoll ab. Unter Umständen können durch das Queueing Timeouts oder andere unerwünschte Effekte auftreten. Eine Untersuchung des Laufzeitverhaltens der JDKLoggingPolicy ergab, dass für jeden Web Service Request ein Thread pro Interceptor gestartet wird. Ein auf JSR 236 [JN06] basierender Thread Pool Manager verwaltet die Threads innerhalb von Tuscany. Ist ein Web Service Request fertig bearbeitet, wird der nicht mehr benötigte Thread zurück in den Pool gelegt. In einem Test wurden die einzelnen Threads für eine Zeit von mehreren Sekunden pausiert. Das Ziel des Testes war es, zu beobachten, ob ein unerwünschtes 54 Kapitel 3. Analyse 3.2. Integration Abbildung 3.9: Integration Proxy mit Nachrichten-Queue Abbildung 3.10: Integration Proxy mit Thread-Queue Verhalten eintritt. Je nach Zeitpunkt des Aufrufes wurden die Web Service Requests, wie erwartet, verzögert beantwortet. Aus den Beobachtungen ergibt sich ein neuer Ansatz zur Implementierung des QoS-Proxy, dargestellt in Bild 3.10. Der Web Service Request wird mit dem Interceptor Thread pausiert und in eine entsprechende Queue des Proxys eingefügt. Der Ansatz fügt damit nicht einzelne Datenpakete eines Web Services in Queues ein, sondern einen vollständigen Web Service Request. Zuätzlich wurde untersucht, ob die Antwort auf eine Web Service Request im selben Thread erfolgt. Wird ein Interceptor Thread wieder aktiv und stellt den Web Service Request, so erfolgt die Antwort auf den Web Service Request im gleichen Interceptor Thread. Eine Analyse eines geeigneten Paketformats entfällt mit dem vorliegenden Ansatz. Mit der vorgestellten Lösung muss eine SCA-Anwendung geringfügig angepasst werden. Um den Proxy als Policy-Erweiterung zu integrieren, müssen in den compositeDateien der Anwendung die jeweiligen require-Attribute gesetzt werden. Für diese Aufgabe könnte man ein graphisches Werkzeug entwickeln, welches die bestehenden composite-Dateien analysiert und dem Anwender erlaubt services und references auszuwählen, deren Aufruf vom QoS-Proxy bearbeiten werden soll. Zusätzlich könnte eine definitions.xml-Datei erzeugt werden, die die in dem Werkzeug gesetzten Einstellungen berücksichtigt. 55 3.3. Queueing 3.2.3 Kapitel 3. Analyse Zusammenfassung In einem ersten Ansatz wurden die Möglichkeiten der Integration in eine SCA-Anwendung und Tuscany mit eigenen, neuen Typen und Erweiterungen untersucht. Eigene Typen eignen sich nicht zu Integration, da keine Möglichkeit besteht, zur Laufzeit direkt Einfluss auf einen Web Service Request zu nehmen. Der Proxy müsste für jede individuelle SCAAnwendung angepasst werden. Darauf aufbauend wurden interne Mechanismen von Tuscany betrachtet und untersucht. Policy-Erweiterungen bieten die Möglichkeit den Proxy in Tuscany zu integrieren und individuell für jede Anwendung zu konfigurieren. Der Proxy soll als Policy-Erweiterung für Tuscany implementiert werden. 3.3 Queueing Im Folgenden sollen die in Abschnitt 2.3 vorgestellten Queueing-Strategien auf ihre Eignung für den QoS-Proxy untersucht werden. Grundlage für die Bewertung ist, neben den spezifischen Eigenschaften der Algorithmen, die Möglichkeit, Dienstgüteanforderungen wie Durchsatz oder Antwortzeit umzusetzen. Alle Queueing-Strategien werden zusammen mit dem Leaky-Bucket-Verfahren zur Umsetzung von Durchsatzanforderungen betrachtet. 3.3.1 Untersuchung der Queueing-Strategien Multi Band Priority Queueing Der MBPQ-Algorithmus ist ein Priority-Queueing-Algorithmus der n Queues zu Bändern zusammenfasst. Dabei schwächt der Algorithmus bekannte Nachteile des PriorityQueueing-Algorithmus ab. Unter der Annahme einer enstprechenden Last, kann es dennoch dazu kommen, dass Aufträge in niedrigprioren Queues nicht mehr bearbeitet werden. Der Algorithmus eignet sich nicht zur Umsetzung von Anforderungen an die Antwortzeit, da im Zweifelsfall immer hochpriore Bänder gegenüber niedrigprioren Queues bevorzugt werden. Zusammen mit dem Leaky-Bucket-Algorithmus lassen sich Anforderungen an den Durchsatz umsetzen. Dabei wird sichergestellt dass der Algorithmus eine geforderte Bandbreite nicht überschreitet. Der Algorithmus kann allerdings nicht sicherstellen, dass jedes Band einen Anteil jederzeit an der Gesamtbandbreite erhält. 56 Kapitel 3. Analyse 3.3. Queueing Stochastic Fairness Queueing Der SFQ-Algorithmus erweitert den einfachen Fairness-Queueing-Algorithmus. Der Algorithmus eignet sich nicht zur Umsetzung von Antwortzeitverhalten, da das Einsortieren in die Queues nach einer stochastischen Funktion erfolgt. Damit kann nicht sichergestellt werden, dass Aufträge in eine bestimmte Queue abgelegt und entsprechend abgearbeitet werden. Zusammen mit dem Leaky-Bucket-Algorithmus kann der Durchsatz reguliert werden. Im Gegensatz zum MBPQ-Algorithmus erhält jede Queue Anteil am Durchsatz, allerdings kann kein Durchsatz für Aufträge einer bestimmten Quelle definiert werden. Weighted Fairness Queueing Der WFQ-Algorithmus ist eine Erweiterung des Fairness-Queueing-Algorithmus um Gewichte. Je höher das Gewicht einer Queue, desto höher die Priorität der Aufträge die darin abgelegt werden. Das Gesamtgewicht entspricht der maximal verfügbaren Bandbreite in einer Zeiteinheit. Der Algorithmus erlaubt eine Priorisierung und garantiert eine Bearbeitung der Aufträge. Damit eignet sich der Algorithmus zur Umsetzung von Antwortzeitanforderungen. Zusammen mit dem Gewicht einer Queue und dem Leaky-BucketAlgorithmus kann sichergestellt werden dass eine Queue nie mehr als dem Gewicht entsprechende Anzahl von Tokens entnehmen kann. Jeder Queue wird damit ein Anteil an der Gesamtbandbreite zugesichert. Class Based Queueing Der CBQ-Algorithmus klassifiziert eingehende Aufträge und legt sie in eine baumartige Struktur ab. Die Blätter des Baumes werden von verschiedenen Queueing-Algorithmen abgearbeitet. Parameter zum Bilden der Äste in diesem Baum können Prioritäten sein. Jeder Ast im Baum hat ein Gewicht. Die Gewichte sind entsprechend Anteile an der Gesamtbearbeitungsrate. Sind in einem Blatt keine Aufträge, so kann sich ein benachbartes Blatt in der Baumstruktur Teile der Bandbreite leihen. Der Algorithmus bietet damit eine recht hohe Flexibilität und erlaubt es, zur Laufzeit Bandbreitenanforderungen dynamisch zu ändern. Der Algorithmus eignet sich zur Umsetzung von Antwortzeit und Durchsatz, ist allerdings relativ komplex. Das Konzept des Leihens von Bandbreite ist nur in besonderen Anwendungsszenarien von Interesse. 57 3.3. Queueing Kapitel 3. Analyse Queueing Strategie Multi Band Priority Queueing Stochastic Fairness Queueing Weighted Fairness Queueing Class Based Queueing Hierarchical Token Bucket Antwortzeit −− −− ++ ++ ++ Durchsatz − −− + ++ ++ Summe −−− − − −− +++ + + ++ + + ++ Tabelle 3.1: Bewertung der Queueing-Strategien Hierarchical Token Bucket Der HTB-Algorithmus repräsentiert einen erweiterten Token-Bucket-Algorithmus und stellt eine Alternative zum CBQ-Algorithmus dar. Aufträge werden nach einer FilterFunktion in die Blätter eines Baumes einsortiert. Der wichtigste Mechanismus im Algorithmus ist das Prinzip des Leihens. Die Blätter leihen sich Tokens von ihrem Vorfahren. Erreichen die Blätter einen festgelegten Wert, so werden die Aufträge in einer Queue abgelegt und zwar solange, bis wieder eine festgelegte Menge von Tokens verfügbar ist. Legt man die verfügbare Anzahl der Tokens pro Vorfahre fest, so lassen sich Gewichte auf einzelne Äste des Baumes abbilden. Der Algorithmus kann über Gewichte, ähnlich wie der WFQ-Algorithmus, Prioritäten nachbilden. Der Algorithmus ist ähnlich wie der CBQ-Algorithmus relativ komplex. Das Prinzip des Leihens von Bandbreite ist wie auch beim CBQ-Algorithmus nur für spezielle Anwendungsszenarien von Interesse. 3.3.2 Zusammenfassung Die Tabelle 3.1 gibt einen Überblick über die untersuchten Queueing-Strategien. Als besonders ungeeignet haben sich der SFQ- und der MBPQ-Algorithmus erwiesen. Von den vorgestellten Queueing-Strategien soll der kombinierte WFQ-/LB-Algorithmus implementiert werden. Das vorgestellte Verfahren bietet die einfachste Möglichkeit, Dienstgüteanforderungen wie Antwortzeit und Durchsatz umzusetzen. Die hohe Flexibilität von CBQ und HTB bringen mehr Punkte in der Bewertung bei der Umsetzung von Durchsatzanforderungen, allerdings sind beide Algorithmen relativ komplex und es ist ungewiss ob sich die Algorithmen auch außerhalb des Linux-Kernel-Umfeld beim berücksichtigen von Web-Service-Anfragen bewähren. Nach einer erfolgreichen Implementierung des WFQ-/LB-Algorithmus sollte der CBQAlgorithmus implementiert werden. Die Komplexität des Algorithmus entsteht zum ei- 58 Kapitel 3. Analyse 3.4. Monitoring und Konfiguration nem durch die Gewichte, die in Form von Anteilen der Bearbeitungsrate abgebildet werden und zum anderen durch Blätter einer Ebene, die sich Anteile an der Bearbeitungsrate von Nachbarblättern leihen können. Die Bearbeitungsrate ist variabel und von verschiedenen Faktoren abhängig. Die Funktionalität des Algorithmus ist wiederum abhängig von der Bearbeitungsrate. Ist die Bearbeitungsrate zu niedrig, so arbeitet der Algorithmus ineffizient, ist die Bearbeitungsrate zu hoch so verletzt der Algorithmus unter Umständen die Dienstgüteanforderungen. Im Linux Kernel entspricht die Bearbeitungsrate des CBQ-Algorithmus der Bandbreite eines Netzwerkgerätes deren Zugriff von mehreren Diensten und Anwendungen geteilt wird. Über einen gewissen Zeitraum betrachtet lässt sich die Bearbeitungsrate immer besser bestimmen. Der Algorithmus sollte implementiert werden um verschiedene Aufträge einer Dienstgüteklasse in eine baumartige Struktur ablegen zu können. Von besonderem Interesse dabei ist es zu beobachten, wie sehr sich die Berücksichtigung von Hierarchien auf die Fähigkeit Dienstgüteanforderungen umzusetzen auswirkt. Für eine bessere Bewertung sollte zusätzlich der HTB-Algorithmus implementiert werden, da er ähnliche Ziele verfolgt, aber einen anderen Ansatz zur Lösung wählt. 3.4 Monitoring und Konfiguration Der QoS-Proxy soll eine einheitliche Schnittstelle zum Monitoring und zur Konfiguration des Proxys anbieten. Die Implementierung des QoS-Proxys erfolgt in Java. Zu den bekannten Standards für IT-Management gehören das Simple-Network-ManagementProtokoll (SNMP) [CFSD90] und das Common Information Model (CIM) [Dis05]. SNMP hat seinen Ursprung im Management von Netzwerken. CIM ist das Informationsmodell für das Web-based Enterprise Management (WBEM) der Distributed Management Task Force (DMTF)1 , das einen Standard für das Management von verteilten Anwendungen spezifiziert. Mit den Java Management Extensions (JMX) [Sun02] hat sich in den letzten Jahren eine weitere Technologie zum Management etabliert. Bekannte Implementierungen von JMX zum Management von Java-Anwendungen finden sich zum Beispiel in JBoss, BEA Weblogic und IBM Websphere. Grundlage für die Integration des QoS-Proxys in SCA ist das Apache-Tuscany-Projekt. Für SNMP und CIM existieren Umsetzungen in Java, allerdings ist JMX vorzuziehen, da es Bestandteil der Java API ist und leicht in Java-Umgebungen zu integrieren ist. Im folgenden Abschnitt soll die Architektur von JMX kurz vorgestellt werden. 1 Homepage der DMTF: http://www.dmtf.org/ 59 3.4. Monitoring und Konfiguration 3.4.1 Kapitel 3. Analyse Java Management Extensions Die Java-Management-Extensions-Spezifikation (JMX) [Sun02, Sun06] beschreibt einen Ansatz zur Instrumentierung von Java-Anwendungen. JMX führt das Konzept der Manageable Bean oder auch MBean in Java ein. MBeans sind Java Beans, die um eine Management-Funktionalität erweitert wurden. Externe Management-Werkzeuge können über MBeans die Zustände eines Java-Objektes abfragen und steuern. Die Architektur, dargestellt in Abbildung 3.11, ist in drei Schichten unterteilt. Im Instrumentation Level Java Virtual Machine JMX Management Application Distributed Services Level C C PA C MBean Server Agent Level Agent Services Agent Services Instrumentation Level Ressource 2 Ressource 4 Ressource 1 Ressource 3 PA C Protocol Adaptor Ressource (MBean) Connector Abbildung 3.11: Java-Management-Extension-Architektur werden die Rahmenbedingungen definiert, wie eine MBean zu implementieren ist, damit diese eine Verbindung zwischen Ressource und einer Management-Anwendung herstellen kann. Kern des Agent Level ist der MBean Server. Der MBean Server ist für die Kommunikation zwischen der Management-Anwendung und dem entsprechenden MBean verantwortlich. Intern verfügt der MBean Server über ein Repository, an das sich eine MBean registriert. Die Agent Services sind verantwortlich für die Ressource und stellen diese über den MBean Server einer Management-Anwendung zur Verfügung. Das Distributed Services Level bietet Interfaces zur Entwicklung von Management-Anwendungen. Zu 60 Kapitel 3. Analyse 3.4. Monitoring und Konfiguration den Aufgaben des Distributed Services Level gehört die semantische Umsetzung einer MBean auf Auszeichnungssprachen wie HTML oder Protokolle wie SNMP. Die JMX-Spezifikation kennt vier verschiedene MBean-Typen: • Standard MBean • Dynamic MBean • Open MBean • Model MBean Die Standard MBeans verfolgen den einfachsten Implementierungsansatz, um die Management-Funktionalität zur Verfügung zu stellen. Alle relevanten Management-Funktionen werden in einem Interface exportiert, das der Namenskonvention KlassenameMBean folgt. Die Methoden werden durch eine Klasse implementiert. Dynamic MBeans bieten eine höhere Flexibilität in der Repräsentation von Datenstrukturen. Während bei Standard MBeans bereits vor der Laufzeit der Typ eines Attributs feststeht, erlauben Dynamic MBeans den Einsatz von dynamischen Strukturen, also Strukturen, deren Aussehen erst zur Laufzeit feststeht oder sich beständig ändert. Für eine Dynamic MBean muss eine Klasse das DynamicMBean-Interface implementieren. Open MBeans bieten Möglichkeiten, den Aufbau einer MBean näher für eine Management-Anwendung oder für den Anwender einer Management-Anwendung zu beschreiben. Eine Open MBean implementiert das DynamicMBean-Interface und stellt weitere Methoden zur Beschreibung der Klasse zur Verfügung. Zusätzlich ist die Anzahl der Datentypen, im Gegensatz zu einer Dynamic MBean, eingeschränkt. Die Model MBean ist eine generische, konfigurierbare MBean, mit der jede Ressource instrumentiert werden kann. Model MBeans entsprechen Dynamic MBeans, die zusätzlich weitere Interfaces implementieren. Die Interfaces exportieren Funktionen, die zu einer instanziierbaren MBean führen. Alle JMX-konformen JMX Agents müssen eine Model MBean implementieren. Mit dieser Voraussetzung ist garantiert, dass Model MBeans in jeder Umgebung, die die JMX-Spezifikation umsetzt, lauffähig sind. Mit JMX ist es möglich interne Zustände des QoS-Proxys zur Laufzeit zu beobachten und zu steuern. Von besonderem Interesse ist es dabei mittelfristig, das Verhalten der Queueing-Strategien und das Einhalten von Service Level Agreements zu überprüfen. Langfristig lassen sich bequem Statistiken erstellen. Ein weiterer Vorteil von JMX ist die Möglichkeit, den QoS-Proxy ohne viel Aufwand in bestehende JMX-basierte Management-Umgebungen zu integrieren. 61 3.4. Monitoring und Konfiguration 3.4.2 Kapitel 3. Analyse Monitoring Das Monitoring des Proxys versucht sicherzustellen, dass SLAs nicht verletzt werden. Dazu muss der Proxy instrumentiert werden. Die Instrumentierungspunkte und die daraus ermittelten Ergebnisse sind relevant für die Durchsetzung von SLOs. Die Ergebnisse des Monitorings sollen über eine einheitliche Schnittstelle verfügbar gemacht werden. 3.4.2.1 Kenngrößen Kenngrößen sind quantitative Größen, die Leistungsmerkmale eines Systems beschreiben [KS93]. Mit Hilfe von Kenngrößen sollen objektive Aussagen über die Leistung des Proxys getroffen werden. Kenngrößen stimmen nicht unbedingt mit beobachtbaren Merkmalen des Systems überein und ergeben sich daher oft aus mehreren Messgrößen. Messgrößen sind Eigenschaften, die direkt im System feststellbar sind. Die einzelne Instanz einer Messgröße wird Messwert genannt. Für den Proxy sind die folgenden Kenngröße von besonderem Interesse: • Verweilzeit Die Verweilzeit entspricht der Zeit in der ein Web-Service-Anfrage im System ist. Damit beschreibt sie die Zeitspanne vom Eintreffen der Web-Service-Anfrage im Interceptor bis zur Antwort des Web-Services auf die Anfrage. • Bearbeitungszeit Die Bearbeitungszeit entspricht der Zeit in der eine Web-Service-Anfrage bearbeitet wird. • Wartezeit Die Wartezeit beschreibt den Zeitraum in dem der Interceptor einer Web-ServiceAnfrage nicht aktiv ist. Innerhalb der Architektur des QoS-Proxys ist das insbesondere die Zeit in der der Thread in einer Queue ist. Betrachtet man mehrere Instanzen dieser Kenngrößen, so lassen sich eine Reihe von Werten bilden. Neben dem Minima und Maxima einer Kenngröße ist der Mittelwert und die Standardabweichung für die Beurteilung des Systems relevant. Die zu den Kenngrößen zugehörigen Messgrößen sollen im folgenden Abschnitt vorgestellt werden. 62 Kapitel 3. Analyse 3.4.2.2 3.4. Monitoring und Konfiguration Instrumentierung Abbildung 3.12 zeigt das bereits aus 3.2.2 bekannte Modell einer Aufrufkette. Zum Zeitpunkt (1) übergibt sich der Interceptor selbst als Parameter an den Proxy, der ihn schlafen legt und in eine interne Queue ablegt. Nach einer gewissen Zeit wird der Interceptor wieder aufgeweckt (2). Der Interceptor führt seine eigentliche Funktionalität fort und ruft den Service auf (3). Der Service antwortet dem Interceptor (4). Zur Berechnung der Kenngrößen ergeben sich eine Reihe von Messgrößen, die im Folgenden eingeführt werden. Der Zeitpunkt zum Aufruf des Interceptors wird tInterceptorAuf ruf und der Zeitpunkt des Proxyaufrufs wird tP roxyAuf ruf genannt. Mit tInterceptorAktiv ist der Zeitpunkt definiert in Invocation Chain MSG 3 MSG MSG MSG MSG Proxy 1 2 MSG MSG 4 Abbildung 3.12: Instrumentierung von Apache Tuscany dem der Interceptor Thread wieder aktiv wird. Der Service wird erst aufgerufen, nachdem der Interceptor Thread wieder aktiv wurde. Der Aufruf-Zeitpunkt wird tServiceAuruf , der Zeitpunkt zu dem die Antwort zugestellt wird tServiceAntwort genannt. In Tabelle 3.2 werden die im vorherigen Abschnitt vorgestellten Kenngrößen den Messgrößen zugeordnet. Wie in Abschnitt 3.3 vereinbart, setzt ein Token-Bucket-Algorithmus die durch die Dienstgüteigenschaft Durchsatz vereinbarte Bandbreite-Anforderungen um. Der Durchsatz, also die Anzahl der Web Service Requests pro Zeiteinheit, muss gemessen werden und auf die im SLO vereinbarte Zeiteinheit umgerechnet werden. Der gemessene Durchsatz dient der Anpassung der Parameter des Token-Bucket-Algorithmus. Die Dienstgüteeigenschaft Antwortzeit entspricht der Kenngröße Bearbeitungszeit. Abweichungen in der Antwortzeit mit den vereinbarten Werten im SLA sind damit eindeutig und schnell identifizierbar. Bei der Wahl der Methode zur Messung der Zeit sollte eine zuverlässige und möglichst 63 3.4. Monitoring und Konfiguration Kenngröße Verweilzeit Bearbeitungszeit Wartezeit Kapitel 3. Analyse Berechnung tServiceAntwort − tInterceptorAuf ruf tServiceAntwort − tServiceAuruf Verweilzeit − Bearbeitungszeit − tP roxyAuf ruf Tabelle 3.2: Berechnung der Kenngrößen im QoS-Proxy genaue Bibliothek genutzt werden. Unterschiedliche Implementierungen nutzen unterschiedliche Ansätze zur Bestimmung der Zeit. Die Art der Implementierung sollte berücksichtig werden, um eine interferenzarme Messung zu gewährleisten und korrekte Ergebnisse zu garantieren. Die Java API stellt mit System.currentTimeMili() und System.nanoTime() geeignete Methoden zur Zeitmessung bereit. Mit der in 3.4.1 vorgestellten JMX-Spezifikation kann eine einheitliche und verbreitete Schnittstelle für externe Management-Anwendungen zur Verfügung gestellt werden. 3.4.3 Konfiguration Der Proxy soll über eine einheitliche Schnittstelle konfigurierbar sein. Dabei soll eine Konfiguration sowohl vor dem Start des QoS-Proxys, als auch zur Laufzeit möglich sein. Ein Ansatzpunkt zur Integration einer Konfigurationsdatei besteht im hinzufügen eines Attributs im policySet der definitions.xml-Datei einer SCA-Anwendung. Die Konfigurationsdatei sollte es erlauben Parameter für die Queueing-Strategie oder die Dienstgüteklasse zu setzen. Über JMX sollten ein Teil der gesetzten Parameter veränderbar sein um Anpassungen an den QoS-Proxys während des Betriebes zu ermöglichen. Service Level Management Zusätzlich zur Konfiguration des QoS-Proxys zum Zeitpunkt des Startes und zur Laufzeit, ist der Proxy verantwortlich für das Bestimmen der Service Level Agreements zu einem Service. Die Service Level Agreements beschreiben die Zusicherungen an einen Service in Form von Service Level Objectives. Von besonderem Interesse sind dabei Zusicherungen in Form von Dienstgüteeigenschaften wie Durchsatz oder Antwortzeit. Diese Dienstgüteeigenschaften definieren den Rahmen in dem eine Queueing-Strategie arbeitet. Abbildung 3.13 beschreibt einen möglichen Vorgang zur Bestimmung der Service Level Agreements. Der QoS-Proxy erzeugt in einem ersten Schritt initial verschiedene Agreement Templates zu einem Service. Die erzeugten Agreement Templates 64 Kapitel 3. Analyse 3.4. Monitoring und Konfiguration werden in einem WSAG4J-System gespeichert und verschiedenen Clients angeboten, die an einem SLA mit diesem Service interessiert sind. Ein Client erzeugt auf Basis der Agreement Templates einen Agreement Offer, der vom WSAG4J-System geprüft wird. Für den Fall einer positiven Überprüfung wird ein Agreement erzeugt und dem Client zugeschickt. Der QoS-Proxy wird über das Agreement zu einem seiner Services informiert. Proxy Registrieren von Agreement Templates WSAG4J Client Erzeugen eines Agreement Offer Übertragen des neu erzeugten Agreements Agreement Template Offerieren der Agreement Templates Agreement Offer Agreement Abbildung 3.13: Kommunikation zwischen QoS-Proxy, WSAG4J und einem Client Neben einem Mechanismus zur Registrierung von Agreement Templates benötigt der QoS-Proxy einen Art Callback-Mechanismus der es dem WSAG4J-System erlaubt den QoS-Proxy zu informieren sobald ein Agreement zu einem seiner Services erzeugt wurde. Weiterhin muss der QoS-Proxy das WSAG4J-System darüber informieren, wenn ein SLA nicht eingehalten werden konnte. Die vorhandene Web-Service-Schnittstelle sieht diese Operationen nicht vor. Ein Ansatz für die Implementierung der SLM-Komponente in die Konfigurations-Komponente ist die Java Remote Method Invocation (RMI). RMI realisiert eine Art von Remote-Procedure-Call für Java-Objekte. In Abbildung 3.14 ist die RMI-Architektur [Sun04] dargestellt. Die Architektur besteht aus den drei Komponenten Client, Server und Registry. In der Registry werden im Server lebende Objekte registriert und mit einem eindeutigem Namen versehen. Der Client erhält durch eine Anfrage an die Registry eine Objekt-Referenz und kann Methoden der Objekte im Server aufrufen. WSAG4J würde den RMI Server und der Proxy den RMI Client implementieren. Die Nutzung von RMI für die SLM-Komponente erlaubt es, die einzelnen Komponenten klar voneinander zu trennen. JMX wird eingesetzt, um die Ergebnisse der Instrumentierung nach außen darzustellen und den Proxy zu parametrisieren. Web Services wer- 65 3.4. Monitoring und Konfiguration Kapitel 3. Analyse Abbildung 3.14: Remote-Method-Invocation-Architektur (nach [Sun04]) den von WSAG4J zur Kommunikation mit dem Client genutzt. Die Kommunikation der SLM-Komponente mit WSAG4J über RMI, vervollständigt die Trennung der einzelnen Aufgabenbereiche. 3.4.4 Zusammenfassung Kenngrößen erlauben es, das Zeitverhalten des QoS-Proxys zu beurteilen. Die MonitoringKomponente ist verantwortlich für das Sammeln von Messgrößen, aus denen sich die Kenngrößen bestimmen lassen. Einstellungen vor und zur Laufzeit erfolgen über die Konfigurationskomponente. Neben der Konfiguration der Queueing-Strategie, ist die Konfigurationskomponente für die Bestimmung der SLAs eines Services verantwortlich. Die Kommunikation zwischen Konfigurationskomponente und einem WS-AgreementServer erfolgt auf Basis von RMI. Über JMX wird es einem Anwender ermöglicht, zur Laufzeit Statistiken aus der Monitoring-Komponente abzurufen und Parameter in der Management-Komponente zu setzen. Eine XML-Datei-Schnittstelle stellt optional initial Informationen in Form von SLAs eines Service zur Verfügung. 66 Kapitel 4 Design Das Kapitel stellt einen konkreten Entwurf für den generischen QoS-Proxy für SOADienste vor. Dabei werden die in Kapitel 3 getroffenen Entscheidungen berücksichtigt und dienen als Grundlage für den Entwurf. 4.1 Architekturüberblick AgreementDatei WS-Agreement WS RMI Business Layer SCA Proxy RMI JMX Monitoring WS JMX XML Konfiguration Queueing ... Integration Tuscany Service Layer JMX Schnittstelle (JMX, RMI, WS, XML) Dienstgüteklasse Client Web Service Kommunikation Wire (Verknüpfung) Abbildung 4.1: Grobarchitektur des QoS-Proxy 67 Konfigurationsdatei 4.1. Architekturüberblick Kapitel 4. Design Abbildung 4.1 fasst die einzelnen Komponenten des QoS-Proxys zur Grobarchitektur zusammen und verdeutlicht die für die einzelnen Schnittstellen eingesetzten Technologien. Die Architektur unterscheidet zwischen einem Business und einem Service Layer. Innerhalb der Abbildung heben schwarze Pfeile mögliche Kommunikationswege hervor. Der QoS-Proxy erzeugt aus ausgewählten Services einer SCA-Anwendung Services, die unterschiedliche Dienstgüteklassen repräsentieren. Dienstgüteklassen werden im Diagramm durch die bereits aus Abschnitt 2.2.2 bekannten grünen Pfeilspitzsymbole dargestellt. Eine Dienstgüteklasse entspricht einer Web-Service-Schnittstelle. Die Dienstgüteklassen unterscheiden sich in ihrer Leistungsfähigkeit. Eine Dienstgüteklasse mit kritischen Anforderungen hat eine höhere Priorität als eine Dienstgüteklasse mit niedrigeren Anforderungen. Auf der Ebene des Business Layers vereinbart ein Client mit WS-Agreement ein oder mehrere Agreements zu einem Service. Grundlage der Agreements sind die vom QoSProxy erzeugten Agreement Templates, in denen Zusicherungen bezüglich Durchsatz und Antwortzeit eines Services gemacht werden. Die Kommunikation zwischen dem Client und WS-Agreement erfolgt auf Basis von Web Services, die zwischen einem WSAgreement und dem QoS-Proxy erfolgt auf Basis von RMI. Das Agreement beinhaltet eine URL zu dem vom QoS-Proxy bereitgestellten Service. Der Client aus dem Business Layer reicht die URL an den Client im Service Layer weiter. Unter Umständen handelt sich dabei um den gleichen Client. Der Client erzeugt WebService-Anfragen, die vom Proxy unter Berücksichtigung von Agreements umgesetzt werden. Grundlage der Grobarchitektur ist die Entscheidung zur Implementierung einer eigenen Policy-Erweiterung für Tuscany (vergleiche 3.2.2). Die Grobarchitektur sieht die folgenden Subsysteme vor: • Queueing Das Queueing-Subsystem ist für das Queueing eingehender Aufträge in Form von Web-Service-Anfragen verantwortlich. Das Subsystem definiert verschiedene Queueing-Strategien. • Monitoring Das Monitoring-Subsystem ermöglicht es, den QoS-Proxy während der Laufzeit zu beobachten. Zu den weiteren Aufgaben des Monitoring-Subsystems gehören das Sammeln von Messwerten der einzelnen Subsysteme und die Erzeug von Statistiken. 68 Kapitel 4. Design 4.2. Queueing-Subsystem • WS-Agreement Das WS-Agreement-Subsystem erlaubt die Verwenndung von Agreements und realisiert die Kommunikation zum QoS-Proxy. Dabei definiert das entsprechende Protokoll die notwendigen Schritte zum Registrieren und Erzeugen von Agreement Templates und einen Benachrichtigungsmechanismus für den QoS-Proxy. • Konfiguration Das Konfigurationssubsystem ermöglicht es, den QoS-Proxy beim Start und zur Laufzeit zu konfigurieren. Über das Konfigurationssubsystem sollen verschiedene Parameter des Proxys angepasst werden können. Dazu definiert die Konfigurationskomponente den Aufbau einer XML-Konfigurationsdatei, in der initiale Konfigurationswerte für den Proxy festgelegt werden. • Integration Die Aufgabe des Integrationssubsystems ist die Einbindung des QoS-Proxys in die Tuscany-Architektur. • Proxy Das Proxy-Subystem ist eine Art Hülle für die angegebenen Subsysteme und realisiert die Anpassung einer bestehende SCA-Anwendung. In den folgenden Abschnitten 4.2 bis 4.7 werden die Detailentwürfe der Subsysteme vorgestellt. Abschnitt 4.7 behandelt den Zusammenhang zwischen den einzelnen Subsystemen. Die Zusammenfassung in Abschnitt 4.8 beschreibt die Zusammenarbeit der einzelnen Subsysteme anhand eines Anwendungsfalls aus Kapitel 3.1. 4.2 4.2.1 Queueing-Subsystem Überblick Abbildung 4.2 präsentiert einen Überblick über alle am Queueing-Subsystem beteiligten Klassen. Das Queueing-Subsystem stellt die Queueing-Strategien und die dazu benötigten Datenstrukturen bereit. Jede Queueing-Strategie erbt von der abstrakten Klasse Strategy und stellt eine eigene Implementierung der abstrakten Klasse ItemList zur Verwaltung der Aufträge zur Verfügung. Die Klasse ItemList besitzt ein QueueStatistic-Objekt, in dem Statistiken zur Queue festgehalten werden. Die 69 4.2. Queueing-Subsystem Kapitel 4. Design tatsächliche Queue wird durch eine ArrayList aus Objekten vom Typ Queue realisiert. Dabei besitzt wiederum eine Queue eine ArrayList von Item-Objekten, die die Aufträge im Queueing-Subsystem repräsentieren. Jede Queueing-Strategie erbt als At- LeakyBucket 1 Thread #bucket 1 WeightedFairQueueing Strategy ClassBasedQueueing HierarchicalTokenBucket 1 1 1 1 - queue 1 WeightedFairQueueingItemList -queue ClassBasedQueueingItemList -queue 1 HierarchicalTokenBucketItemList ItemList Queue <<bind>> 1 1 1 -queue 1 1 -statistic QueueStatistic E > Element ArrayList -list 1 Item <<bind>> ItemStatistic -statistic 1 1 Abbildung 4.2: Klassendiagramm: Überblick Queueing-Subsystem tribut die Implementierung des Leaky-Bucket-Algorithmus die Klasse LeakyBucket. Sowohl die einzelnen Queueing-Strategien als auch die Realisierung des Leaky-BucketAlgorithmus implementieren einen Thread. 70 Kapitel 4. Design 4.2.2 4.2. Queueing-Subsystem Beschreibung der Klassen Item und ItemStatistic Jede Instanz der Klasse Item verwaltet genau einen Auftrag. In der Klasse wird ein Objekt vom Typ Thread abgelegt. Dabei entspricht das Thread-Objekt einem InterceptorThread der zu implementierenden Policy-Erweiterung. Zusätzlich führt die Klasse die Statistik zu dem Thread in einem Objekt vom Typ ItemStatistic mit. Abbildung 4.3 repräsentiert die Klasse Item und ItemStatistic. Zusammen mit der Referenz auf den Thread werden eine Reihe von weiteren Parametern in der Klasse Item gespeichert. Zu den Parametern zählt der Name, die Priorität und die Dienstgüteklasse des Services. Die Klasse Item stellt get- und set-Methoden für die Parameter zur Verfügung. Um den abgelegten Thread in den Zustand Wartend oder Aktiv versetzen Item ItemStatistic <<constructor>>+Item() +getPriority() : int +setPriority( prio : int ) : void +getService() : String +getQueueingClass() : String +suspend() : void +resume() : void +getStatistics() : ItemStatistic +setService( ser : String ) : void +setQueueingClass( queueing : String ) : void +setThread( thr : Thread ) : void 1 1 -statistic +setRequestTime() : void +setExposureTime() : void +setResponseTimeOnRequest() : void +setResponseTimeAfterRequest() : void +getExposureTime() : double +getResponseTime() : double +getTotalRequestTime() : double +toString() : String +setService( name : String ) : void +getService() : String Abbildung 4.3: Klassendiagramm: Item zu können, stehen die Methoden suspend() und resume() zur Verfügung. In der Klasse ItemStatistic werden die in Abschnitt 3.4.2.2 vorgestellten Messgrößen gespeichert, um später Kenngrößen wie Verweilzeit, Bearbeitungszeit oder Wartezeit bestimmen zu können. Über die Methode getStatistic() in der Klasse Item wird das ItemStatistic-Objekt eines Interceptor-Threads zurückgegeben. Queue Die Klasse Queue repräsentiert eine Queue für Item-Objekte. In der Klasse werden die Item-Objekte in einer Listenstruktur abgelegt und verwaltet. Dabei besitzt jede Queue optional eine Priorität und ein Gewicht. Abbildung 4.4 zeigt das Klassendiagramm für die 71 4.2. Queueing-Subsystem Kapitel 4. Design Queue <<constructor>>+Queue( p : int, w : int ) +add( item : Item ) : boolean{guarded} +size() : int{guarded} +update( weight : int, priority : int ) : void{guarded} +get( index : int ) : Item{guarded} +remove( index : int ) : Item{guarded} +getPriority() : int{guarded} +getWeight() : int{guarded} Abbildung 4.4: Klassendiagramm: Queue Klasse Queue. Die Methode add() fügt ein Item-Objekt zur Liste hinzu, remove() entfernt ein Item-Objekt. Die Methode size() gibt die Anzahl der Item-Objekte in der Queue zurück. Über die Funktion update() können das Gewicht und die Priorität einer Queue aktualisiert werden. Die Methode remove() entnimmt ein Item-Objekt. Mit den Methode getPriority() und getWeight() kann die Priorität bzw. das Gewicht einer Queue bestimmt werden. QueueStatistic Die Klasse QueueStatistic sammelt die Statistiken zu einer Queueing-Strategie. Abbildung 4.5 stellt das Klassendiagramm für die Klasse QueueStatistic vor. Mit der Methode addQueueData() werden die Statistiken einer Queue hinzugefügt. Parameter der Funktion ist die zugehörige Queueing-Strategie, die Nummer, die Priorität, das Gewicht, die Anzahl der Aufträge in der Queue und die Anzahl der bereits abgearbeiten Aufträge der Queue. Über die Methode addItemData() werden Daten zur der Queueing-Strategie, von der das Item-Objekt bearbeitet wurde, übergeben. Dazu zählt die Nummer der Queue, der Service und die Verweilzeit in der Queue. Mit der Methode getItemData() werden die Statistiken der Item-Objekte zurückgegeben. Die Statistiken, aufgeschlüsselt nach Queueing-Strategie und Queue, werden über die Methode getQueueData() bestimmt. Die Methode getCombinedData() gibt die gesammelten Daten zusammengefasst zurück. ItemList Mit Hilfe der abstrakten Klasse ItemList wird eine Liste definiert, in der Aufträge einer Queueing-Strategie abgelegt werden können. Die Klasse ItemList stellt bekannte Operationen auf Listen zur Verfügung. Abbildung 4.6 stellt die Klasse ItemList 72 Kapitel 4. Design 4.2. Queueing-Subsystem QueueStatistic +addItemData( strategy : String, queue : String, service : String, duration : long ) +addQueueData( strategy : String, queue : String, priority : int, weight : int, current : int, done : int ) +getItemData() : String[] +getQueueData() : String[] +getCombinedData() : String[] Abbildung 4.5: Klassendiagramm: QueueStatistic vor. Zu den definierten Methoden der Klasse gehören die Methoden get(), add() und remove(). Die Methode get() gibt ein entsprechendes Element zurück. Mit Hilfe der Methode add() werden Aufträge hinzugefügt. Über die Methode remove() werden Aufträge entfernt. ItemList +add( item : Item ) : boolean +remove( index : int, queue : int ) : Item +size( queue : int ) : int +get( index : int, queue : int ) : Item Abbildung 4.6: Klassendiagramm: ItemList Strategy In der abstrakten Klasse Strategy werden die grundlegenden Operationen einer Queueing-Strategie beschrieben. Abbildung 4.7 stellt das zugehörige Klassendiagramm vor. Zu den grundlegenden Operationen gehören die Methoden add(), run(), schedule() und requeue(). Über die Methode add() wird ein Auftrag an die QueueingStrategie übergeben. Die Klasse erweitert die Thread-Klasse und überschreibt die Methode run(). Innerhalb der Methode wird die schedule()-Methode aufgerufen, welche die tatsächliche Queueing-Strategie realisiert. Mit Hilfe der Methode requeue() werden die Aufträge, die sich in der Queue einer Queueing-Strategie befinden, an die Queue einer neuen Queueing-Strategie übergeben. Die Methode soll das Wechseln der Queueing-Strategie während des laufenden Betriebs erleichtern. Da jede Queueing-Strategie als Thread implementiert wird, müssen bei der Implementierung bekannte Nebenläufigkeitskonzepte betrachtet werden. Eine 73 4.2. Queueing-Subsystem Kapitel 4. Design Strategy <<constructor>>+Strategy( name : String ) +add( item : Item ) : void +schedule() : void +dumpActiveThreads() : void +run() : void +getStrategyName() : String +requeue( strategy : Strategy ) : void +getLeakyBucket() : LeakyBucket Abbildung 4.7: Klassendiagramm: Strategy Queueing-Strategie sollte nur wirklich dann aktiv sein, wenn Aufträge abgearbeitet werden. Realisiert werden kann dies über eine Semaphore in der entsprechenden ItemListImplementierung, deren Wert sich mit jedem hinzugefügten Auftrag erhöht und jedem entnommen Auftrag verringert. Erreicht die Semaphore den Wert Null und versucht der Thread den Wert der Semaphore zu senken, so blockiert der Thread an dem Aufruf. Der Thread wird erst dann wieder aktiv wenn Aufträge in die ItemList-Implementierung abgelegt werden. LeakyBucket Der Leaky-Bucket-Algorithmus (vergleiche 2.3.2.5) ist unter anderem verantwortlich für die Umsetzung von Durchsatzanforderungen. Realisiert wird der Leaky-BucketAlgorithmus durch die Klasse LeakyBucket. Jede Queueing-Strategie besitzt ein Objekt vom Typ LeakyBucket. Die Klasse definiert verschiedene get- und setMethoden für die Parameter des Algorithmus. Parameter des Algorithmus sind die Erzeugungsrate der Tokens, die Größe des Buckets und die Anzahl der aktuell verfügbaren Tokens. Abbildung 4.8 stellt das Klassendiagramm vor. Für jeden Auftrag, den ei- LeakyBucket <<constructor>>+LeakyBucket( s : int, i : int, r : long, n : int ) +take() : boolean +getSize() : int{guarded} +>+getAvailableTokens() : int{guarded} +getRate() : double{guarded} +setRate( rate : double ) : void{guarded} +getNumber() : int{guarded} +setNumber( n : int ) : void{guarded} Abbildung 4.8: Klassendiagramm: LeakyBucket 74 Kapitel 4. Design 4.2. Queueing-Subsystem ne Queueing-Strategie bearbeitet, wird ein Token aus dem Bucket des Leaky-BucketAlgorithmus entnommen. Sollten mehr Aufträge in den einzelnen Queues vorliegen als Tokens verfügbar sind, so wartet die Queueing-Strategie nicht aktiv darauf, dass Tokens verfügbar sind, sondern es werden entsprechende Datenstrukturen, wie sie sich beispielsweise in den Concurrency Utilities der Java API befinden, vorgesehen. Der Bucket der Klasse LeakyBucket kann beispielsweise als BlockingQueue implementiert werden. 4.2.3 Beispiel: Weighted-Fair-Queueing-Algorithmus Der Weighted-Fair-Queueing-Algorithmus wird durch die Klasse WeightedFairQueueing implementiert. Aufträge in Form von Item-Objekten legt die Queueing-Strategie in einem Objekt der Klasse WeigtedFairQueueingItemList ab. Abbildung 4.9 stellt das Klassendiagramm der beteiligten Klassen vor. Der Konstruktor der Klasse WeightedFairQueueingItemList <<constructor>>+WeightedFairQueueingItemList( weight : int, divider : int ) +add( item : Item ) : boolean{guarded} +remove( index : int, queue : int ) : Item +size( queue : int ) : int{guarded} +totalSize() : int{guarded} +get( index : int, queue : int ) : Item{guarded} +createQueue( priority : int ) : boolean{guarded} +getWeightFromQueue( queue : int ) : int{guarded} +getMaximumWeight() : int{guarded} +available() : boolean +dumpQueues() : void 1 -queues 1 WeightedFairQueueing <<constructor>>+WeightedFairQueueing( bucket : LeakyBucket, divider : int, maximumWeight : int ) +schedule() : void +run() : void +add( item : Item ) : void +getStrategyName() : String +requeue( strategy : Strategy ) : void +getLeakyBucket() : LeakyBucket{guarded} Abbildung 4.9: Klassendiagramm: WeightedFairQueueing und WeightedFairQueueingItemList WeightedFairQueueingItemList erhält als Parameter das maximal verfügbare Gewicht und den Divisor zur Bestimmung der Gewichte. Die Klasse ist eine AdapterKlasse, die Operationen auf Objekten vom Typ Queue erlaubt. Eine WeightedFair- 75 4.2. Queueing-Subsystem Kapitel 4. Design QueueingItemList kann dabei aus n-Queue-Objekten bestehen, wobei die QueueObjekte in einer ArrayList abgelegt werden. Über die Methode add() wird ein Item-Objekt hinzugefügt. Mit der Methode remove() wird ein entsprechendes Item-Objekt aus der Queue entfernt. Die Methode size() gibt die Größe einer Queue in der WeightedFairQueueingItemList zurück. Die Anzahl der Queues der WeightedFairQueueingItemList kann über die Methode getTotalSize() ermittelt werden. Über die Methode get() erhält man ein ItemObjekt, ohne es aus einer Queue zu entfernen. Mit der Methode createQueue() wird eine neue Queue in der Klasse WeightedFairQueueing erzeugt. Ablauf zur Laufzeit Abbildung 4.10 stellt das Sequenzdiagramm zur Bearbeitung eines Auftrags durch die Queueing-Strategie Weighted Fair Queueing vor. Der Auftrag wird in Form eines ItemObjektes an ein WeightedFairQueueing-Objekt mit der Methode add() übergeben. Der Algorithmus erhält über die Methode getThread() eine Referenz auf das in der Klasse Item abgelegte Thread-Objekt und versetzt den Thread in den Zustand Wartend. Das WeightedFairQueueing-Objekt fügt das Objekt mit der Methode add() in seine WeightedFairQueueingItemList ein. In der run()-Methode der Klasse WeightedFairQueueing wird die Methode schedule() aufgerufen, die den Algorithmus der Queueing-Strategie implementiert. Für jede Queue im WeightedFairQueueingItemList-Objekt prüft der Algorithmus, ob Aufträge in der Queue abgelegt sind. Falls das der Fall ist, versucht der Algorithmus, die Aufträge zu bearbeiten. Das WeightedFairQueueing-Objekt bearbeitet maximal soviele Aufträge, wie das Gewicht der Queue ist. Für jeden Auftrag versucht die Methode mit dem Aufruf von take() einen Token aus dem Bucket des Leaky-Bucket-Algorithmus zu entnehmen. Falls ein Token verfügbar ist, wird ein Item-Objekt aus der Queue entnommen. Über die Methode getThread() wird eine Referenz auf das zugehörige Thread-Objekt im Item-Objekt zurückgegeben. Der Thread wird in den Zustand Aktiv gesetzt. 76 Kapitel 4. Design : Item 4.3. Monitoring-Subsystem : WeightedFairQueueing : WeightedFairQueueingItemList : Queue : LeakyBucket 1: add() 2: getThread() 3: add() 4: run() 5: add() 6: schedule() loop [for every queue in the weightedfairqueueingitemlist] loop [for every item in the queue and weight is available for the queue] 7: take() alt [if take was successful] 8: remove() 9: getThread() [else] Abbildung 4.10: Sequenzdiagramm: Bearbeitung eines Interceptors durch eine QueueingStrategie 4.3 4.3.1 Monitoring-Subsystem Überblick Zu den Aufgaben des Monitoring-Subsystem gehört das Sammeln und Erzeugen von Statistiken der einzelnen Subsysteme. Dabei werden die erzeugten Statistiken über JMX Management-Anwendungen zur Verfügung gestellt. 4.3.2 Beschreibung der Klasse Das Statistiksubsystem besteht aus der Klasse Statistic und dem Interface StatisticMBean. Das Interface definiert die Methoden die über JMX bereitgestellt werden. Die Klasse Statistic implementiert das Interface StatisticMBean. Abbildung 4.11 stellt das Klassendiagramm vor. 77 4.3. Monitoring-Subsystem Kapitel 4. Design StatisticMBean +getItemData() : String"[]" +getItemMinData() : String"[]" +getItemMaxData() : String"[]" +getItemAverageData() : String"[]" +getItemStandardDeviationData() : String"[]" +setInterval( start : int, stop : int ) : void +getItemDataSize() : int +getServices() : String"[]" +getServiceLevelAgreementSuccessful() : int +getServiceLevelAgreementFailed() : int +resetInterval() : void +setFilter( filter : String ) : void +getFilter() : String +resetFilter() : void +setItemDataCVSFileName( file : String ) : void +getItemDataCVSFileName() : String +exportItemDataToCVSFile() : void +getItemsInQueue() : int +getQueueData() : String"[]" +getQueueItemData() : String"[]" Statistic <<constructor>>+Statistic() +getItemData() : String"[]" +getItemMinData() : String"[]" +getItemMaxData() : String"[]" +getItemAverageData() : String"[]" +getItemStandardDeviationData() : String"[]" +setInterval( startInterval : int, stopInterval : int ) : void +getItemDataSize() : int +getServices() : String"[]" +getServiceLevelAgreementSuccessful() : int +getServiceLevelAgreementFailed() : int +resetInterval() : void +setFilter( filter : String ) : void +getFilter() : String +resetFilter() : void +setItemDataCVSFileName( file : String ) : void +getItemDataCVSFileName() : String +exportItemDataToCVSFile() : void +getItemsInQueue() : int +updateQueueData() : void +getQueueData() : String"[]" +getQueueItemData() : String"[]" +addItemStatistic( statistic : ItemStatistic ) : void +addQueueStatistic( stat : QueueStatistic ) : void +addServiceLevelAgreementFailed() : void +addServiceLevelAgreementSuccessful() : void Abbildung 4.11: Klassendiagramm: Statistic Der Erfolg des QoS-Proxys wird in der Einhaltung von Service Level Agreements gemessen. Ein Service Level Agreement ist üblicherweise über einen relativ langen Zeitraum gültig. Um eine mittelfristige Bewertung des QoS-Proxys zu erleichtern, können die in 3.4.2 vorgestellten Mess- und Kenngrößen zur Leistungsbewertung herangezogen werden. Der QoS-Proxy wird an fünf Punkten instrumentiert, um die entsprechenden Messwerte bestimmen zu können. Der erste Instrumentierungspunkt befindet sich kurz nach dem Aufruf der invoke()Methode des Interceptors. Weitere Instrumentierungspunkte befinden sich vor dem Einfügen in die Queue und nach dem Entfernen aus der Queue. Die letzten beiden Messungen werden kurz vor dem tatsächlichen Absetzen des Web-Service-Aufruf und kurz nach der Antwort des Web Services vorgenommen. Die Statistik-Objekte des Queueing- und Integrationssubsystem werden über die Methoden addQueueStatistic() und addPolicyStatistic() eingefügt. Die Methode getPolicyData() gibt alle gesammelten Datensätze des Integrationssubystems zurück. Aus den gesammelten Datensätzen werden die Minimal-, Maximalund Durchschnittswerte sowie die Standardabweichung bestimmt. Über die Methode setInterval() lässt sich die Anzahl der Datensätze einschränken. Das Interval kann mit der Methode resetInterval() zurückgesetzt werden. Die Methode 78 Kapitel 4. Design 4.3. Monitoring-Subsystem getPolicyDataSize() gibt die Anzahl der Datensätze des Integrationssubystems zurück. Die Methode getServices() gibt eine Liste aller vom QoS-Proxy behandelten Services zurück. Sollte ein SLA während der Lebenszeit des Proxys terminiert werden, so wird in Abhängigkeit von der Art der Terminierung mit der Methode addSuccessfulServiceLevelAgreement() oder addFailedServiceLevelAgreement() ein entsprechender Zähler erhöht. Ein Grund für ein erfolgreiches SLA ist das Beenden durch das Erreichen des Ablaufdatums des SLA. Während der Lebenszeit des SLAs sind keine Verletzungen des SLAs eingetreten, die zu einer Terminierung des SLAs geführt hätten. Die Methode addSuccessfulServiceLevelAgreement() wird aufgerufen. Wird ein SLA durch den Client terminiert, weil Service Level Objectives nicht eingehalten wurden, so wird die Methode addFailedServiceLevelAgreement() aufgerufen. Über die Methode getSuccesfulServiceLevelAgreement() und getFailedServiceLevelAgreement() wird die Anzahl der erfolgreichen, beziehungsweise der nicht erfolgreichen, Service Level Agreements zurückgegeben. Über die Methode setFilter() kann auf einen Web-Service eingeschränkt werden. Der Filter wirkt sich auf alle Methoden aus, auf die der Filter anwendbar ist. Beispielsweise werden beim Aufruf der Methode getPolicyData() nur noch die Datensätze zurückgegeben, die auf den Filter zutreffen. Die Methode getFilter() gibt den aktuell gesetzten Filter zurück. Der Filter kann über die Methode resetFilter() zurückgesetzt werden, alternativ kann auch ein leerer Filter gesetzt werden. Um das Auswerten der Statistiken des Integrationssubsystem zu erleichtern, kann mit der Methode setPolicyDataCSVFileName() eine Datei angegeben werden, in der die gesammelten Daten des Integrationssubsystem in eine CSV-Datei mit dem Aufruf der Methode exportPolicyDataToCSV() geschrieben werden. Über die Methode getPolicyDataCSVFileName() wird der Name der CSV-Datei zurückgegeben. Mit Hilfe der Methode getQueueData() werden die gesammelten Datensätze des Queueing-Subsystems zurückgegeben. Über die Methoden getQueueMinData(), getQueueMaxData(), getQueueAverageData() werden aus den gesammelten Datensätzen die Minimal-, Maximal- sowie die Durchschnittswerte bestimmt. 79 4.4. WS-Agreement-Subsystem 4.4 4.4.1 Kapitel 4. Design WS-Agreement-Subsystem Überblick Das WS-Agreement-Subsystem definiert die Kommunikation und das Protokoll zwischen einem WS-Agreement-System und dem Konfigurationssubsystem. Das Konfigurationssubsystem erzeugt auf Grundlage von Angaben zur Leistungsfähigkeit eines Services verschiedene Agreement Templates und registriert sie an einem WSAgreement-System. Ein Agreement Template repräsentiert eine Dienstgüteklasse, wobei es mehrere unterschiedliche Agreement Templates zu einer Dienstgüteklasse geben kann. Das WS-Agreement-System bietet die unterschiedlichen Agreement Templates einem Client an. Der Client erzeugt auf Grundlage der Agreement Templates ein Agreement Offer. Das Agreement Offer wird vom WSAgreement-System auf gültige Parameter hin überprüft. Sind die Parameter im Agreement Offer gültig, so erzeugt das WS-Agreement-System ein Agreement mit dem Client (vergleiche Kapitel 2.1.2). Unter Umständen ist ein WS-Agreement-System nicht immer verfügbar oder das Erzeugen von Service Level Agreements soll über einen andere Software erfolgen. Für diesen Fall wird eine Schnittstelle auf Basis einer XML-Datei es erlauben, bereits abgeschlossene Service Level Agreements dem Konfigurationssubsystem zur Verfügung zu stellen. Die Kommunikation zwischen dem WS-Agreement-System und dem Konfigurationssubsystem erfolgt auf Basis von RMI. Das Erzeugen der Agreement Templates auf Grundlage von Angaben zur Leistungsfähigkeit des Services ist Aufgabe des Konfigurationssubsystems. Im Interface ICallback werden die Operationen definiert, die das WSAgreement-System am QoS-Proxy aufruft. Abbildung 4.12 zeigt die für die Kommunikation relevanten Klassen. Das Interface IServiceLevelManagement definiert die Operationen, die der QoS-Proxy am WS-Agreement-System aufruft. Zusammen mit dem Interface ICallback definiert das Interface das Kommunikationsprotokoll zwischen einem WS-Agreement-System und dem QoS-Proxy. Die Klasse AgreementManager implementiert das Interface IServiceLevelManagement. 80 Kapitel 4. Design 4.5. Konfigurationssubsystem IServiceLevelManagement +report( information : String[] ) : void +register( callback : ICallback ) : void +createTemplate( template : String[] ) : void AgreementManager ICallback 1 +createTemplate( template : String[] ) : void +report( information : String[] ) : void +register( callback : ICallback ) : void 1 +notify( message : String ) : void -callback +notifyAgreement( agreement : String[] ) : void +notifyTermination( id : String ) : void Abbildung 4.12: Klassendiagramm: ICallback, IServiceLevelManagement, AgreementManager 4.4.2 Beschreibung der Klasse AgreementManager Die Klasse AgreementManager implementiert die durch das Interface IServiceLevelManagement bereitgestellten Methoden. Über den Aufruf der Methode register() wird ein Callback-Objekt im WS-Agreement-System registriert. Die Klasse AgreementManager ist daraufhin in der Lage, die Methoden des Objektes aufzurufen und dem QoS-Proxy mitzuteilen, ob beispielsweise ein Agreement Template erfolgreich registriert wurde. Erzeugt werden Agreement Templates über den Aufruf der Methode createTemplate(). Kann der QoS-Proxy ein Agreement nicht einhalten, so meldet der Manager mit Hilfe der Methode report() die Verletzung des zugehörigen Agreements. 4.5 4.5.1 Konfigurationssubsystem Überblick Abbildung 4.13 präsentiert einen Überblick über alle am Konfigurationssubsystem beteilitigen Klassen. Die Aufgaben des Konfigurationssubsystems umfassen die Konfiguration des Proxys zum Zeitpunkt des Starts und während des Betriebes. Weiterhin bestimmt das Subsystem die Service Level Agreements zu einem Service, die die zeitliche Anforderungen an das Queueing-Subsystem festlegen. Grundlage für die Bestimmung der Service 81 4.5. Konfigurationssubsystem Kapitel 4. Design ServiceLevelAgreementFile Callback 1 -callback -serviceLevelAgreementFile 1 1 1 -strategy 1 1 Manager 1 ConfigurationFile -configuration ICallback ManagerMBean 1 1 1 1 1 1 LeakyBucket -bucket 1 -qos key > Element value > Element HashMap Strategy ServiceLevelAgreementList <<bind>> ServiceClass 1 1 - list E > Element ArrayList <<bind>> String <<bind>> ServiceLevelAgreement Abbildung 4.13: Überblick über das Konfigurationssubsystem Level Agreements bildet die in Abschnitt 4.4 beschriebene Kommunikation mit einem WS-Agreement-System. Die Klasse Manager besitzt Referenzen zu anderen Teilen der Architektur des QoSProxys. Der Manager bietet vereinfachte und einheitliche Schnittstellen zu anderen Subsystemen und orientiert sich damit am Fassaden-Entwurfsmuster [GHJ95]. Die Klassen ConfigurationFile und ServiceLevelAgreementFile sind Laufzeitrepräsentierung der entsprechenden Konfigurationsdateien. Die Klasse ConfigurationFile verwaltet ServiceClass-Objekte in einer HashMap der Schlüssel ein String und Wert ein ServiceClass-Objekt ist. Aus einzelnen ServiceClass-Objekten werden in der Klasse Manager verschiedene Agreement Templates erzeugt. Gespeichert werden die ServiceLevelAgreementList die eine Liste zur Verwaltung von ServiceLevelAgreement-Objekten bereitstellt. Realisiert wird die Klasse durch Operationen auf eine ArrayList von ServiceLevelAgreementObjekten. Neben den Java-Objektrepräsentierungen der Konfigurationsdateien verfügt der Manager über Referenzen zum Queueing-Subsystem und stellt Verwaltungsoperationen auf das Queueing-Subsystem zur Verfügung. 82 Kapitel 4. Design 4.5. Konfigurationssubsystem 4.5.2 Konfiguration des QoS-Proxys 4.5.2.1 Initialisierung Die initiale Konfiguration des QoS-Proxys soll über eine XML-Datei erfolgen. Quellcode 4.1 stellt das XML-Schema für eine QoS-Proxy-Konfigurationsdatei vor. 1 <xml xmlns="http://www.osoa.org/xmlns/sca/1.0" 2 targetNamespace="http://tuscany.apache.org/xmlns/sca/1.0" 3 xmlns:sca="http://www.osoa.org/xmlns/sca/1.0" 4 xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.0" 5 xmlns:xs="http://www.w3.org/2001/XMLSchema"> 6 7 <hostName>xs:anyURI</hostName> 8 <loggingConfigurationFile>xs:string</loggingConfigurationFile> 9 <leakyBucket size="xs:int" initial="xs:int" rate="xs:float" token="xs:int" 10 unit="xs:string"/> 11 <weightedFairQueueing weight="xs:int"/> 12 <qosResponseTime service="xs:string" class="xs:string" max="xs:float" 13 unit="xs:float"/> 14 <qosThroughPut service="xs:string" class="xs:string" min="xs:float" max="xs:float" 15 unit="xs:string"/> 16 <rmiRegistry>xs:string</rmiRegistry> | 17 <slaFileLocation>xs:string</slaFileLocation> 18 <qosClass>xs:string</qosClass> 19 20 </xml> Quellcode 4.1: QoS-Proxy-XML-Schema der Konfigurationsdatei Das Element hostName in Zeile 7 definiert die URL zum Service, darauf aufbauend werden später beim Erzeugen der Agreement Templates die URLs zu den einzelnen Dienstgüteklassen eines Services erzeugt. Um interne Vorgänge im QoS-Proxy transparent mitverfolgen zu können, wird ein Logging-Mechanismus genutzt, der Log-Ausgaben in eine Datei schreibt. Für das Logging stehen verschiedene Systeme zur Auswahl, wie beispielsweise die Java Logging API [Ham01] oder log4j [Gup05]. Über das Element loggingConfigurationFile in Zeile 8 kann der Name und Ort einer Konfigurationsdatei für das Logging zur Verfügung gestellt werden. In der QoS-Proxy-Konfigurationsdatei werden initiale Parameter für die im QoS-Proxy verwendeten Algorithmen festgelegt. In Zeile 9 wird das Element leakyBucket definiert. Parameter des Algorithmus sind die Attribute size, initial, rate, token und unit. Das Attribut size legt die Größe des Buckets fest (vergleiche 2.3.2.5). Die Anzahl der initial verfügbaren Tokens wird mit dem Attribut initial definiert. Mit Hilfe des Attributes rate und token wird die Erzeugungsrate und die Anzahl der pro Rate 83 4.5. Konfigurationssubsystem Kapitel 4. Design erzeugten Tokens bestimmt. Das Attribut unit definiert die Einheit, in der die Erzeugungsrate vorliegt. Das Element weightedFairQueueing in Zeile 11 definiert die initialen Parameter für den Weighted-Fair-Queueing-Algorithmus (vergleiche 2.3.2.3). Das Atttribut weight legt das maximale Gewicht des Algorithmus fest. Aus den Elementen qosResponseTime und qosThroughPut werden die Agreement Templates für einen Service erzeugt. Die Attribute entsprechen den Attributen der QoS-Erweiterung für WS-Agreement wie sie in 2.1.3 vorgestellt wurden. Die Kommunikation mit dem WS-Agreement-System erfolgt auf Basis von RMI. Über das Element rmiRegistry in Zeile 16 wird der Hostname der Registry gesetzt. Ist das Element rmiRegistry nicht gesetzt, so müssen die SLAs in Form einer Datei vorliegen. Der Ort und Name der Datei wird über das Element slaFileLocation in Zeile 17 festgelegt. Über das Element qosClass in Zeile 18 erhält der QoS-Proxy seine Dienstgüteklassen, dabei wird pro Dienstgüteklasse eine Queue angelegt. Quellcode 4.2 stellt das XML-Schema der Service-Level-Agreement-Datei vor. Eine Service-Level-Agreement-Datei (SLA-Datei) besteht aus mindestens einem agreementElement. Das agreement-Element entspricht dabei einem Service Level Agreement. Jedes agreement-Element verfügt über die Attribute name und service. Das Attribut name vergibt einen eindeutigen Namen für das Agreement. Das Attribut service benennt den zum Agreement zugehörigen Service. 1 <xml version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" encoding="UTF-8"> 2 { 3 <agreement name="xs:string" service="xs:string"> 4 <client>xs:sequence</client> 5 <responseTime max="xs:float" unit="xs:string"/> 6 <throughput min="xs:float" max="xs:float" unit="xs:string"/> 7 <expiration>xs:any</expiration> 8 </agreement> 9 } + 10 <xml> Quellcode 4.2: XML-Schema der Service-Level-Agreement-Datei Das agreement-Element hat die folgenden vier Kindelemente: client-, responseTime-, throughput- und expiration. Im client-Element in Zeile 4 wird eine Liste mit zulässigen Clients für das Agreement hinterlegt. Die Elemente responseTime 84 Kapitel 4. Design 4.5. Konfigurationssubsystem und throughput in Zeile 5 und 6 entsprechen den Dienstgüteeigenschaften Antwortzeit und Durchsatz. Beide Elemente verfügen über die Attribute unit und max. Das Attribut unit gibt eine Einheit an, in der die Werte vorliegen. Über das Attribut max wird ein maximaler Wert definiert. Über das Attribut min, welches zusätzlich im Element throughput definiert ist, wird ein minimaler Wert bestimmt. Das Element expiration in Zeile 7 legt ein Ablaufdatum für das Agreement fest. Realisiert wird die initiale Konfiguration des QoS-Proxys durch eine Klasse ConfigurationFileReader. Die Klasse liest sowohl die Konfigurationsdatei des QoS-Proxys als auch eine optionale Service-Level-Agreement-Datei. Die Werte der Konfigurationsdatei werden in einem Objekt vom Typ ConfigurationFile abgelegt, die der SLADatei in einem Objekt vom Typ ServiceLevelAgreementFile. 4.5.2.2 Management Der QoS-Proxy soll auch zur Laufzeit konfigurierbar sein. Um eine einheitliche Schnittstelle zur Verfügung zu stellen, nutzt das Konfigurationssubsystem wie auch das MonitoringSubsystem JMX. Die JMX-Schnittstelle wird im Interface ManagerMBean definiert und durch die Klasse Manager implementiert. 4.5.3 Beschreibung der Klassen Callback Die Klasse Callback implementiert die im Interface ICallback definierten Methoden. Über den Aufruf der Methode notify() wird dem QoS-Proxy eine allgemeine Nachricht mitgeteilt. Eine solche Nachricht könnte das erfolgreiche Registrieren von Agreement Templates am WS-Agreement-System oder Statusmitteilungen sein. Die Methode notifyAgreement() wird aufgerufen, wenn das WS-AgreementSystem mit einem Client ein Agreement abgeschlossen hat. Wird ein Agreement beendet, so wird der QoS-Proxy über die Methode notifyTermination() darüber informiert. 85 4.5. Konfigurationssubsystem Kapitel 4. Design ICallback +notify( message : String ) : void +notifyAgreement( agreement : String[] ) : void +notifyTermination( id : String ) : void Callback +notify( message : String ) : void +notifyTermination( id : String ) +notifyAgreement( agreement : String[] ) : void Abbildung 4.14: Klassendiagramm: ICallback und Callback ServiceClass Die Klasse ServiceClass repräsentiert die responseTime- und throughputElemente der Konfigurationsdatei als Java-Klasse. Üblicherweise werden ServiceClass-Objekte beim Einlesen der Konfigurationsdatei durch die Klasse ConfigurationFileReader erzeugt und in einer Liste in der Klasse ConfigurationFile abgelegt. Abbildung 4.15 stellt das Klassendiagramm der Klasse vor. Die Klasse be- ServiceClass <<constructor>>+ServiceClass( s : String ) +getQosClass() : String +setQosClass( c : String ) : void +getServiceClass() : String +setServiceClass( serviceClass : String ) : void +getResponseTime() : double +setResponseTime( responseTime : double ) : void +getResponseTimeUnit() : String +setResponseTimeUnit( responseTimeUnit : String ) : void +getThroughputMinValue() : double +setThroughputMinValue( throughputMinValue : double ) : void +getThroughputMaxValue() : double +setThroughputMaxValue( throughputMaxValue : double ) : void +getThroughputUnit() : String +setThroughputUnit( throughputUnit : String ) : void +setUrl( host : String ) : void +getUrl() : String +getOperator() : String +setOperator( operator : String ) : void Abbildung 4.15: Klassendiagramm: ServiceClass steht aus get- und set-Methoden der im vorherigen Abschnitt beschriebenen At- 86 Kapitel 4. Design 4.5. Konfigurationssubsystem tribute der Elemente responseTime und throughput. Aus den verschiedenen ServiceClass-Objekten werden in der Klasse Manager die Agreement Templates erzeugt und im WSAG4J-System registriert. ServiceLevelAgreement Die Klasse ServiceLevelAgreement repräsentiert ein Service Level Agreement in der Architektur des QoS-Proxys. Abbildung 4.16 stellt das Klassendiagramm der Klasse ServiceLevelAgreement vor. Die Klasse implementiert get- und set-Methoden für die Elemente einer SLA-Datei. Dabei implementiert die Klasse zusätzlich die Methode isValid(). Über diese Methode kann geprüft werden, ob das SLA noch gültig ist. Mit der Methode setValid() kann der Status des SLAs aktualisiert werden. ServiceLevelAgreement <<constructor>>+ServiceLevelAgreement( agreement : String"[]" ) <<constructor>>+ServiceLevelAgreement( service : String ) +getService() : String +getMaxResponseTime() : float +getMinThroughput() : double +getMaxThroughput() : double +getClient() : String +getResponseTimeUnit() : String +getThroughputUnit() : String +isValid() : boolean +setValid( valid : boolean ) : void +setService( service : String ) : void +setResponseTime( maxResponseTime : float ) : void +setMinThroughput( minThroughput : double ) : void +setMaxThroughput( maxThroughput : double ) : void +setClient( client : String ) : void +setResponseTimeUnit( responseTimeUnit : String ) : void +setThroughputUnit( throughputUnit : String ) : void Abbildung 4.16: Klassendiagramm: ServiceLevelAgreement ServiceLevelAgreementList Die Klasse ServiceLevelAgreementList stellt Verwaltungsoperationen für eine Liste von ServiceLevelAgreement-Objekten zur Verfügung. Abbildung 4.17 stellt das Klassendiagramm vor. Mit der add()-Methode wird ein ServiceLevelAgreement an die Klasse übergeben. Über die Methode remove() wird ein ServiceLevelAgreement aus der Klasse entfernt. Ein bestimmtes ServiceLevel- 87 4.5. Konfigurationssubsystem Kapitel 4. Design Agreement erhält man mit der Methode get(). Die Methode size() gibt die Größe der Liste zurück. ServiceLevelAgreementList <<constructor>>+ServiceLevelAgreementList() +add( agreement : ServiceLevelAgreement ) : boolean{guarded} +add( agreement : String"[]" ) : boolean{guarded} +add( agreement : ServiceLevelAgreement"[]" ) : boolean{guarded} +remove( service : String, client : String ) : boolean{guarded} +getResponseTime( service : String, client : String ) : double +get( service : String, client : String ) : ServiceLevelAgreement{guarded} Abbildung 4.17: Klassendiagramm: ServiceLevelAgreementList ServiceLevelAgreementFile Die Klasse ServiceLevelAgreementFile repräsentiert die SLA-Datei als JavaKlasse und stellt verschiedene get- und set-Methoden für die Elemente der Datei zur Verfügung. Abbildung 4.18 zeigt das Klassendiagramm der Klasse ServiceLevelAgreementFile. ServiceLevelAgreementFile +setService( service : String ) : void +setResponseTime( service : String, max : float, unit : String ) : void +setThroughPut( service : String, min : double, max : double, unit : String ) : void +toArray() : ServiceLevelAgreement"[]" Abbildung 4.18: Klassendiagramm: ServiceLevelAgreementFile ConfigurationFile Die Klasse ConfigurationFile ist die Repräsentierung der XML-Konfigurationsdatei in Form einer Java-Klasse. Die Klasse besteht im wesentlichen aus get- und setMethoden der Attribute. Attribute der Klasse sind die Elemente der XML-Konfigurationsdatei. Elemente, die beliebig oft auftreten können, werden in einer Liste in der Klasse verwaltet. Abbildung 4.19 repräsentiert das zugehörige Klassendiagramm. 88 Kapitel 4. Design 4.5. Konfigurationssubsystem ConfigurationFile <<constructor>>+ConfigurationFile() +getLoggingConfigurationFile() : String +setLoggingConfigurationFile( file : String ) : void +getQos() : HashMap<String, ServiceClass> +setQosResponseTime( s : String, c : String, max : float, unit : String, operator : String ) : void +setQosThroughPut( s : String, c : String, min : double, max : double, unit : String, operator : String ) : void +getRmiRegistry() : String +setRmiRegistry( registry : String ) : void +getSlaFileLocation() : String +setSlaFileLocation( location : String ) : void +setHostname( host : String ) : void +getHostname() : String +setWeightedFairQueueing( w : int ) : void +getWeightedFairQueueingWeight() : int +setLeakyBucket( r : long, s : int, n : int, u : String ) : void +getLeakyBucketRate() : long +getLeakyBucketSize() : int +getLeakyBucketNumber() : int +getLeakyBucketUnit() : String +setQosClass( list : String ) : void +getQosClass() : String Abbildung 4.19: Klassendiagramm: ConfigurationFile ConfigurationFileReader Die Klasse ConfigurationFileReader ist verantwortlich für das Lesen der Konfigurationsdateien des QoS-Proxy. Abbildung 4.20 stellt die Klasse vor. Eingelesen werden die Konfigurationsdateien über einen XMLStreamReader [BEA03]. In einem ersten Schritt wird die Konfigurationsdatei des QoS-Proxy über die Methode readConfigurationFile() eingelesen. Die Konfigurationsdatei liest initiale Konfigurationsparameter des QoS-Proxys aus. Sollte in der Konfigurationsdatei kein Wert für eine rmiRegistry gesetzt sein, so muss ein Element slaFileLocation gesetzt sein. Ist das Element slaFileLocation gesetzt, so wird die SLA-Datei über den Aufruf der Methode readSLAFile() eingelesen. Die Werte aus der SLA-Datei werden in Form eines ServiceLevelAgreementFile-Objektes zurückgegeben. ConfigurationFileReader +readConfigurationFile( reader : XMLStreamReader ) : ConfigurationFile +readSLAFile( reader : XMLStreamReader ) : ServiceLevelAgreementFile Abbildung 4.20: Klassendiagramm: ConfigurationFile 89 4.5. Konfigurationssubsystem Kapitel 4. Design Manager Die Klasse Manager implementiert die im Interface ManagerMBean definierten Methoden. In Abbildung 4.21 ist das Klassendiagramm der Klasse dargestellt. Über die Methode initialize() wird die RMI-Kommunikation initialisiert. Die Methode createTemplate() erzeugt Agreement Templates zu einem Service und registriert sie an einem WS-Agreement-System mit dem Aufruf der Methode registerTemplate(). Weiterhin stellt der Manager Methoden zum Wechseln der Queueing-Strategie zur Verfügung. Mit der Methode getQueueingStrategies() werden die verfügbaren Queueing-Strategien ermittelt. Über die Methode getActiveQueueingStrategy() wird die aktive Queueing-Strategie bestimmt und mit dem Aufruf der Methode setActiveQueueingStrategy() wird auf eine andere verfügbare Queueing-Strategie gewechselt. ManagerMBean +getQueueingStrategies() : String"[]" +getActiveQueueingStrategy() : String +setActiveQueueingStrategy( index : String ) : void +getBucketSize() : int +getTokenRate() : double +getAvailableToken() : int +setAvailableToken( value : int ) : void +getToken() : int +setToken( newToken : int ) : void +setTokenRate( time : double ) : void +getLoggingConfigurationFileLocation() : String +getServiceLevelAgreementFileLocation() : String Manager <<constructor>>+Manager() <<setter>>+setConfigurationFile( file : ConfigurationFile ) : void +initialize( hostname : String, name : String ) : void +createTemplates( templates : HashMap<String, ServiceClass> ) : void +getQueueingStrategies() : String"[]" +getActiveQueueingStrategy() : String +setActiveQueueingStrategy( index : String ) : void +getBucketSize() : int +getTokenRate() : double +getAvailableToken() : int +setAvailableToken( value : int ) : void +getToken() : int +setToken( newToken : int ) : void +setTokenRate( time : double ) : void +setAvailableQueueingStrategies( strategies : String"[]" ) : void +getLoggingConfigurationFileLocation() : String +getServiceLevelAgreementFileLocation() : String +getServiceLevelAgreementList() : ServiceLevelAgreementList Abbildung 4.21: Klassendiagramm: Manager Zu den Methoden der Klasse Manager gehören Methoden zum Anpassen des Leaky- 90 Kapitel 4. Design 4.5. Konfigurationssubsystem Bucket-Algorithmus. Mit der Methode getBucketSize() wird die Größe des Buckets ermittelt. Die Methode getTokenRate() gibt die Erzeugungsrate der Tokens zurück. Die Methode setTokenRate() setzt die Erzeugungsrate auf einen neuen Wert. Mit der Methode getTokenRateNumber() wird die aktuelle Anzahl der pro Rate erzeugte Tokens bestimmt, setTokenRateNumber() verändert die Anzahl der pro Rate erzeugte Tokens. Über die Methode getToken() kann die aktuell im Bucket befindliche Anzahl von Tokens bestimmt werden. Mit der Methode setToken() wird die Anzahl der Tokens neu gesetzt. Über eine Referenz auf die Klasse LeakyBucket kann der Durchsatz des QoS-Proxys reguliert werden. Die Methode setAvailableQueueingStrategies() informiert die Klasse Manager über die im QoS-Proxy registrierten Queueing-Strategien. Die Methode getServiceLevelAgreementList() gibt die ServiceLevelAgreeementList zurück. 4.5.4 Ablauf der Kommunikation zwischen dem WS-Agreementund dem Konfigurationssubsystem Abbildung 4.22 stellt das Sequenzdiagramm zur Kommunikation mit WS-Agreement vor. In einem ersten Schritt initialisiert der Manager in der Methode initialize() die RMI-Kommunikation und registriert sein Callback-Objekt am WS-AgreementSystem. Für jeden Service in der composite-Datei einer SCA-Anwendung erstellt der Manager mit der Methode createTemplates() aus den ServiceClassObjekten Agreement Templates, die im WS-Agreement-System über den Aufruf der Methode createTemplate() registriert werden. Wurde ein Agreement Template erfolgreich registriert, wird der Manager über das zugehörige Callback-Objekt benachrichtigt. Wird ein Agreement zwischen einem WS-Agreement-System erzeugt, so ruft die Klasse AgreementManager die Methode notifyAgreement() auf. In einem nächsten Schritt erhält die Klasse Callback über eine Referenz auf die Klasse Manager die Möglichkeit auf die ServiceLevelAgreementList zuzugreifen. Über die Methode getServiceLevelAgreementList() erhält die Klasse Callback eine Referenz auf das ServiceLevelAgreementList-Attribut der Klasse Manager und kann mit der Methode add() das neue Agreement hinzufügen. Das Agreement bildet damit die Anforderungen an das Queueing im QoS-Proxy. 91 4.6. Integrationssubsystem : ServiceLevelAgreementList Kapitel 4. Design : Manager : Callback : AgreementManager 1: initialize() 2: notify() 3: createTemplates() 4: createTemplate() 5: notify() 6: notifyAgreement() 7: getServiceLevelAgreementList() 8: add() Abbildung 4.22: Sequenzdiagramm: Kommunikation mit WSAG4J-System/QoS-Proxy 4.6 4.6.1 Integrationssubsystem Überblick Das Integrationssubsystem beschreibt die notwendigen Schritte zur Integration des QoSProxys in Tuscany. Neben einer Reihe von Hilfsklassen, die den QoS-Proxy als PolicyErweiterung registrieren (vergleiche 3.2.2), sind die folgenden Klassen von besonderer Bedeutung: • ProxyPolicyProcessor Der ProxyPolicyProcessor ist verantwortlich für das Lesen und Schreiben der Modelldaten der Policy-Erweiterung. • ProxyPolicyInterceptor Der ProxyPolicyInterceptor beinhaltet die Interceptor-Klasse, die in die Aufrufkette einer SCA-Anwendung eingefügt wird. 92 Kapitel 4. Design 4.6.2 4.6. Integrationssubsystem Beschreibung der Klassen ProxyPolicyProcessor Über das Element policySet und intent in der Datei definitions.xml einer SCA-Anwendung werden Angaben zur Policy hinterlegt. Ausgelesen wird die Datei über eine Implementierung des generischen Interface StAXArtifactProcessor der Klasse ProxyPolicyProcessor. ProxyPolicy m>M +getResourceBundleName() : String +setResourceBundleName( resourceBundleName : String ) : void +isUseParentHandlers() : boolean +setUseParentHandlers( useParentHandlers : boolean ) : void +getSchemaName() : QName +isUnresolved() : boolean +setUnresolved( unresolved : boolean ) : void +getConfigFileLocation() : String +setConfigFileLocation( logFileLocation : String ) : void StAXArtifactProcessor <<bind>> +read( reader : XMLStreamReader ) : M +write( model : M, writer : XMLStreamWriter ) : void +getArtifactType() : QName ProxyPolicyProcessor <<constructor>>+ProxyPolicyProcessor( modelFactories : ModelFactoryExtensionPoint ) +getArtifactType() : QName +read( reader : XMLStreamReader ) : ProxyPolicy +write( policy : ProxyPolicy, writer : XMLStreamWriter ) : void +getModelType() : Class<ProxyPolicy> +resolve( arg0 : ProxyPolicy, arg1 : ModelResolver ) : void Abbildung 4.23: Klassendiagramm: ProxyPolicyProcessor In Abbildung 4.23 ist das Klassendiagramm der Klasse ProxyPolicyProcessor dargestellt. Die Klasse wandelt die Daten aus der Datei definitions.xml in ein Modell der Policy, die durch die Klasse ProxyPolicy repräsentiert wird, um. Ausgelesen und geschrieben wird das Modell über einen StAX XMLStreamReader. Die Klasse implementiert die durch das Interface bereitgestellten Methoden getArtifactType(), read() und write(). Das von der Klasse ProxyPolicyProcessor verwaltete Artefakt wird über die Methode getArtifactType() bestimmt. Mit der Methode read() wird das Modell gelesen, mit der Methode write() geschrieben. Der Typ des Modells wird mit der Methode getModelType() bestimmt. Jedes Element, das ausgelesen wird, besitzt in der Klasse ProxyPolicy eine getund set-Methode. In Quellcode 4.3 ist ein Beispiel für die definitions.xmlDatei des Taschenrechner-Web-Service (vergleiche 2.2.3) zu sehen. Mit der Methode setConfigurationFileLocation() wird der Wert, der von dem Element 93 4.6. Integrationssubsystem Kapitel 4. Design configFileLocation eingeschlossen ist, gesetzt. Über die Methode getConfigurationFileLocation() kann der Wert zu einem späteren Zeitpunkt wieder zurückgegeben werden. Innerhalb der Klasse ProxyPolicy wird der Pfad, der sich zwischen dem Element configFileLocation befindet, an den Proxy übergeben, der über die Konfigurationskomponente die initiale Konfiguration des Proxys aus der Konfigurationsdatei ausliest (vergleiche 4.5.2.1). 1 <definitions xmlns="http://www.osoa.org/xmlns/sca/1.0" 2 targetNamespace="http://tuscany.apache.org/xmlns/sca/1.0" 3 xmlns:sca="http://www.osoa.org/xmlns/sca/1.0" 4 xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.0" xmlns:sample="http://sample"> 5 <policySet name="proxyPolicy" provides="tuscany:proxy" 6 appliesTo="sca:binding.ws" xmlns="http://www.osoa.org/xmlns/sca/1.0"> 7 <tuscany:proxy name="Calculator"> 8 <configFileLocation>/root/configuration/proxyconfig.xml</configFileLocation> 9 </tuscany:proxy> 10 </policySet> 11 </definitions> Quellcode 4.3: Beispiel: Auszug aus der Datei definitions.xml Die Klasse, die den generischen Typen StAXArtifactProcessor implementiert, muss in der Datei org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor festgelegt werden. Zusätzlich muss der XML-Namensraum der Policy-Erweiterung und die Klasse, die das Modell implementiert, genannt werden. ProxyPolicyInterceptor Die Klasse ProxyPolicyInterceptor implementiert das Interface Interceptor und repräsentiert den Interceptor, der in die Aufrufkette einer bestehenden SCA-Anwendung eingebunden wird (vergleiche 3.2.2). Abbildung 4.24 stellt das Klassendiagramm der Klasse ProxyPolicyInterceptor vor. Die Klasse implementiert die durch das Interface Interceptor definierten Methoden getNext(), setNext() und invoke(). Über die Methode getNext() wird der nächste Interceptor in der Aufrufkette bestimmt und mit setNext() der nächste Interceptor aufgerufen. In der Methode invoke() befindet sich die eigentliche Logik des Interceptors. Ein Web-Service-Aufruf entspricht einem Thread in Tuscany. Die Klasse ProxyPolicyInterceptor implementiert keinen Thread sondern ist Teil der Aufrufkette und damit des aufrufenden, aktiven Threads. Dies bedeutet, dass pro Web-Service-Aufruf nur 94 Kapitel 4. Design 4.7. Proxy-Subsystem Interceptor +getNext() : Invoker +setNext( next : Invoker ) ProxyPolicyInterceptor <<constructor>>+ProxyPolicyInterceptor( c : String, o : Operation, s : PolicySet ) +invoke( msg : Message ) : Message +getNext() : Invoker +setNext( n : Invoker ) : void Abbildung 4.24: Klassendiagramm: ProxyPolicyInterceptor ein Interceptor Objekt erzeugt wird, um das unter Umständen verschiedene Threads konkurrieren. Für das Queueing ist es wichtig, dass der Thread in seiner Ausführung unterbrochen werden kann, um ihn zu einem späteren Zeitpunkt wieder zu aktivieren. 4.7 Proxy-Subsystem Das Proxy-Subsystem ist die Hülle für die in den vorherigen Abschnitten vorgestellten Subsysteme. Zusätzlich definiert das Proxy-Subsystem die Integration des QoS-Proxys in eine SCA-Anwendung. Für das Hinzufügen der Funktionalität des QoS-Proxys zu einer SCA-Anwendung sind keine Anpassungen am bestehenden Quelltext der Anwendung notwendig. 4.7.1 Anpassung einer SCA-Anwendung Eine Anforderung an den QoS-Proxy ist das leichte Hinzufügen und Entfernen zu einer SCA-Anwendung. Der QoS-Proxy bietet verschiedene Dienstgüteklassen zu einem Service an. Über die Konfigurationsdatei des QoS-Proxys werden die unterschiedlichen Dienstgüteklassen definiert und die zugehörigen Werte der Dienstgüteeigenschaften Durchsatz beziehungsweise Antwortzeit festgelegt (vergleiche 4.5). Die Struktur einer SCA-Anwendung wird in einer composite-Datei festgelegt. Um den QoS-Proxy für einen Web Service einzubinden, muss die composite-Datei der zugehörigen SCA-Anwendung angepasst werden. Jede Dienstgüteklasse entspricht einer Web-Service-Schnittstelle. In Quellcode 4.4 ist ein Beispiel für eine angepasste composite-Datei aufgeführt. 95 4.7. Proxy-Subsystem Kapitel 4. Design Für jede Dienstgüteklasse muss ein Eintrag hinzugefügt werden. In Zeile 6 ist der Service CalculatorService definiert. Die Funktionalität des Service wird in Zeile 7 im interface.java-Element definiert. Der Zugriffsmechanismus ist ein Web Service, wie in Zeile 8 zu sehen ist. Für die Dienstgüteklasse „Gold“ wird ein weiteres service-Element in Zeile 11 definiert. Das neue Element verweist auf die gleiche Funktionalität, bindet aber mit dem Attribut requires den Proxy für den Web Service CalculatorServiceGold ein. 1 <composite xmlns="http://www.osoa.org/xmlns/sca/1.0" 2 targetNamespace="http://wwwvs.informatik.fh-wiesbaden.de/" 3 xmlns:sample="http://wwwvs.informatik.fh-wiesbaden.de" 4 xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.0" name="Calculator"> 5 6 <service name="CalculatorService" promote="CalculatorServiceComponent"> 7 <interface.java interface="calculator.CalculatorService" /> 8 <binding.ws/> 9 </service> 10 11 <service name="CalculatorServiceGold" promote="CalculatorServiceComponent" 12 requires="tuscany:proxy> 13 <interface.java interface="calculator.CalculatorService" /> 14 <binding.ws/> 15 </service> 16 ... 17 </composite> Quellcode 4.4: Beispiel: Angepasste composite-Datei einer SCA-Anwendung Zusätzlich muss eine Datei definitions.xml erstellt werden, in der ein intentund ein policySet-Element für den Wert proxy definiert wird (vergleiche 3.2.2). 4.7.2 Initialisierung der Subsysteme Repräsentiert wird das Proxy-Subystem durch die Klasse Proxy, in der die verschiedenen Subsysteme, ausgenommen das Integrationssubsytem, initialisiert werden. Abbildung 4.25 stellt das Klassendiagramm der Klasse vor. Die Methode getProxyInstance() gibt eine Instanz der Klasse zurück. Über die Methode queue() übergibt sich ein ProxyPolicyInterceptor-Thread an die Klasse Proxy. Um die Statistiken unterschiedlicher Subysteme zu sammeln, steht für das Queueing-Subsytem die Methode addQueueStatistic() und für das Integrations-Subsystem die Methode addPolicyStatistic() zur Verfügung. 96 Kapitel 4. Design 4.8. Zusammenfassung Proxy +getProxyInstance() : Proxy{guarded} +queue( thread : ProxyPolicyInterceptor, service : String, queueingClass : String, priority : int ) : void +addPolicyStatistic( stat : ProxyPolicyInterceptorStatistic ) : void +addQueueStatistic( stat : QueueStatistic ) : void +setActiveStrategy( index : int ) : boolean +getServiceLevelAgreementList() : ServiceLevelAgreementList +getActiveStrategy() : int +getStrategy() : ArrayList<Strategy> +setConfigurationPath( path : String ) : void Abbildung 4.25: Klassendiagramm: Proxy Um die aktive Queueing-Strategie zu wechseln, steht die Methode setActiveStrategy() zur Verfügung. Über den Aufruf der Methode getServiceLevelAgreementList() wird eine Liste mit den gültigen Service Level Agreements des Proxys zurückgegeben. Die aktive Queueing-Strategie wird mit der Methode getActiveStrategy() bestimmt. Über den Aufruf der Methode getStrategy() wird eine Liste der im Proxy registrierten Queueing-Strategien zurückgegeben. Nach dem Setzen des Pfades zur Konfigurationsdatei über die Methode setConfigurationPath() liest der Proxy die Konfigurationsdatei des Proxys ein. 4.8 Zusammenfassung Abbildung 4.26 stellt das vollständige Sequenzdiagramm des QoS-Proxys dar. Das Sequenzdiagramm ergänzt die Diagramme 4.10 und 4.22 um weitere Funktionsaufrufe und beschreibt damit den in 3.1 aufgeführten Anwendungsfall. Der Proxy erhält in einem ersten Schritt den Pfad zur Konfigurationsdatei mit dem Aufruf der Methode setConfigurationPath(). Um die Konfigurationsdatei einzulesen, erzeugt der Proxy ein Objekt vom Typ ConfigurationFileReader und liest die Konfigurationsdatei mit dem Aufruf der Methode readConfigurationFile() ein. Anhand der Konfigurationsdatei lässt sich bestimmen, ob die Service Level Agreements über RMI mit einem WSAG4J-System ermittelt werden können oder ob sie aus einer weiteren Datei ausgelesen werden müssen. Falls die Service Level Agreements über einen WSAG4J-System bestimmt werden, ruft der Proxy die Methode initialize() der Klasse Manager auf. Nachdem das AgreementManager-RMI-Objekt in der RMI Registry gefunden wurde, registriert der Manager seinen Callback. Alternativ liest der Manager über den Aufruf der Methode readSLAFile() die Service-LevelAgreement-Datei ein. 97 4.8. Zusammenfassung Kapitel 4. Design Der Manager erzeugt für jeden Service und jede in der Konfigurationsdatei definierte Dienstgüteklasse ein Agreement Template. Über die Methode createTemplates() werden die Agreement Templates erzeugt, mit createTemplate() werden die Agreement Templates am AgreementManager registriert. Wird ein Agreement basierend auf einem Agreement Template erzeugt, so ruft die Klasse AgreeementManager den zugehörigen Callback auf. Über die Methode notifyAgreement() erhält das Konfigurationssubsystem das neue Agreement. Das Agreement wird von der Klasse Callback an die ServiceLevelAgreementListKlasse mit dem Aufruf der add()-Methode übergeben. Stellt ein Client eine Anfrage an einen Web Service, der vom QoS-Proxy verwaltet wird, so erzeugt Tuscany einen neuen ProxPolicyInterceptor für die Anfrage. In einem ersten Schritt wird die Ankunftszeit des Web-Service-Aufrufs im ItemStatistic-Objekt des vom ProxyPolicyInterceptor erzeugten ItemObjektes mit der Methode setRequestTime() gespeichert. Über den Aufruf der Methode getProxyInstance() holt sich der ProxyPolicyInterceptor eine Referenz auf eine Instanz der Klasse Proxy, um in einem nächsten Schritt den aufrufenden Thread in ein Item-Objekt abzulegen und mit dem Aufruf der Methode queue() an den Proxy zu übergeben. Der Proxy Item übergibt über die Methode add() das Item-Objekt an die QueueingStrategie WeightedFairQueueing. Die Queueing-Strategie legt das Objekt in seine Queue WeightedFairQueueingItemList über die Methode add() ab. Das WeightedFairQueueingItemList reicht mit der Methode add() wiederum das Item-Objekt an seine interne Queue weiter. Über die Methode getThread() erhält die Queueuing-Strategie eine Referenz auf das Thread-Objekt. Der Thread wird über die Methode suspend() in den Zustand Wartend versetzt. Nach einer gewissen Zeit ruft die Queueing-Strategie in der run-Methode die schedule()-Methode auf. Für jede Queue in der Klasse WeightedFairQueueingItemList prüft die WeightedFairQueueing-Klasse, ob die entsprechende Queue Item-Objekte enthält. Falls die Queue Item-Objekte enthält und das Gewicht der Queue in der aktuellen Iteration noch nicht „aufgebraucht wurde“, versucht die Queueing-Strategie, einen Token aus dem LeakyBucket mit der Methode take() zu entnehmen. Falls ein Token verfügbar ist, wird das Item-Objekt aus der Queue mit der Methode remove() entfernt und mit getThread() die Referenz auf das gespeicherte Thread-Objekt zurückgegeben. Daraufhin kann die Queueing-Strategie auf das zugehörige ItemStatistic-Objekt mit der Methode getStatistic() zugreifen und 98 Kapitel 4. Design 4.8. Zusammenfassung die Verweilzeit in der Queue mit dem Aufruf der Methode setExposureTime() festhalten. Der Thread wird mit der Methode resume() in den Zustand Aktiv versetzt. Nachdem das ProxyPolicyInterceptor-Objekt wieder aktiv ist, kann es den Aufruf an den Web Service fortsetzen. Kurz vor dem Aufruf setzt das Objekt mit der Methode setResponseTimeOnRequest() und nach dem Eintreffen der Antwort mit der Methode setResponseTimeAfterRequest() die Zeitmarken, um die Antwortzeit des Web Services zu bestimmen. Abschließend übergibt das ProxyPolicyInterceptor-Objekt über die Methode addItemStatistic() das ItemStatistic-Objekt an den Proxy. Der Proxy übergibt das ItemStatistic-Objekt an die Klasse Statistic zur Auswertung. 99 Kapitel 4. Design 4.8. Zusammenfassung : ProxyPolicyInterceptor : Callback alt : Manager 3: initialize() 5: createTemplates() 6: createTemplate() 9: add() 10: readSlaFile() : ServiceLevelAgreementList 12: getStatistic() 32: setResponseTimeAfterRequest 30: setResponseTimeOnRequest() 29: getStatistic 17: add() 16: Item() 2: readConfigurationFile() : AgreementManager 4: register 1: setConfigurationPath() : Proxy [if rmiregistry is set] alt [if serviceclass list != null] [else] 7: notifyAgreement() 8: getServiceLevelAgreementList() [else] 15: queue() 14: getProxyInstance() 31: getNext() 33: addItemStatistic 11: add() : ConfigurationFileReader loop : Item 21: run() : AgreementFactory 19: add() 23: take() 25: remove() 27: setExposureTime() : WeightedFairQueueingItemList 24: remove() 22: schedule() 18: add() 13: setRequestTime() : WeightedFairQueueing 20: suspend() [for every queue in the weightedfairqueueingitemlist] loop 28: resume() 26: getStatistic() [for every item in the queue and weight is available for the queue] alt [if take was successful] [else] 34: addItemStatistic() : Queue : LeakyBucket Abbildung 4.26: Sequenzdiagramm: Berücksichtigung von QoS-Anforderungen an Web Services : ItemStatistic : Statistic 100 Kapitel 5 Implementierung Im folgenden Kapitel soll das Konzept eines QoS-Proxy für SOA-Dienste, wie es im Kapitel 4 entworfen wurde, umgesetzt werden. Im ersten Abschnitt werden die Entwicklungsumgebung und verwendeten Werkzeuge vorgestellt. Im Anschluss werden die Implementierungsdetails der zuvor entworfenen Subsysteme betrachtet. 5.1 Umgebung Der Proxy wurde in die Version 1.2.1 der Apache Tuscany SCA integriert. Als Application Server wurde Apache Tomcat in der Version 5.5.26 eingesetzt. Als Java Compiler und Java Runtime wurde das JDK von Sun in der Version 1.5.0_15 verwendet. Die QoSErweiterung für WSAG4J machte es erforderlich ein JDK in der Version 1.6 einzusetzen. Zum Einsatz kam das JDK in der Version 1.6.0_10, allerdings wurde der Code im Kompatibilitätsmodus übersetzt, so dass er auch unter einem JDK 1.5 lauffähig ist. Für WSAG4J wurde als Application Server Tomcat in der Version 6.0.18 verwendet. Zur Erstellung der Software-Komponenten wurde als Entwicklungsumgebung die Eclipse IDE in der Version 3.3.1 eingesetzt. 5.2 Namenskonventionen Alle erstellten Klassen im Proxy-Modul werden unterhalb des Packages org.apache.tuscany.sca.policy.proxy abgelegt. Interface-Namen beginnen mit einem I gefolgt von einem weiteren Großbuchstaben. Ausgenommen von dieser Konvention sind 101 5.3. Logging Kapitel 5. Implementierung die MBean-Interfaces, da der Klassenname ebenfalls IKlassennamen lauten müsste und zwischen den anderen Interfaces und Klasse nicht mehr unterschieden werden könnte. Klassennamen beginnen mit einem Großbuchstaben und alle Bezeichner mit einem Kleinbuchstaben. Klassen und Interfaces werden jeweils in eine eigene Datei abgelegt, ausgenommen davon sind innere, private Klassen. Weiterhin wurde Wert auf sogenannte „sprechende Bezeichner“ gelegt. Der jeweils erste Buchstaben bei zusammengesetzten Bezeichnern wird groß geschrieben, wie zum Beispiel objectInstance. 5.3 Logging Für den QoS-Proxy wurde das Apache-log4j-Projekt (log4j) [Gup05] verwendet. Das Verhalten des log4j-Systems kann durch eine Datei individuell gestaltet werden, was es einem Entwickler erlaubt, das Logging-Verhalten einer Software, ohne das Anpassen des Quellcodes, zu steuern. Mit Hilfe von log4j kann zwischen verschiedenen Schweregraden unterschieden werden. Die Schweregrade sind in einer Hierarchie angeordnet. Aus einer Anwendung heraus können diese Schweregrade ausgewählt werden, um ihnen LogNachrichten zuzuweisen. Man unterscheidet zwischen den Schweregraden TRACE, DEBUG, INFO, WARN, ERROR und FATAL. Konfiguriert wird die Ausgabe mit Hilfe einer Konfigurationsdatei. Dabei wird mit sogenannten Appendern festgelegt, wohin die Ausgabe der Log-Nachrichten erfolgt. Zur Auswahl stehen dabei die Standardausgabe, eine Datei oder beliebige andere Ziele. Für jeden Appender kann ein Layout festgelegt werden, welches definiert, wie die Daten strukturiert ausgegeben werden. In Quellcode 5.1 ist ein Beispiel für eine Konfigurationsdatei von log4j abgebildet. 1 2 3 4 5 log4j.rootLogger=DEBUG, ProxyAppender log4j.appender.ProxyAppender=org.apache.log4j.FileAppender log4j.appender.ProxyAppender.File=proxy.log log4j.appender.ProxyAppender.layout=org.apache.log4j.PatternLayout log4j.appender.ProxyAppender.layout.ConversionPattern=%d [%t] - %c - %m%n Quellcode 5.1: Beispiel: Konfigurationsdatei für log4j Die Konfigurationsdatei wird einmalig mit der Methode configure() der log4j-Klasse PropertyConfigurator initialisiert. Jede Klasse besitzt ein Attribut logger vom Typ Logger. Mit der Funktion getLogger() der Klasse Logger wird der Logger für die entsprechende Klasse zurückgegeben. Log-Nachrichten für einen bestimmten Schweregrad erfolgen mit dem Aufruf logger.SCHWEREGRAD(). 102 Kapitel 5. Implementierung 5.4 5.4.1 5.4. Queueing-Subsystem Queueing-Subsystem Überblick Das Queue-Subsystem stellt Implementierungen von Queueing-Strategien und die dazu benötigten Datenstrukturen bereit. Eine weitere Queueing-Strategie lässt sich über das Erben der abstrakten Klasse Strategy realisieren. Jede Queueing-Strategie benötigt eine Datenstruktur, die die Queues realisiert. Die Klasse ItemList stellt als abstrakte Klasse das Grundgerüst an Operationen zur Verfügung. Die Klasse Strategy erbt von der Klasse Thread und besitzt eine Methode run(), die periodisch aufgerufen wird. Jeder Algorithmus ist damit auch ein Thread. Mit Java 5 wurden die Concurrency Utilities1 in Java eingeführt. Die Concurrency Utilities sollen das Entwickeln von Anwendungen mit Nebenläufigkeit erleichtern. Jede Queueing-Strategie besitzt eine Binärsemaphore deren Wert erhöht wird, wenn ein ItemObjekt in eine Queue abgelegt wird und gesenkt wird, wenn kein Item-Objekt mehr in einer Queue vorhanden ist. Sind keine Item-Objekte mehr in der Queue und ist der Wert der Semaphore 0, so blockiert der Thread und wartet nicht aktiv darauf, dass ThreadObjekte eingefügt werden. • Item Innerhalb der Klasse wird ein Auftrag für eine Queueing-Strategie in Form eines Threads abgelegt. • ItemStatistic In der Klasse ItemStatistic werden Messwerte des aufrufenden Threads abgelegt und verschiedene Kenngrößen berechnet. • LeakyBucket Die Klasse LeakyBucket implementiert den Leaky-Bucket-Algorithmus und erzeugt in einer konstanten Rate Tokens. • Queue Die Klasse Queue ist eine Hilfsklasse für die Implementierung der Klasse ItemList. In eine Queue werden Item-Objekte abgelegt. • WeightedFairQueueingItemList Die Klasse WeightedFairQueueingItemList implementiert die Queue der Queueing-Strategie Weighted Fair Queueing. 1 Homepage der Java 5 Concurrency Utilities: http://java.sun.com/j2se/1.5.0/docs/guide/concurrency/ 103 5.4. Queueing-Subsystem Kapitel 5. Implementierung • WeightedFairQueueing In der Klasse WeightedFairQueueing wird die Queueing-Strategie Weighted Fair Queueing implementiert. 5.4.2 Beschreibung der Implementierung Item In der Klasse Item wird ein Auftrag für eine Queueing-Strategie abgelegt. Ein Auftrag entspricht einem Thread der pro Web-Service-Anfrage verwendet wird. Zusätzlich werden eine Reihe von weiteren Informationen in der Klasse abgelegt, die über get- und set-Methoden abrufbar bzw. setzbar sind. Die Klasse speichert den aufrufenden Thread in einem Attribut. Die Klasse realisiert zusätzlich die Methoden, die benötigt werden, um den Thread in den Zustand Wartend oder Aktiv zu versetzen. Innerhalb der suspend()-Methode wartet der Thread mit Hilfe des Aufrufes der wait()-Methode. Dabei wird über eine Zähler festgelegt, ob der Thread nach dem Ablauf des Timeouts des wait()-Aufrufes weiter warten muss oder weiterlaufen kann. In den Zustand Aktiv wird der Thread über den Aufruf der Methode resume() versetzt. Der Zustandswechsel wird dabei durch den Aufruf der Methode notify() durchgeführt. ItemStatistic Die Klasse ItemStatistic speichert Messwerte des aufrufenden Threads und berechnet daraus die in Abschnitt 3.4.2.1 vorgestellten Kenngrößen. Die Messwerte werden über einen einfachen Aufruf der jeweiligen Methode gesetzt, dabei wird mit der Methode System.nanoTime() eine Zeitmarke im entsprechenden Attribut gespeichert. LeakyBucket Der Leaky-Bucket-Algorithmus erzeugt in einer konstanten Rate Tokens. Der Konstruktor der Klasse hat als Parameter die Größe des Buckets, die initiale Anzahl der verfügbaren Tokens, die Rate in der Tokens erzeugt werden und die Anzahl der Tokens die erzeugt werden. Erzeugt werden die Tokens in einer inneren, privaten Klasse Producer. Die Klasse Producer implementiert einen Thread und erzeugt in einer konstanten Rate Tokens. 104 Kapitel 5. Implementierung 5.4. Queueing-Subsystem Abgelegt werden die erzeugten Tokens in einer LinkedBlockingQueue. Die Klasse LinkedBlockingQueue ist Bestandteil der Java Concurrency API. Werden mehr Tokens erzeugt als in der LinkedBlockingQueue Platz ist, so häufen sich die Tokens vor der LinkedBlockingQueue und warten bis wieder Platz in der LinkedBlockingQueue verfügbar ist. Die Queueing-Strategie entnimmt immer dann ein Token, wenn ein Item-Objekt aus einer Queue entfernt wird und bearbeitet werden soll. Mit der Methode take() entnimmt die Queueing-Strategie die Tokens. Sind keine Tokens mehr in der LinkedBlockingQueue vorhanden, so blockiert die Queueing-Strategie an der Datenstruktur, solange bis Tokens wieder verfügbar sind. Nach der Erzeugung der Tokens schläft der Thread der Klasse Producer für einen entsprechenden Zeitraum. Der Zeitraum entspricht der Erzeugungsrate. Der Algorithmus wird initial in der Klasse Proxy erzeugt. Alle im Proxy registrierten Queueing-Strategien erhalten eine Referenz auf das LeakyBucket-Objekt. Da alle Queueing-Strategien zum Zeitpunkt des Startes inaktiv sind bzw. über einen Semaphore sichergestellt ist, dass die Strategien an der Semaphore blockieren, kann es nicht zu Wechselwirkungen zwischen einzelnen Queueing-Strategien kommen. Queue Die Klasse Queue implementiert eine einfache Queue für die Klasse WeightedFairQueueingItemList. In der Klasse Queue werden die Item-Objekte einer Dienstgüteklasse abgelegt. Die Klasse WeightedFairQueueingItemList verwaltet bis zu n-Queue-Objekte in einer ArrayList. Jede Queue verfügt über ein Gewicht und eine Priorität. Die Klasse verfügt über verschiedene get- und set-Methoden. Innerhalb der Klasse Queue werden die Item-Objekte ebenfalls in einer ArrayList verwaltet. WeightedFairQueueingItemList Die Klasse WeightedFairQueueingItemList implementiert die Queue für die Klasse WeightedFairQueueing. Dabei erbt die Klasse von der abstrakten Klasse ItemList. Aufträge werden von der Klasse WeightedFairQueueing an die Klasse WeightedFairQueueingItemList über den Aufruf der Methode add() übergeben. Dabei werden die Aufträge in ein Objekt vom Typ Queue abgelegt. Die Klasse kann dabei n Queue-Objekte besitzen, die in einem ArrayList-Objekt verwaltet werden. Eingehende Aufträge werden von der Klasse anhand der Dienstgüteklasse klassifiziert und in die entsprechende Queue abgelegt. 105 5.4. Queueing-Subsystem Kapitel 5. Implementierung Die Queue prüft, ob bereits eine Queue mit der Dienstgüteklasse existiert. Falls ja, wird das Objekt in die Queue einsortiert. Falls nein, so wird geprüft, ob überhaupt eine weitere Queue mit einem Gewicht angelegt werden kann. Das kleinste Gewicht einer Queue ist 1. Ein Gewicht von 1 bedeutet, dass für jeden Aufruf genau ein Auftrag verarbeitet werden kann. Eine Verarbeitung von Bruchteilen ist nicht möglich. Die Methode size() liefert die Größe einer Queue, die Methode totalSize() gibt die Anzahl der Queues in der WeightedFairQueueingItemList zurück. Mit der Methode getIndexFromPriority() kann bestimmt werden, welche Queue in der Verwaltungsstruktur die entsprechende Priorität besitzt. Um das Gewicht einer Queue zu bestimmen, existiert die Methode getWeightFromQueue(). Mit der Methode contains() wird bestimmt, ob eine Queue mit der Priorität bereits existiert. Eine neue Queue wird mit der Methode createQueue() erzeugt. Alle öffentlichen Methoden der Klasse sind synchronized-Methoden, um einen Thread-sicheren Zugriff zu garantieren. WeightedFairQueueing Die Klasse WeightedFairQueueing realisiert den Weighted-Fair-Queueing-Algorithmus. Parameter des Konstruktors sind das maximale verfügbare Gewicht und eine Referenz auf das LeakyBucket-Objekt. Mit der Methode add() übergibt der Proxy ein Objekt vom Typ Item an die Implementierung des Algorithmus. In der add()-Methode wird das Item-Objekt an die Queue weitergereicht. Über den Aufruf der Methode suspend des Item-Objektes wird die im Objekt befindliche Referenz des Thread in den Zustand Wartend versetzt. In der schedule()-Methode ist der eigentliche WFQ-Algorithmus implementiert. Der Algorithmus durchläuft jede Queue der WeightedFairQueueingItemList-Klasse und entnimmt Item-Objekte. Die Anzahl der Objekte die entnommen wird, entspricht dem Gewicht der Queue. Mit der Methode inspectThroughput() wird in der Funktion geprüft, ob die SLOs für den jeweiligen Service noch einzuhalten sind. 106 Kapitel 5. Implementierung 5.5 5.5.1 5.5. Monitoring-Subsystem Monitoring-Subsystem Überblick Das Monitoring-Subsystem sammelt und erzeugt Statistiken der einzelnen Subsysteme und stellt sie über JMX Management-Anwendungen zur Verfügung. Bestandteile des Subsystems sind das Interface StatisticMBean und die Klasse Statistic. Die Klasse implementiert die durch das Interface StatisticMBean bereitgestellten Methoden. Aufgrund von Konflikten1 mit der aktuellen JDK-Version 1.6 nutzt das Apache-TuscanySCA-Projekt das JDK 1.5. Der Konflikt beruht auf der in Tuscany genutzten Version von JAXB oder StAX und den in JDK 1.6 ausgelieferten Versionen. Die JDK-Version 1.6 setzt die JMX-Spezifikation 1.4 um. Das JDK in der Version 1.5 setzt die JMX-Spezifikation 1.2 um. Da die Management-Komponente im Proxy und damit in Tuscany selbst integriert ist, werden die MBeans als OpenMBeans modelliert. Der Einsatz von OpenMBeans garantiert, dass jede JMX-Management-Anwendung benutzt werden kann. 5.5.2 Beschreibung der Implementierung Statistic Die Klasse Statistic implementiert die im Interface StatisticMBean definierten Methoden. Von besonderem Interesse sind die Statistiken die aus der Klasse ItemStatistic erzeugt werden. Mit der Methode getItemData() werden alle gesammelten ItemStatistic-Datensätze zurückgegeben. In einem relativ kurzen Zeitraum können, je nach Anzahl der Web-Service-Anfragen, sich entsprechend viele ItemStatistic-Objekte in der Klasse Statistic befinden. Über die Methode setInterval kann ein Interval gesetzt werden. Das Interval hat auf alle weitere Methoden, die Statistiken zu den Item-Objekten erzeugen, Einfluss. Mit resetInterval() wird das Interval zurückgesetzt. Das Interval wird durch zwei Marken realisiert, die in den jeweiligen Schleifen zur Erzeugung einen Start- und einen Endwert bilden. Mit der Methode setFilter() kann ein Filter gesetzt werden, der auf einen Web Service einschränkt. Das ist besonders hilfreich, wenn man nur die Statistiken zu einem ganz bestimmten Datensatz bilden möchten. Intern werden die Datensätze in HashMaps verwaltet. Der Filter entspricht dem Schlüssel in einer HashMap. Statt alle Werte aller 1 Hinweis auf der Apache Tuscany faq.html#TuscanySCAJava-FAQ-BuildA Homepage: 107 http://tuscany.apache.org/tuscany-sca-java- 5.6. WS-Agreement-Subsystem Kapitel 5. Implementierung Schlüssel zurückzugeben werden nur die Werte eines bestimmten Schlüssel zurückgegeben. Über die Methode resetFilter() wird der Filter zurückgesetzt. Um die Statistiken außerhalb einer Management-Anwendung auswerten zu können, steht eine Exportfunktion zur Verfügung. Mit der Methode setFileName wird ein Dateiname und ein Pfad für die Exportfunktion gesetzt. Die Methode exportItemDataToCVSFile() exportiert die ItemStatistic-Datensätze in eine CSV-Datei. Die Methode getSize() gibt die Anzahl der protokollierten ItemStatisticObjekte zurück. Das Betrachten von Abweichungen ist von besonderem Interesse. Mit der Methode min(), max() und getStandardDeviationData() wird das Minimum, Maximum und die Standardabweichung bestimmt. Die Standardabweichung in der Klasse Statistic entspricht dabei der diskreten Standardabweichung. Je höher die Werte sind, die vom Wert 0 abweichen, desto größer sind die Schwankungen in den Messwerten. Das arithmetische Mittel lässt sich mit der Methode getAverageData() bestimmen. Die Methode getServices() gibt die Services der gesammelten ItemStatistic-Objekte zurück. Mit der Methode getSuccessfulSLA() und getFailedSLA() wird der entsprechende Zähler zurückgegeben. 5.6 5.6.1 WS-Agreement-Subsystem Überblick Das WS-Agreement-Subsystem wird durch WSAG4J, einer WS-Agreement-Implementierung des Fraunhofer Instituts (vergleiche 2.1.3) implementiert. Das WSAG4J-Subsystem beschreibt die Klassen, die für die Kommunikation mit dem Konfigurationssubsystem auf Seiten des WSAG4J angepasst oder neu erstellt werden mussten. Zu den Klassen gehören: • AgreementManager Die Klasse AgreementManager implementiert das Interface IServiceLevelManagement und stellt Methoden zur Registrierung von Agreement Templates bereit. • TemplateManager In der Klasse TemplateManager werden Agreement Templates registriert und Agreement Offer auf ihre Gültigkeit hin überprüft. 108 Kapitel 5. Implementierung 5.6. WS-Agreement-Subsystem Die Funktionalität der Klasse AgreementManager wurde bewusst nicht in die Klasse TemplateManager integriert. Das vom WSAG4J-System erzeugte Objekt vom Typ AgreementManager wird in einer RMI-Registry abgelegt. Um das Objekt nutzen zu können, muss eine Java-Anwendung den gleichen package-Namensraum verwenden. Für das WSAG4J-System hätte das bedeutet, den ursprünglichen Namensraum von de.fh_wiesbaden.cs.vs.agreement auf org.apache.tuscany.sca.policy.proxy zu ändern, was alleine inhaltlich nicht korrekt wäre. Eine Änderung des Namensraums des QoS-Proxys war aus Integrationsgründen nicht möglich. 5.6.2 Beschreibung der Implementierung AgreementManager Die Klasse AgreementManager kann als eine Art Adapter-Klasse für die Klasse TemplateManager betrachtet werden. In einem ersten Schritt wird über die Methode register() ein Callback für den QoS-Proxy am Server registriert. Agreement Templates werden über die Methode createTemplate() registriert. Die Methode erzeugt dabei aus einem String-Array die XML-Repräsentierung eines Agreement Templates. Über die Methode report() kann der QoS-Proxy dem WSAG4J-System mitteilen, wenn ein Agreement nicht eingehalten werden konnte. TemplateManager Die Klasse TemplateManager ist die eigentliche Schnittstelle um Agreement Templates eines Services zu registrieren. Über den Aufruf der Methode registerTemplate() werden Agreement Templates im WSAG4J-System registriert. Alle Methoden sind, bis auf eine neue, erweiterte createTemplate()-Methode, bereits vorhanden. Die bestehenden Methoden werden um zusätzliche Funktionalität erweitert. Dabei wird geprüft, ob ein Agreement mit einem über den AgreementManager erzeugtem Agreement Template übereinstimmt oder darauf basiert. Trifft dies zu, wird die Methode notify() des zugehörigen Callback-Objekts aufgerufen. Wird ein neues Agreement erzeugt, so wird die Methode newAgreement() aufgerufen. Bei einer Übereinstimmung zu einem Agreement Template ruft die Klasse die Methode notifyAgreement() des zugehörigen Callback-Objekts auf. Wird 109 5.7. Konfigurationsubsystem Kapitel 5. Implementierung ein Agreement beendet, so wird die Methode agreementTerminated() aufgerufen. Im Falle einer Übereinstimmung ruft die Klasse die notifyTermination() des zugehörigen Callback-Objekts auf. Verwaltet werden die Callback-Objekte in einer HashMap, dabei entspricht das Template dem Schlüssel der HashMap und das Callback-Objekt dem Wert. 5.7 5.7.1 Konfigurationsubsystem Überblick Das Konfigurationssubsystem ist verantwortlich für die Konfiguration des QoS-Proxys zum Zeitpunkt des Startes und zur Laufzeit. Zum Konfigurationssubsystem zählen die folgenden Klassen: • Callback Die Klasse Callback ermöglicht es dem WS-Agreement-Subsystem den QoSProxy über das erfolgreiche Registrieren von Agreement Templates oder das Erzeugen von neuen Agreements zu informieren. • ServiceClass In der Klasse ServiceClass werden die Elemente througput und responseTime der Konfigurationsdatei zur Erzeugung von Agreement Templates gespeichert. • ConfigurationFile Die Klasse ConfigurationFile repräsentiert die Konfigurationsdatei des QoS-Proxys als Java-Objekt. • ServiceLevelAgreementFile Die Klasse ServiceLevelAgreementFile ist die Java-Objektrepräsentierung einer Service-Level-Agreement-Datei wie sie in Abschnitt 4.5.2 definiert wurde. • ServiceLevelAgreementList In der Klasse ServiceLevelAgreementList werden die ServiceLevelAgreement-Objekte des QoS-Proxys verwaltet. • ConfigurationFileReader Die Klasse ConfigurationFileReader liest die Konfigurationsdateien des QoS-Proxys ein. 110 Kapitel 5. Implementierung 5.7. Konfigurationsubsystem • Manager Die Klasse Manager implementiert das Interface ManagerMBean und stellt über JMX Operationen zur Verwaltung des QoS-Proxys zur Verfügung. 5.7.2 Beschreibung der Implementierung Callback Die Klasse Callback implementiert die im Interface ICallback definierten Methoden. Der Konstruktor der Klasse erhält als Parameter eine Referenz auf die Klasse Manager und kann somit Methoden dieser Klasse aufrufen. Ein Agreement erhält die Klasse über die Methode notifyAgreement(). Innerhalb der Methode wird die Methode getServiceLevelAgreementList() der Klasse Manager aufgerufen und eine Referenz auf das ServiceLevelAgreementList-Objekt der Klasse Manager zurückgegeben. Über die Methode add() der Klasse ServiceLevelAgreementList wird ein Agreement zur Liste hinzugefügt. Wird ein Agreement mit der Methode notifyTermination() beendet, so wird ein Flag im entsprechenden ServiceLevelAgreement-Objekt in der ServiceLevelAgreementList gesetzt. Über den Aufruf der Methode getServiceLevelAgreement() in der Klasse ServiceLevelAgreementList kann das entsprechende Agreement bestimmt werden. ServiceClass In der Klasse ServiceClass werden die Elemente throughput und responseTime aus der Konfigurationsdatei des QoS-Proxys gespeichert. Die Attribute der Elemente sind über get- und set-Methoden setzbar. Aus den verschiedenen ServiceClassObjekten erzeugt die Klasse Manager in einem späteren Schritt die Agreement Templates und registriert sie an einem WSAG4J-System. ConfigurationFile Die Klasse ConfigurationFile repräsentiert die Konfigurationsdatei des QoSProxys als Java-Objekt. Elemente der Konfigurationsdatei werden über get- und setMethoden bestimmt bzw. gesetzt. In einer Konfigurationsdatei können sich beliebig viele throughput- und responseTime-Elemente befinden. Verwaltet werden die Elemente in der Klasse in einer HashMap. 111 5.7. Konfigurationsubsystem Kapitel 5. Implementierung ServiceLevelAgreementFile Die Klasse ServiceLevelAgreementFile repräsentiert die alternative ServiceLevel-Agreement-Datei für den QoS-Proxy. Über verschiedene set-Methoden werden die Elemente der Datei in der Klasse gespeichert. Die Klasse erzeugt aus den gesammelten Agreements Objekte der Klasse ServiceLevelAgreement-Objekte. Die Methode toArray() gibt ein Array von ServiceLevelAgreement-Objekten zurück, welche aus den aus der Datei ausgelesenen Agreements erzeugt wurde. ServiceLevelAgreementList In der Klasse ServiceLevelAgreementList werden die ServiceLevelAgreement-Objekte des QoS-Proxys verwaltet. Die Klasse stellt drei verschiedene add()Methoden zur Verfügung. Über die erste add()-Methode können ServiceLevelAgreement-Objekte in Form eines Arrays übergeben werden. Die zweite Methode hat als Parameter ein String-Array und gibt der Callback-Klasse die Möglichkeit das Array, das bei einem notifyAgreement() erhalten wird, direkt an die Klasse weiterzugeben. Die letzte add()-Methode nimmt ein einzelnes SerivceLevelAgreementObjekt entgegen. Verwaltet werden die SerivceLevelAgreement-Objekt intern in einer ArrayList. ConfigurationFileReader Die Klasse ConfigurationFileReader ist verantwortlich für das Lesen der Konfigurationsdateien. Über den Aufruf der Methode readConfigurationFile() wird eine Konfigurationsdatei für den QoS-Proxy ausgelesen. Die Konfigurationsdatei enthält Angaben zur Erzeugung von Agreement Templates oder einen Pfad zu einer alternativen Datei mit Service Level Agreements, die über die Methode readSLAFile() ausgelesen wird. Beide Dateien liegen im XML-Format vor und werden über einen StAX XMLStreamReader ausgelesen. Die Methoden liefern eine Repräsentierung der Konfigurationsdatei als Java-Objekt und werden in der Klasse Proxy weiterverarbeitet. Manager Die Klasse Manager implementiert das Interface ManagerMBean. In der initializeMethode wird die RMI-Kommunikation initialisiert und ein Callback-Objekt regis- 112 Kapitel 5. Implementierung 5.8. Integrationssubsystem triert. Das Callback-Objekt erlaubt es einem WSAG4J-System, dem QoS-Proxy Statusmeldungen zu schicken und über neue Agreements zu informieren. Auf Grundlage der durch die Konfigurationsdatei erzeugten ServiceClass-Objekte erzeugt der Manager in der Methode createTemplates() verschiedene Templates und registriert sie mit dem Aufruf der Methode createTemplate() am WSAG4JSystem. 5.8 5.8.1 Integrationssubsystem Überblick Das Integrationssubsystem beschreibt die Implementierung der Hilfsklassen und verwandter Klassen die benötigt werden, um den QoS-Proxy in Tuscany zu integrieren. Zu den Klassen gehören: • ProxyPolicyInterceptor Die Klasse ProxyPolicyInterceptor implementiert den Interceptor der Policy der in eine Aufrufkette einer SCA-Anwendung integriert wird. • ProxyPolicyProcessor Über die Klasse ProxyPolicyProcessor wird die definitions.xmlDatei einer SCA-Anwendung eingelesen. • ProxyPolicyProvider Die Klasse ProxyPolicyProvider erzeugt die entsprechenden Provider für das entsprechende SCA-Element. • ProxyPolicyDefinitionsProvider Mit der Klasse ProxyPolicyDefinitionsProvider wird die definitions.xml-Datei der Policy eingelesen. 5.8.2 Beschreibung der Implementierung ProxyPolicyInterceptor Der ProxyPolicyInterceptor ist der Interceptor, der in die Aufrufkette einer bestehenden SCA-Anwendung eingekettet wird. Pro Operation wird der ProxyPolicyInterceptor genau einmal erzeugt. Dies bedeutet, dass bei einem Aufruf der Operation 113 5.8. Integrationssubsystem Kapitel 5. Implementierung von verschiedenen Quellen verschiedene Threads um das Objekt konkurrieren. Der Konstruktor der Klasse erhält als Parameter die Operation, das policySet, welches aus der Datei definitions.xml ausgelesen wurde und einen Kontext. Die eigentliche Funktionalität des Interceptors befindet sich in der Methode invoke(). In einem ersten Schritt wird ein neues Item-Objekt erzeugt. Das Item-Objekt initialisiert sein ItemStatistic-Attribut. Mit dem Aufruf der Methode getStatistic() aus dem neu erzeugten Item-Objekt wird das ItemStatistic-Objekt zurückgegeben. Der Interceptor kann dann die erste Zeitmarke, die Ankunftszeit im System, setzen. Über die Methode getServiceInformationFromURI() wird die Dienstgüteklasse aus der aufrufenden URL bestimmt und im Item-Objekt mit dem Aufruf der Methode setQueueingClass() gesetzt. Der Interceptor übergibt das Item-Objekt mit der Methode queue() an die Klasse Proxy. Der Interceptor implementiert weiterhin die Methoden getNext() und setNext(). Mit der Methode getNext() wird der nächste Interceptor in der Aufrufkette bestimmt. Über die Methode setNext() wird die Nachricht an den nächsten Interceptor in der Aufrufkette weitergegeben und der auf dem ProxyPolicyInterceptor folgende Interceptor wird aktiv. ProxyPolicyProcessor Die Klasse ProxyPolicyProcessor implementiert einen StAXArtifactProcessor für die Klasse PolicyProcessor. Der StAXArtifactProcessor kapselt einen StAX XMLStreamReader und stellt als Interface die Methoden read(), write() und getArtifactType() bereit. Die Methode read() der Klasse ProxyPolicyProcessor liest die Datei definitions.xml ein und speichert die eingelesenen Elemente in einem PolicyProcessor-Objekt. In der Klasse PolicyProcessor wird das XML-Schema definiert. Dies bedeutet, dass jedes Attribut, das eingelesen wird, in der Klasse als Datentyp abgebildet ist. 1 org.apache.tuscany.sca.policy.proxy.ProxyPolicyProcessor; 2 qname=http://tuscany.apache.org/xmlns/sca/1.0#proxy, 3 model=org.apache.tuscany.sca.policy.proxy.ProxyPolicy Quellcode 5.2: Konfiguration: StAXArtifactProcessor-Datei Die Klasse ProxyPolicyProcessor muss zusätzlich in der Datei org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor im Ver- 114 Kapitel 5. Implementierung 5.8. Integrationssubsystem zeichnis src/main/resources/META-INF/services/ mit dem Eintrag in Quellcode 5.2 beschrieben werden. ProxyPolicyProvider Jedes Element, auf das eine Policy angewendet werden soll, muss einen ProxyPolicyProvider zur Verfügung stellen. In der aktuellen SCA-Spezifikation ist es nur möglich, Policies auf service-, reference- oder implementation-Elemente anzuwenden. Alle ProxyPolicyProvider implementieren die durch das Interface PolicyProvider bereitgestellten Methoden createInterceptor() und getPhase(). Die Klasse ProxyPolicyProviderFactory implementiert das Interface PolicyProviderFactory. Das Interface PolicyProviderFactory ist ein parameterisiertes Interface, welches als Parameter eine Klasse, die das Interface Policy erweitert, besitzt. Die Klasse ProxyPolicyProviderFactory implementiert daher das Interface PolicyProviderFactory<ProxyPolicy>. Zu dem Interface gehören Methoden zur Erzeugung von ProxyPolicyProvidern für die Elemente implementation, service und reference. Die Methoden createImplementationPolicyProvider, createServicePolicyProvider() und createReferencePolicyProvider() rufen den Konstruktur der Klassen ProxyImplementationPolicyProvider, ProxyServicePolicyProvider und ProxyReferencePolicyProvider auf. Gemeinsame Argumente der Konstruktoren ist die Laufzeitrepräsentierung der component der Anwendung. Der Konstruktor der Klasse ProxyImplementationPolicyProvider hat als weiteres Argument die Laufzeitrepräsentierung der zugehörigen implementation. Die Klasse ProxyServicePolicyProvider und ProxyReferencePolicyProvider haben als Argumente die Laufzeitrepräsentierung des zugehörigen service bzw. reference und der des bindings. Die Klasse ProxyPolicyProvider muss zusätzlich in der Datei org.apache.tuscany.sca.provider.PolicyProviderFactory im Verzeichnis src/main/resources/META-INF/services/ mit dem folgenden Eintrag (Quellcode 5.3) beschrieben werden. 1 org.apache.tuscany.sca.policy.proxy.ProxyPolicyProviderFactory; 2 model=org.apache.tuscany.sca.policy.proxy.ProxyPolicy Quellcode 5.3: Konfiguration: ProxyPolicyProviderFactory-Datei 115 5.9. Proxy-Subsystem Kapitel 5. Implementierung ProxyPolicyDefinitionsProvider Die Klasse ProxyPolicyDefinitionsProvider ist verantwortlich für das Einlesen der Policy-eigenen Datei definitions.xml. Der Pfad zur Datei wird als relativer Pfad in einem Attribut gesetzt. Quellcode 5.4 zeigt den Aufbau der Datei. Die Datei befindet sich im Verzeichnis src/main/resources/org/apache/tuscany/sca/policy/proxy/. 1 <definitions xmlns="http://www.osoa.org/xmlns/sca/1.0" 2 targetNamespace="http://tuscany.apache.org/xmlns/sca/1.0" 3 xmlns:sca="http://www.osoa.org/xmlns/sca/1.0" 4 xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.0"> 5 <!-- Policy Intents Defined by the SCA Runtime --> 6 <intent name="proxy" constrains="sca:binding.ws"> 7 <description> 8 All messages to and from this implementation must be proxied 9 </description> 10 </intent> 11 </definitions> Quellcode 5.4: definitions.xml-Datei des QoS-Proxys Über das Attribut constrains in Zeile 6 wird die Policy auf ein SCA-Element eingeschränkt. In Zeile 8 findet sich eine allgemeine Beschreibung des QoS-Proxys. Über den Konstruktor wird der Wert eines weiteren Attributes vom Typ URLArtifactProcessor bestimmt. Der URLArtifactProcessor ermöglicht es, Model-Daten aus einer URL, wie beispielsweise einem Dateipfad, auszulesen und zu verarbeiten. Die Klasse ProxyPolicyDefinitionsProvider muss zusätzlich in der Datei org.apache.tuscany.sca.definitions.SCADefinitionsProvider im Verzeichnis src/main/resources/META-INF/services/ mit dem folgenden Eintrag (Quellcode 5.5) beschrieben werden. 1 org.apache.tuscany.sca.policy.proxy.ProxyPolicyDefinitionsProvider Quellcode 5.5: Konfiguration: SCADefinitionsProvider-Datei 5.9 Proxy-Subsystem Die Klasse Proxy ist die zentrale Komponente in der Architektur des QoS-Proxys. In der Klasse werden alle relevanten Klassen instanziiert. Der Proxy wird als Singleton [GHJ95] 116 Kapitel 5. Implementierung 5.9. Proxy-Subsystem implementiert. Dies bedeutet, dass der Konstruktor der Klasse private ist. Im Konstruktur des Proxys werden das Statistic- und Manager-Objekte für den MBean Server erzeugt und registriert. Der ProxyPolicyProcessor liest die Datei definitions.xml einer SCAAnwendung ein und wandelt die Informationen aus der Datei in ein Modell der Policy um. Die Klasse ProxyPolicy entspricht dem Modell der Policy. Der Proxy erhält den Pfad zur Konfigurationsdatei über die Klasse ProxyPolicy, sobald der Pfad über den ProxyPolicyProcessor gesetzt wird, wird das Proxy-Objekt zum ersten Mal aufgerufen. Über den Aufruf der Methode setConfigurationPath() wird die Konfigurationsdatei des Proxys ausgelesen. Der Proxy erzeugt ein Objekt vom Typ ConfigurationFileReader und ruft die Methode readConfigurationFile() auf, die ein Objekt vom Typ Configuration zurückgibt, die die aus der Konfigurationsdatei ausgelesenen Werte speichert. In einem nächsten Schritt erzeugt der Proxy die Queues mit der Methode initializeQueues(). Der Proxy erzeugt von jeder verfügbaren Queueing-Strategie ein Objekt und legt es in einer Verwaltungsstruktur ab. Da jede Queueing-Strategie über ein Semaphor verfügt, die mit 0 initialisiert wird, blockiert jede Strategie und wartet nicht aktiv auf Aufträge, die in der Queue abgelegt werden. Mit der Methode setActiveStrategy() kann von der aktive Queueing-Strategie auf eine neue Strategie gewechselt werden. Über die Methode queue() übergibt die Klasse ProxyPolicyInterceptor ein Item-Objekt an den Proxy. Im Proxy-Objekt wird die Priorität der Dienstgüteklasse bestimmt und im Item-Objekt abgelegt. Die Queueing-Strategie versetzt den Thread in den Zustand Wartend. Die Klasse Item stellt dazu die Methode suspend() zur Verfügung. Nach einer entsprechenden Zeit wird der Thread von der Queueing-Strategie bearbeitet und über die Methode resume() in den Zustand Aktiv versetzt. Die Queueing-Strategie setzt einen Messwert im ItemStatistic-Objekt des Items um die Verweilzeit in der Queue festzuhalten. Verschiedene Statistiken werden über den Proxy an das Monitoring-Subsytem weitergereicht. Die Methoden addItemStatistic() und addQueueStatistic übergeben ItemStatistic- und QueueStatistic-Objekte an das Monitoring-Subsystem. Innerhalb der addItemStatistic()-Methode prüft der Proxy, ob für den Service eine maximale Antwortzeit festgelegt wurde. Falls eine Antwortzeit festgelegt wurde, prüft der Proxy, ob die Anforderungen eingehalten wurde. Wurde die Anforderungen verletzt, so informiert der Proxy den Manager. 117 5.10. Implementierungsaufwand 5.10 Kapitel 5. Implementierung Implementierungsaufwand In Tabelle 5.1 ist der Implementierungsaufwand aufgeschlüsselt nach Komponenten dargestellt. 5.11 Zusammenfassung Der Anwendungsfall 3.1 beschreibt das Berücksichtigen von QoS-Anforderungen an Web Services. In Kapitel 4 wurde der Anwendungsfall unter Berücksichtigung der vorgestellten Subsystemen in einem Sequenzdiagramm beschrieben. Die Funktionalität des QoSProxys soll anhand der log4j-Ausgabe der Implementierung unter Berücksichtigung des Anwendungsfalldiagramms verdeutlicht werden. Für den QoS-Proxy wurde auf Basis des in Abschnitt 2.1.4 vorgestellten TaschenrechnerWeb-Service mit Axis2 ein Client erzeugt. Der Übersichtlichkeit wegen wurde die log4jAusgabe unterteilt. Der Quellcode 5.6 beginnt mit Informationen zu den Konfigurationsdateien. In Zeile 2 wird der Ort und Name der Konfigurationsdatei ausgegeben und in Zeilte 4 der der log4j-Konfigurationsdatei. In einem nächsten Schritt initialisiert die Klasse Proxy den Leaky-Bucket-Algorithmus (Zeile 5 bis 7) und die Queues der QueueingStrategie (Zeile 8 bis 16). Zeile 18 zeigt den Ort und Namen der SLA-Konfigurationsdatei. In der SLA-Konfigurationsdatei befinden sich Agreements, die die Rahmenbedingungen für die QueueingStrategie definieren. Alternativ hätte die Konfigurationsdatei auch Agreement Templates beinhalten können, die das Konfigurationssubsystem des QoS-Proxys über RMI an einem WSAG4J-System registriert hätte. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 2008-12-06 18:01:53,929 [main] - Proxy - Configuration File Location: /users/m_frey/Projekte/Diplom/trunk/src/Proxy/configuration.xml 2008-12-06 18:01:53,929 [main] - Proxy - Logging Configuration File Location: /users/m_frey/Projekte/Diplom/trunk/src/Proxy/log4j.txt 2008-12-01 18:01:53,932 [main] - LeakyBucket - Start the Producer Thread 2008-12-01 18:01:53,961 [Leaky Bucket] - LeakyBucket - Rate is 1000 Number is 2 Size is 10 2008-12-01 18:01:53,966 [main] - WeightedFairQueueingItemList - Set the divider to 2 2008-12-01 18:01:53,966 [main] - WeightedFairQueueingItemList - Set the maximum weight to 8 2008-12-01 18:01:53,967 [main] - WeightedFairQueueingItemList - Creating queue with a service class Gold, priority 0 and weight 4 2008-12-01 18:01:53,967 [main] - WeightedFairQueueingItemList - Creating queue with a service class Silver, priority 1 and weight 2 2008-12-01 18:01:53,967 [main] - WeightedFairQueueingItemList - Creating queue with a 118 Kapitel 5. Implementierung Datei Queueing Item.java ItemList.java ItemStatistic.java LeakyBucket.java Queue.java QueueStatistic.java Strategy.java WeightedFairQueueing.java WeightedFairQueueingItemList.java Monitoring Statistic.java StatisticMBean.java WS-Agreement AgreementManager.java TemplateManager.java Konfiguration Callback.java ConfigurationFile.java ConfigurationFileReader.java ICallback.java IServiceLevelManagement.java Manager.java ManagerMBean.java ServiceClass.java ServiceLevelAgreement.java ServiceLevelAgreementFile.java ServiceLevelAgreementList.java Integration ProxyImplementationPolicyProvider.java ProxyPolicy.java ProxyPolicyDefinitionsProvider.java ProxyPolicyInterceptor.java ProxyPolicyProcessor.java ProxyPolicyProviderFactory.java ProxyReferencePolicyProvider.java ProxyServicePolicyProvider.java Proxy Proxy.java Summe 5.11. Zusammenfassung Leerzeilen Kommentare Code Summe 18 3 22 18 11 15 11 18 19 106 47 98 153 73 50 65 113 121 75 8 72 128 34 54 25 132 102 139 58 192 299 118 119 101 263 242 76 21 258 120 352 23 686 164 22 0 127 10 129 16 278 26 8 26 11 3 3 26 12 21 20 10 15 65 167 99 38 41 189 79 144 145 43 78 23 115 139 8 8 168 15 69 79 47 62 96 308 249 49 52 383 106 234 244 100 155 11 22 7 13 23 9 10 9 27 30 34 91 68 34 27 27 52 53 27 67 94 32 52 50 90 105 68 171 185 75 89 86 24 537 227 2994 239 2549 490 6080 Tabelle 5.1: Implementierungsaufwand sortiert nach Subsystemen 119 5.11. Zusammenfassung 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 Kapitel 5. Implementierung service class Bronze, priority 2 and weight 1 2008-12-01 18:01:54,008 [main] - Proxy - Available Strategies: 0. Weighted Fair Queueing 2008-12-01 18:01:54,009 [main] - Proxy - SLA File Location: /users/m_frey/Projekte/Diplom/trunk/src/Proxy/log4j.txt 2008-12-01 18:01:54,033 [main] - ServiceLevelAgreementFile - Create agreement CalculatorBronzeService for a CalculatorServiceBronze 2008-12-01 18:01:54,033 [main] - ServiceLevelAgreementFile - The proxy received a agreement for a CalculatorServiceBronze. The name of the agreement is: CalculatorBronzeService 2008-12-01 18:01:54,035 [main] - ServiceLevelAgreementFile - Agreement: CalculatorBronzeService. Set response time to max: 400.0. The unit is: ms 2008-12-01 18:01:54,035 [main] - ServiceLevelAgreementFile - Agreement: CalculatorBronzeService. Set throughput to min: 1.0 and max: 20.0. The unit is: rps 2008-12-01 18:01:54,035 [main] - ServiceLevelAgreementFile - Create agreement CalculatorGoldService for a CalculatorServiceGold 2008-12-01 18:01:54,035 [main] - ServiceLevelAgreementFile - The proxy received a agreement for a CalculatorServiceGold. The name of the agreement is: CalculatorGoldService 2008-12-01 18:01:54,035 [main] - ServiceLevelAgreementFile - Agreement: CalculatorGoldService. Set response time to max: 300.0. The unit is: ms 2008-12-01 18:01:54,035 [main] - ServiceLevelAgreementFile - Agreement: CalculatorGoldService. Set throughput to min: 1.0 and max: 50.0. The unit is: rps 2008-12-01 18:01:54,036 [main] - Proxy - Adding SLA to list was successful Quellcode 5.6: Logging: Initialisierung des QoS-Proxys Um die Funktionalität des Queueings zu zeigen, wird ein Client der die Dienstgüteklasse Bronze und ein Client der die Dienstgüteklasse Gold nutzt gestartet. Beide Clients erzeugen jeweils 5 Threads die 15 Web-Service-Anfragen stellen. In Quellcode 5.7 ist zu sehen, dass eine Web-Service-Anfrage eintrifft (Zeile 1 und 2) und dass es sich dabei um einen Bronze-Client handelt (Zeile 3 und 4). Die Anfrage wird direkt aus der Bronze-Queue von der Queueing-Strategie entnommen. Die Anzahl der wartenden Aufträge ist Null (Zeile 10 bis 12). 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 2008-12-01 18:05:57,073 [http-172.25.48.142-8080-Processor24] - Proxy -Add thread item to the list 2008-12-01 18:05:57,073 [http-172.25.48.142-8080-Processor24] - Item - Try to suspend thread with id 49 and service class Bronze 2008-12-01 18:05:57,073 [Weighted Fair Queueing] - LeakyBucket - Number of tokens available: 10 2008-12-01 18:05:57,073 [http-172.25.48.142-8080-Processor23] - Proxy - Add thread item to the list 2008-12-01 18:05:57,073 [Weighted Fair Queueing] - WeightedFairQueueingItemList Items in Queue 0 : 0 Items in Queue 1 : 0 Items in Queue 2 : 0 2008-12-01 18:05:57,073 [Weighted Fair Queueing] - WeightedFairQueueing - Schedule thread with service class Bronze. 2008-12-01 18:05:57,073 [Weighted Fair Queueing] - WeightedFairQueueing - Weight (Total): 1 (Used): 1 120 Kapitel 5. Implementierung 5.11. Zusammenfassung Quellcode 5.7: Logging: Bearbeiten einer Web-Service-Anfragen Nach einer gewissen Zeit sind die Tokens verbraucht und die Queueing-Strategie muss solange warten bis wieder Tokens verfügar sind. In Quellcode 5.8 ist erkennbar, dass zur Zeit 4 Gold-Anfragen (Queue 0) und vier Bronze-Anfragen (Queue 3) auf Bearbeitung warten. Die fünfte Gold-Anfrage wird gerade bearbeitet (Zeile 11). In Zeile 6 ist zu sehen, dass nur noch ein Token verfügbar ist, der allerdings von der gerade bearbeiteten GoldAnfrage verwendet wurde. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 2008-12-01 18:05:59,075 [Weighted Fair Queueing] - Item - Try to resume thread with id 36 and service class Bronze 2008-12-01 18:05:59,075 [Weighted Fair Queueing] - Item - Resume thread with id 36 and service class Bronze 2008-12-01 18:05:59,075 [Weighted Fair Queueing] - LeakyBucket - Number of tokens available: 1 2008-12-01 18:05:59,075 [Weighted Fair Queueing] - WeightedFairQueueingItemList Items in Queue 0 : 4 Items in Queue 1 : 0 Items in Queue 2 : 4 2008-12-01 18:05:59,075 [Weighted Fair Queueing] - WeightedFairQueueing - Schedule thread with service class Gold. 2008-12-01 18:05:59,075 [Weighted Fair Queueing] - WeightedFairQueueing - Weight (Total): 4 (Used): 1 2008-12-01 18:05:59,075 [Weighted Fair Queueing] - ItemStatistic - Calculates the exposure time to 1.228583159075905E12 - 1.228583158113223E12 = 962.68212890625 2008-12-01 18:05:59,076 [Weighted Fair Queueing] - Item - Try to resume thread with id 33 and service class Gold 2008-12-01 18:05:59,076 [Weighted Fair Queueing] - Item - Resume thread with id 33 and service class Gold 2008-12-01 18:05:59,076 [Weighted Fair Queueing] - LeakyBucket - Number of tokens available: 0 Quellcode 5.8: Logging: Wartende Web-Service-Anfragen Das Gewicht von Queue 0 garantiert dem Gold-Client, dass mindestens 4 Gold-Anfragen bearbeitet werden. Die Queue für Bronze-Anfrage hat nur ein Gewicht von 1, was bedeutet, dass bei vielen Gold- und Silber-Anfragen höchstens nur 1 Bronze-Auftrag bearbeitet wird. Für die Bearbeitung durch den QoS-Proxy benötigt ein Bronze-Client mit 5 Threads mit je 25 Anfragen 1 Minute und 16 Sekunden, ein Gold-Client 59 Sekunden. 121 5.11. Zusammenfassung Kapitel 5. Implementierung 122 Kapitel 6 Bewertung Das vorliegende Kapitel soll eine Bewertung des implementierten QoS-Proxy für SOADienste durchführen. Dabei gliedert sich das Kapitel in einer architekturelle Bewertung und eine Bewertung der Leistungsfähigkeit des QoS-Proxys. Innerhalb der Leistungsbewertung wird in einem ersten Schritt das zugrunde liegende Messmodell vorgestellt, das die Art und Weise des Messaufbaus in Zusammenspiel mit der gegebenen Hardware beschreibt. Anschließend werden die Messungen durchgeführt und die Ergebnisse interpretiert. 6.1 Bewertung der Architektur Der QoS-Proxy implementiert den Weighted-Fair-Queueing- und Leaky-Bucket-Algorithmus. Das Ziel weitere Queueing-Strategien zu implementieren konnte aus Zeitgründen nicht umgesetzt werden. Innerhalb der Aufrufkette von Tuscany ist es in der verwendeten Version 1.2.1 nicht möglich den Client einer Web-Service-Anfrage zu ermitteln. Informationen zum Client werden vor der Aufrufkette aus der Nachricht entfernt. Aus diesem Grund kann ein SLA nicht eindeutig einem Client zugewiesen werden. Problematisch wird das insbesondere, wenn man eine Art Abrechnungsmodell für die vom QoS-Proxy bereitgestellten Dienste zur Verfügung stellen möchte. Demnach ist es nur möglich nach Dienst und nicht nach Client abzurechnen. Für zukünftige Versionen von Tuscany ist es angedacht, Informationen zum Client, wie beispielsweise die IP, in der Nachricht zu belassen. Alternativ wäre es vorstellbar eine weitere Policy neben dem QoS-Proxy für eine SCA-Anwendung einzubinden. In der Entwicklerversion von Tuscany gibt es eine Policy, die eine Authentifizierung auf 123 6.2. Bewertung der Leistungsfähigkeit Kapitel 6. Bewertung Basis von Tokens ermöglicht. Der Token wird dabei in den SOAP Header der Nachricht eingebunden. Der Inhalt des Tokens ist frei wählbar und so wäre es denkbar, Informationen zum Client im Token zu hinterlegen. Zur Zeit ist die QoS-Proxy-Policy nur auf das implementation.java-Elemente anwendbar und verletzt damit den generischen Aspektes des QoS-Proxys. Damit schränkt der QoS-Proxy auf SCA-Anwendungen ein die in Java implementiert wurden. Zusätzlich ist es nicht möglich, den QoS-Proxy auf service-Elemente anzuwenden, deren Implementierung nicht lokal ist. Einschränkungen für eine Policy werden in Tuscany über die Policy-eigene Datei definitions.xml gesetzt. Um den QoS-Proxy auf das binding.ws-Element einzuschränken, hätte es ausreichen müssen, in der Datei im intent-Element das Attribut constrain auf den Wert sca:binding.ws statt sca:implementation.java zu setzen. In einer SCA-Anwendung hätte in der definitions.xml der Anwendung das constrain-Attribut statt auf sca:implemenation das Attribut auf sca:service/sca:binding.ws gesetzt werden müssen. Verschiedene Tests haben leider zu keinem verwendbaren Ergebnis geführt. 6.2 6.2.1 Bewertung der Leistungsfähigkeit Versuchsaufbau Alle Messungen wurden auf einem Intel Core 2 Duo mit 1,86 Ghz und 2 GB RAM durchgeführt. Als Betriebssystem wurde Ubuntu/Linux mit einem Kernel in der Version 2.6.24 verwendet. Als Java Runtime diente, wie schon bei der Implementierung, das JDK von SUN in der Version 1.5.0_15. Zusätzlich wurde Grinder [AF08], ein ein Java-basiertes Lasttest-Framework, für die Messungen verwendet. Abbildung 6.1 zeigt die drei prinzipiellen Versuchsaufbauten, die dazu dienen den QoSProxy zu bewerten. Im Versuchsaufbau 1 werden die Messungen ohne den QoSProxy durchgeführt. Die Messungen dienen als Referenz für die Beurteilung des Overheads durch den QoS-Proxy. Im zweiten Versuchsaufbau (Versuchsaufbau 2) wird der QoS-Proxy zum Web Service hinzugefügt, allerdings werden Web-Service-Anfragen nicht in Queues einsortiert. Der Versuch dient als Referenz für das Ermitteln des Aufwandes der entsteht wenn eine Web-Service-Anfrage in eine Queue einsortiert wird. Versuchsaufbau 3 erweitert den vorherigen Versuchsaufbau um das Queueing von Web-Service-Anfragen. 124 Kapitel 6. Bewertung 6.2. Bewertung der Leistungsfähigkeit Versuchsaufbau 1 Client Web Service Requests Versuchsaufbau 2 Client Requests QoS-Proxy Web Service Requests QoS-Proxy Web Service Versuchsaufbau 3 Client Abbildung 6.1: Aufbau der Versuche für die Leistungsbewertung Für alle Versuche wird mit Grinder eine Web-Service-Anfrage an einen Web Service aufgezeichnet. Dabei wird der bereits in der Implementierung in 5.11 benutzte Client verwendet. Als Web Service wird der in 2.1.4 vorgestellte Taschenrechner-Web-Service eingesetzt. Die Aufzeichnung zwischen einem Client und dem Web Service erfolgt über den TCPProxy des Grinders. Der TCPProxy zeichnet dabei die Web-Service-Anfrage auf und generiert aus der Anfrage ein Python-Testskript. Das erzeugte Testskript ist Grundlage für Messung. Die Web-Service-Anfrage ruft über den Taschenrechner-WebService den Add-Service auf und addiert zwei Zahlenwerte. Der Web-Service erhält zwei java.lang.double-Parameter und liefert ein Ergebnis als java.lang.double zurück. Alle beteiligten Komponenten werden ohne Optimierungen eingesetzt. Um die Ergebnisse nicht durch zusätzlichen I/O Overhead zu verfälschen wird das Log Level von Tomcat und Tuscany auf WARNING beziehungsweise ERROR gesetzt. Mit den aufgeführten Versuchsaufbauten werden insgesamt fünf Messreihen durchgeführt. In jeder Messreihe ruft der Grinder fünftausendmal einen Web Service auf. 6.2.2 Auswertung der Messungen Versuch 1 wurde ohne den QoS-Proxy durchgeführt und zeigt auch bei mehreren Messreihen relativ ähnliche Ergebnisse. Für den nächsten Versuch wurde der QoS-Proxy in die Anwendung eingebunden, allerdings wurde in der Konfigurationsdatei des QoS-Proxys 125 6.2. Bewertung der Leistungsfähigkeit Kapitel 6. Bewertung keine Dienstgüteklassen hinterlegt. Der QoS-Proxy prüft vor dem Einfügen in eine Queue, ob eine Dienstgüteklasse für den aufgerufenen Web-Service existiert. Der Versuch 1 erweitert Versuch 2 um einen weiteren Interceptor in der Aufrufkette der Anwendung, einer Prüfung der aufrufenden URL des Web Services sowie die Initialisierung der Subsysteme des QoS-Proxys. Die Auswirkungen auf das Antwortzeitverhalten sind zwischen Versuch 1 und 2 geringfügig. In Versuch 3 wurden für den QoS-Proxy in der Konfigurationsdatei Dienstgüteklassen hinterlegt, so dass der QoS-Proxy eingehende Aufträge klassifizieren und in eine Queue einsortieren kann. Im Vorlauf zur Messung zeigten sich bei einer Probemessung Spitzen in den Messwerten von bis zu 1000 ms. Zeitlich betrachtet waren die Spitzen am Anfang der Messung, konnten aber bei den folgenden Messreihen nicht erfasst werden. Tabelle 6.1 enthält die Mittelwerte der Versuche 1 bis 3. Um eine Einschätzung zu den Werten geben zu können sollten weitere Versuche erfolgen. Eine Standardabweichung von fast 2,4 ms bei einem einfachen Web Service erscheint nicht normal. Aus Zeitgründen konnte das Verhalten nicht näher untersucht werden. Versuch Min [ms] Max [ms] Mittelwert [ms] Standardabweichung [ms] 1 9 59 12,65 2,37 2 9 77 12,84 2,69 3 9 103,2 13,01 3,23 Tabelle 6.1: Mittelwerte der Versuch 1 bis 3 6.2.3 Zusammenfassung Das Antworzeitverhalten des QoS-Proxys wird durch die Token-Erzeugungsrate, das Gewicht der jeweiligen Queue und die Anzahl der Aufträge im QoS-Proxy beeinflusst. Tests mit einem einfachen Axis2-basierten Client, der eine Reihe von Operationen durchführt, haben gezeigt, dass sich Auswirkungen auf das Antwortzeitverhalten besonders stark bei einer Reihe von einander abhängigen Web-Service-Anfragen äußern. Der mit Grinder erzeugte Test ruft nur einen Service auf und so ist es naheliegend ein Testszenario aufzubauen dass eine Reihe von Web-Service-Anfragen durchführt und das Ergebnis jeder Anfrage für eine neue Berechnung verwendet. Aus Zeitgründen konnte keine Bandbreitentest durchgeführt werden. Dieser Test sollte verteilt auf mehreren Rechnern erfolgen. 126 Kapitel 7 Zusammenfassung Diese Arbeit entstand im Labor für Verteilte Systeme (DOPSY) an der Fachhochschule Wiesbaden im Rahmen des Projektes ”Selbstmanagement am Beispiel Serviceorientierter Architekturen”. Ziel der Arbeit war das Design und die Implementierung eines generischen QoS-Proxys für SOA-Dienste. Der zu entwickelnde QoS-Proxy sollte dazu mit Hilfe der Service Component Architecture transparent in bestehende Web-servicebasierte Anwendungen integriert werden. In einem ersten Schritt wurden in der Analyse die Anforderungen an den QoS-Proxy formuliert. Dazu gehört die transparente Integrierbarkeit des QoS-Proxys in bestehende SCA-Anwendungen, das Queueing von Web-Service-Anfragen, Monitoring des Laufzeitverhaltens sowie die Konfiguration des QoS-Proxys zur Laufzeit. Zunächst wurde die SCA auf mögliche Erweiterungspunkte untersucht. Dabei stellte sich heraus, dass der QoS-Proxy sich am besten über eine SCA-Policy in eine SCAAnwendung integerieren lässt. Im weiteren wurden Queueing-Strategien des Linux Kernels auf Ihre Eignung für das Queueing von Web-Service-Anfragen betrachtet. Zu den betrachteten QueueingStrategien gehört das Multi Band Priority Queueing, Stochastic Fairness Queueing, Weighted Fair Queueing, Class Based Queueing sowie der Hierarchical-Token-BucketAlgorithmus. Als Token-Verfahren zur Realisierung von Bandbreitenanforderungen wurde der Leaky-Bucket-Algorithmus untersucht. Bei der Analyse geeigneter QueueingStrategien stand im Vordergund die Möglichkeit Anforderungen an Durchsatz und Antwortzeit mit einer entsprechenden Queueing-Strategie umzusetzen. Eine Kombination aus dem Weighted-Fair-Queueing-Algorithmus mit dem Leaky-Bucket-Algorithmus hat sich bei der Betrachtung hierfür als besonders geeignet erwiesen. 127 Kapitel 7. Zusammenfassung Ausgehend von den in der Analyse getroffenen Entscheidungen wurde ein Konzept für einen QoS-Proxy erstellt. In der Grobarchitektur des QoS-Proxys wurden die einzelne Subsysteme identifiziert und in einem Business und Service Layer aufgeteilt. Beim Entwurf der einzelnen Subsysteme wurde auf eine flexible Erweiterbarkeit der Architektur Wert gelegt. Der Proxy soll in eine SCA-Policy integriert werden. Dabei bietet der Proxy unterschiedliche Dienstgüteklassen zu einem Web Service an, die alle auf die selbe Implementierung verweisen. Kern der Architektur ist das Queueing-Subsystem, das die Queueing-Strategien und für das Queueing benötigten Datenstrukturen bereitstellt. Aufgabe des Queueing-Subsystems ist das Queueing von Web-Service-Anfragen. Eine eigene Klasse zum Sammeln von Messwerten erleichtert das Prüfen von Dienstgüteanforderungen. Das Monitoring-Subsystem umfasst die Klassen die zur Sammlung und zur Erzeugung von Statistiken der einzelnen Subsysteme benötigt werden. Verantwortlich für die Konfiguration des QoS-Proxy ist das Konfigurationssubsystem. Dabei werden die Management-Operationen für die im Queueing-Subsystem definierten Algorithmen über JMX zur Verfügung gestellt. Zusätzlich besitzt das Konfigurationssubsystem eine Schnittstelle um einen vertraglichen Rahmen für die Anforderungen an den QoS-Proxy und der bereitgestellten Services zu definieren. Im Anschluß an den Entwurf wurde eine prototypische Implementierung des QoSProxys vorgenommen. Der QoS-Proxy wurde dabei in eine Policy für Apache Tuscany, das eine Umsetzung der SCA Spezifikation 1.0 bereitstellt, integriert. Als QueueingStrategie wurde der Weighted-Fair-Queueing-Algorithmus zusammen mit dem LeakyBucket-Algorithmus implementiert. Innerhalb der Architektur von Tuscany wird pro Web-Service-Anfrage ein Thread erzeugt. Das erlaubt es anstatt der Nachricht den aufrufenden Thread in einer Queue einzusortieren und nach einer Queueing-Strategie abzuarbeiten. Ein bestehendes WSAG4J-System wurde um Funktionalität zur Registrierung von Templates erweitert und ein zusätzlicher Callback-Mechanismus implementiert, der es erlaubt den QoS-Proxy neben allgemeinen Informationen über neue Agreements und der Terminierung von Agreements zu informieren. Die Monitoring- und Konfigurationskomponenten stellen Teile ihrer Funktionalität über JMX zur Verfügung. Mit Hilfe von Management-Anwendungen kann somit die Funktionalität des QoS-Proxys nachvollzogen werden. Exportmöglichkeiten aus dem Monitoring-Subsystem heraus erlauben eine spätere und einfachere Auswertung des Laufzeitverhalten. Aus Zeitgründen konnten keine weitere Queueing-Strategien implementiert werden. Der generische Aspekt des QoSProxys wird durch die Einschränkung auf sca:implementation.java verletzt, verschiedene Tests konnten die Ursache dafür nicht näher eingrenzen. 128 Kapitel 7. Zusammenfassung Mit Hilfe eines Beispiel-Clients auf Basis von Axis2 wurde ein Test der Funktionalität durchgeführt. Dabei wurden für einen Web-Service mehrere Dienstgüteklassen erzeugt. Der Test sollte die Priorisierung der angebotenen Services verdeutlichen und zusätzlich die Funktionalität der Queueing-Strategie Weighted Fair Queueing präsentieren. Nach der Analyse und einem ersten funktionalen Test erfolgte eine architekturelle Bewertung des QoS-Proxys. Dabei wurden insbesondere Schwachstellen in der vorliegenden Implementierung hervorgehoben und mögliche Verbesserungsansätze vorgestellt. Der architekturellen Bewertung folgte ein Bewertung der Leistungsfähigkeit des QoS-Proxys. In einem ersten Schritt wurde das zugrunde liegende Messmodell vorgestellt. Darauf aufbauend wurden Messungen vorgenommen um den Overhead durch den QoS-Proxy zu ermitteln. Ein weiterer Test zur Überprüfung der Bandbreitenanforderungen des QoSProxys konnte aus Zeitgründen nicht durchgeführt werden. Das Ergebnis der Bewertung des Overheads ist nicht eindeutig und soll durch weitere Tests ermittelt werden. Im Rahmen dieser Arbeit wurde die Möglichkeit geschaffen Web-Service-Anfragen unter Berücksichtigung von Dienstgüteanforderungen umzusetzen. Grundlage für weitere Arbeiten am QoS-Proxy sollte die Portierung auf eine aktuelle Version von Tuscany sein. Zur Zeit arbeiten die Apache Tuscany Entwickler an einer Aktualisierung des Policy-Modells in der Tuscany-Architektur. Eine neueren Version von Tuscany erlaubt es die QoS-ProxyPolicy auf das binding.ws-Element einzuschränken. Um eine umfassendere Bewertung des QoS-Proxys zu ermöglichen sollten weitere Queueing-Strategien implementiert werden. Besonders Queueing-Strategien die ein Hierarchie-Modell von Dienstgüteklassen unterstützen sind dabei von Interesse. Queueing-Strategien die hierarchische Strukturen unterstützen eignen sich für spezielle Anwendungsfälle. In der aktuellen Version des Policy-Modells von Tuscany wird die IP des Clients, der eine Web-Service-Anfrage stellt, bereits vor der Aufrufkette aus der SOAP-Nachricht entfernt. Die Entwicklerversion von Tuscany bietet Ansätze zur Umgehung dieser Problematik. Bisher erfolgt die Anpassung einer SCA-Anwendung manuell. Ein graphisches Werkzeug würde das Anpassen, insbesondere bei komplexen und umfangreichen SCAAnwendungen erheblich erleichtern. Das Werkzeug könnte die composite-Dateien einer Anwendung analysieren, Services zur Auswahl stellen für die das Dienstgütemanagement aktiviert werden soll und verschiedene Dienstgüteklassen zur Auswahl stellen. Die graphische Anwendung könnte in einem weiteren Schritt um einen Editor für die Konfigurationsdatei des QoS-Proxys erweitert werden. Workflow-Beschreibungen in Form der BPEL sind in vielen Geschäftsanwendungen weit verbreitet. Einzelne Aktivitäten in einem BPEL-basierten Workflow erfolgen auf Basis 129 Kapitel 7. Zusammenfassung von Web Services. Eine Erweiterung des QoS-Proxys könnte solche Workflows berücksichtigen und unterschiedliche Wertigkeiten für verschiedene Web Services offerieren. Insbesondere die Koordinationen von verteilten Web Services und der Umsetzung durch den QoS-Proxy bietet eine interessante Herausforderung. Langfristig sollte der QoS-Proxy um eine Bewertungsplattform erweitern werden. Dabei sollte ein Abrechnungsmodell eingeführt werden, dass es erlaubt die Nutzung der Web Services des QoS-Proxys abzurechnen. Aufgeschlüsselt nach Client und Dienstgüteklasse kann das Abrechnungsmodell in eine Service-Level-Management-Plattform integriert werden. 130 Kapitel 8 Literaturverzeichnis [ACD+ 07] A NDRIEUX, Alain ; C ZAJKOWSKI, Karl ; DAN, Asit ; K EAHEY, Kate ; L UDWIG, Heiko ; NAKATA, Toshiyuki: Web Services Agreement Specification (WS-Agreement). V1.0. Open Grid Forum, P.O. Box 2326, Joliet, Illinois 60434 USA: Open Grid Forum, März 2007. http://forge.gridforum.org/sf/docman/ do/downloadDocument/projects.graap-wg/docman. root.published_documents.web_services_agreement_ specifica/doc14574 [AF08] A STON, Philip ; F ITZGERALD, Calum: The Grinder 3 - Complete User Guide, August 2008. http://grinder.sourceforge.net/g3/ manual.pdf [BBB+ 07] B EISIEGEL, Michael ; B LOHM, Henning ; B OOZ, Dave ; E DWARDS, Mike ; H URLEY, Oisin ; I ELCEANU, Sabin: SCA Assembly Model. V1.0. Open Service Oriented Architecture, März 2007. http://www.osoa.org/ download/attachments/35/SCA_AssemblyModel_V100.pdf [BBC+ 07a] B EISIEGEL, Michael ; B OOZ, Dave ; C HAO, Ching-Yun ; E DWARDS, Mike ; I ELCEANU, Sabin: SCA Policy Framework. V1.0. Open Service Oriented Architecture, März 2007. http://www.osoa.org/download/ attachments/35/SCA_Policy_Framework_V100.pdf [BBC+ 07b] B ERGLUND, Anders ; B OAG, Scott ; C HAMBERLIN, Don ; F ERNÁNDEZ, Mary F. ; K AY, Michael ; ROBIE, Jonathan ; S IMÉON, Jérôme: XML Path Language (XPath). V2.0. Massachusetts Institute of Technology,32 Vassar 131 Kapitel 8. Literaturverzeichnis Street, Cambridge, MA 02139 USA: W3C, Januar 2007. http://www. w3.org/TR/xpath20/ [BEA03] BEA Systems Inc.: Streaming API for XML JSR-173 for Java Specification. 1. Auflage. Oktober 2003 [Blo08] B LOCH, Joshua: Effective Java: A Programming Language Guide. 2. Auflage : Addison-Wesley Longman, 2008 (The Java Series). – 384 S [BVP06] B ON, Jan von ; V EEN, Annelies van d. ; P IEPER, Mark: Foundations in IT Service Management basierend auf ITIL. Van Haren Publishing, 2006 [CFSD90] C ASE, J. ; F EDOR, M. ; S CHOFFSTALL, M. ; DAVIN, J.: RFC1157 - Simple Network Management Protocol. IETF Secretariat c/o Association Management Solutions, LLC (AMS) 48377 Fremont Blvd., Suite 117 Fremont, California 94538 USA: Internet Engineering Task Force Network Working Group, Mai 1990 [Deb04] D EBUSMANN, Markus: Modellbasiertes Service Level Management verteilter Anwendungssysteme, Universität Kassel, Diss., Dezember 2004 [Dis05] Distributed Management Task Force: CIM Infrastructure Specification. v2.3. Oktober 2005 [DKS89] D EMERS, A. ; K ESHAV, S. ; S HENKER, S.: Analysis and simulation of a fair queueing algorithm. In: SIGCOMM ’89: Symposium proceedings on Communications architectures & protocols. New York, NY, USA : ACM, 1989. – ISBN 0–89791–332–9, S. 1–12 [Erl07] E RL, Thomas: SOA Principles of Service Design. 1. Auflage. Prentice Hall International, 2007 (Prentice Hall Service-Oriented Computing Series from Thomas Erl). – 608 S [Fen08] F ENG, Raymond: Extending Tuscany. http://tuscany.apache.org/scajava-extension-development-guide.data/ExtendingTuscany1.pdf. Version: Juni 2008. http://tuscany.apache.org/ sca-java-extension-development-guide.data/ ExtendingTuscany1.pdf. – Präsentation [FJ95] F LOYD, Sally ; JACOBSON, Van: Link-sharing and Resource Management Models for Packet Networks. In: IEEE/ACM Transactions on Networking 3 132 Kapitel 8. Literaturverzeichnis (1995), August, S. 365 – 386. http://dx.doi.org/10.1109/90. 413212. – DOI 10.1109/90.413212 [Fou08] F OUNDATION, Apache S.: Apache Tuscany SCA Java Architecture Guide. http://tuscany.apache.org/sca-java.html, 2008 [FW04] FALLSIDE, David C. ; WALMSLEY, Priscilla: XML Schema Part 0: Primer Second Edition. V1.1. Massachusetts Institute of Technology,32 Vassar Street, Cambridge, MA 02139 USA: W3C, Oktober 2004. http://www. w3.org/TR/xmlschema-0/ [GC01] G OVERNMENT C OMMERCE, Office of: Service Delivery. Stationery Office, 2001 (IT Infrastructure Library Series) [GHJ95] G AMMA, Erich ; H ELM, Richard ; J OHNSON, Ralph E.: Design Patterns. Elements of Reusable Object-Oriented Software. 1. Auflage. AddisonWesley, 1995 [Gup05] G UPTA, Samudra: Pro Apache Log4j. 2. Auflage. APress, 2005. – 224 S [Ham01] H AMILTON, Graham: Java Logging APIs. Sun Microsystems Incoperated, 901 San Antonio Road, Palo Alto, California 94303, U.S.A: Sun Microsystems, September 2001 [Hof00] H OFFMANN, Ulrich: Modellierung von Kommunikationssystemen. 1. Auflage. Fortis, 2000. – 182 S [JN06] J OHNSON, Chris D. ; NARESH, Revanuru: Concurrency Utilities for Java EE, April 2006. http://gee.cs.oswego.edu/dl/ concurrencyee-interest/ConcurrencyUtilsEE_Early_ Draft_Preview_V01.pdf [Knu98] K NUTH, Donald E.: The Art of Computer Programming. Bd. 3. Addison Wesley, 1998. – 780 S [Kö07] KÖHLER, Peter T.: ITIL. 2. Auflage. Springer, 2007. – 396 S [KS93] K LEMM, Liesel ; S CHWELLENBACH, Detlef: Leistungsmessung in verteilten Systemen: Meßmodell, Implementierung, Anwendung. (1993). http: //www.scientificcommons.org/26091074 133 Kapitel 8. Literaturverzeichnis [Lew99] L EWIS, Lundy: Service Level Management of Enterprise Networks. 1. Auflage. Artech House, 685 Canton Street, Norwood, MA 02062, USA : Artech House, 1999. – 326 S [McK90] M C K ENNEY, P.E.: Stochastic fairness queueing. In: INFOCOM ’90. Ninth Annual Joint Conference of the IEEE Computer and Communication Societies. ’The Multiple Facets of Integration’. Proceedings., IEEE (1990), June, S. 733–740 vol.2. http://dx.doi.org/10.1109/INFCOM.1990. 91316. – DOI 10.1109/INFCOM.1990.91316 [PG93] PAREKH, Abhay K. ; G ALLAGER, Robert G.: A generalized processor sharing approach to flow control in integrated services networks: the single-node case. In: IEEE/ACM Transactions on Networking 1 (1993), Nr. 3, 344–357. http://dx.doi.org/http://dx.doi.org/10. 1109/90.234856. – DOI http://dx.doi.org/10.1109/90.234856. – ISSN 1063–6692 [SMS+ 02] S AHAI, Akhil ; M ACHIRAJU, Vijay ; S AYAL, Mehmet ; J IN, Li J. ; C ASATI, Fabio: Automated SLA Monitoring for Web Services. In: Lecture Notes in Computer Science 2506 (2002), S. 28–41 [Sun02] Sun Microsystems: Java Management Extensions (JMX) Specification. V1.2. Oktober 2002. http://jcp.org/aboutJava/ communityprocess/final/jsr003/index3.html [Sun04] Sun Microsystems: Java Remote Method Invocation Specification. V1.5. 2004. http://java.sun.com/j2se/1.5/pdf/rmi-spec-1. 5.0.pdf [Sun06] Sun Microsystems: Java Management Extensions (JMX) Specification. V1.4. November 2006. http://java.sun.com/javase/6/docs/ technotes/guides/jmx/JMX_1_4_specification.pdf [SV95] S HREEDHAR, M. ; VARGHESE, George: Efficient fair queueing using deficit round robin. In: SIGCOMM Comput. Commun. Rev. 25 (1995), Nr. 4, S. 231–242. http://dx.doi. org/http://doi.acm.org/10.1145/217391.217453. – DOI http://doi.acm.org/10.1145/217391.217453. – ISSN 0146–4833 [Tan02] TANENBAUM, Andrew S.: Computer Networks. 4. Auflage. Prentice Hall, 2002. – 912 S 134 Kapitel 8. Literaturverzeichnis [Tan07] TANENBAUM, Andrew S.: Modern Operating Systems. 3. Auflage. Prentice Hall, 2007. – 1104 S [TG05] T RAN -G IA, Phuoc: Einführung in die Leistungsbewertung und Verkehrstheorie. 2. Auflage. Oldenbourg, 2005. – 284 S [Tur02] T URNER, J.S.: New directions in communications (or which way to the information age?). In: Communications Magazine, IEEE 40 (2002), May, Nr. 5, S. 50–57. http://dx.doi.org/10.1109/MCOM.2002. 1006972. – DOI 10.1109/MCOM.2002.1006972. – ISSN 0163–6804 [VMSE+ 04] VALENZUELA, J.L. ; M ONLEON, A. ; S AN E STEBAN, I. ; P ORTOLES, M. ; S ALLENT, O.: A hierarchical token bucket algorithm to enhance QoS in IEEE 802.11: proposal, implementation and evaluation. In: Vehicular Technology Conference, 2004. VTC2004-Fall. 2004 IEEE 60th 4 (2004), Sept., S. 2659–2662 Vol. 4. http://dx.doi.org/10.1109/ VETECF.2004.1400539. – DOI 10.1109/VETECF.2004.1400539. – ISSN 1090–3038 135 Kapitel 8. Literaturverzeichnis 136 Anhang A Abkürzungen A API Application Programming Interface. B BPEL Business Process Execution Language. C CBQ Class Based Queuing. CIM Common Information Model. D DMTF Distributed Management Task Force. E EAR Enterprise Application Archive. EJB Enterprise Java Beans. EPR Endpoint Reference. 137 Anhang A. Abkürzungen F FIFO First In First Out. G GRAAP Grid Resource Allocation Agreement Protocol. H HTB Hierarchical Token Bucket. I ITIL IT Infrastructure Library. J J2SE Java 2 Standard Edition. JAR Java Archive. JAXB Java Architecture for XML Binding. JBI Java Business Integration. JEE Java Enterprise Edition. JMX Java Management Extensions. JSR Java Specification Request. L LB Leaky Bucket. Q QoS Quality of Service. 138 Anhang A. Abkürzungen S SCA Service Component Architecture. SFQ Stochastic Fairness Queuing. SLA Service Level Agreement. SLM Service Level Management. SLO Service Level Objective. SLR Service Level Requirement. SNMP Simple Network Management Protocol. SOA Service Oriented Architecture. StAX Streaming API for XML. W WAR Web Archive. WBEM Web-Based Enterprise Management. WCF Windows Communication Foundation. WFQ Weighted Fair Queuing. WSAG4J Web Service Agreement for Java. WSDL Web Service Description Language. X XML Extensible Markup Language. XSLT Extensible Stylesheet Language Transformation. 139 Anhang A. Abkürzungen 140 Anhang B Messwerttabellen für den QoS-Proxy Messreihe Min [ms] Max [ms] 1 9 56 2 9 59 3 9 64 4 9 60 5 9 56 Mittelwert [ms] Standardabweichung [ms] 12,72 2,32 12,45 2,37 12,62 2,29 12,77 2,42 12,67 2,43 Tabelle B.1: Messwerte für Versuch 1 Messreihe Min [ms] Max [ms] 1 10 107 2 9 70 3 9 69 4 9 73 5 9 66 Mittelwert [ms] Standardabweichung [ms] 13,35 3,24 12,86 2,72 12,40 2,38 13,13 2,7 12,47 2,4 Tabelle B.2: Messwerte für Versuch 2 141 Anhang B. Messwerttabellen für den QoS-Proxy Messreihe Min [ms] Max [ms] Mittelwert [ms] Standardabweichung [ms] 1 9 93 13,34 2,77 2 9 56 13,05 2,9 3 9 64 12,92 2,76 4 9 228 12,83 3,9 5 9 75 13,01 3,23 Tabelle B.3: Messwerte für Versuch 3 142 Anhang C Inhalt des Datenträgers Der Inhalt des dieser Arbeit beiliegenden Datenträgers gliedert sich in die folgenden fünf Verzeichnisse: 1. Im Verzeichnis Text befindet sich der Text dieser Arbeit als PDF-Datei. 2. Das Verzeichnis Source enthält die Quellen der Arbeit. Zu den Quellen gehören: • der QoS-Proxy, • die verwendete Apache-Tuscany-SCA-Implementierung, • eine Beispielanwendung, • ein angepasstes WSAG4J-System • und eine Beispielanwendung für das WSAG4J-System. 3. Das Verzeichnis Javadoc enthält die Javadoc-generierte Dokumentation der erstellten Klassen. 4. Im Verzeichnis Software befindet sich die für die Arbeit verwendete Software. Dazu gehören Programmpakete und Bibliotheken die zum übersetzen benötigt werden oder bei der Entwicklung verwendet wurden. 5. Das Verzeichnis Literatur enthält Dokumente, die in der Arbeit zitiert werden, sofern sie elektronisch verfügbar waren. Im Grundverzeichnis des Datenträgers befindet sich eine Textdatei Anmerkungen mit Hinweisen zur Software, inbesondere zum übersetzen des QoS-Proxys und der Integration in bestehende SCA-Anwendungen. 143