|Die MQSeries-Funktionen können in einer Vielzahl von Szenarios verwendet |werden. In diesem Abschnitt werden einige der allgemeineren Szenarios, |einschließlich Basis-Nachrichtenübertragung, Anwendungskonnektivität und |Datenveröffentlichung, beschrieben.
|Die grundlegendste Form der Nachrichtenübertragung mit den DB2 |MQSeries-Funktionen findet statt, wenn alle Datenbankanwendungen mit demselben |DB2-Server verbunden sind. Die Clients können mit dem Server lokal oder |in einer Netzwerkumgebung verbunden sein.
|In einem einfachen Szenario ruft Client A die Funktion MQSEND auf, um eine |benutzerdefinierte Zeichenfolge an den standardmäßig definierten |Servicestandort zu senden. Die MQSeries-Funktionen werden dann in DB2 |auf dem Datenbankserver ausgeführt. Zu einem späteren Zeitpunkt ruft |Client B die Funktion MQRECEIVE auf, um die Nachricht am Kopfsatz der vom |Standardservice definierten Warteschlange zu entfernen und an den Client |zurückzugeben. Die MQSeries-Funktionen für diesen Vorgang werden wieder |von DB2 ausgeführt.
|Datenbankclients können die einfache Nachrichtenübertragung auf |unterschiedliche Weise verwenden. Im Folgenden werden einige allgemeine |Verwendungsmöglichkeiten der Nachrichtenübertragung erläutert: |
|Das folgende Szenario ist eine Erweiterung des obigen Szenarios und |berücksichtigt die Nachrichtenübertragung von einem fernen Standort. |Nachrichten werden hierbei zwischen Maschine A und Maschine B |ausgetauscht. Die Vorgehensweise ist wie folgt: |
|Unter Verwendung von MQSEND legt ein DB2-Benutzer oder -Entwickler fest, |welche Daten zu welchem Zeitpunkt an welche Zieladresse gesendet |werden. In der IT-Branche wird dieser Vorgang als "Senden und |Vergessen" (Send and Forget) bezeichnet. Damit ist gemeint, dass der |Sender die Nachricht nur sendet und sich im Hinblick auf den ordnungsgemäßen |Empfang der Nachricht auf die garantierten Übergabeprotokolle von MQSeries |verlässt. Diese Vorgehensweise wird in den folgenden Beispielen |verdeutlicht.
|Beispiel 4: Senden einer benutzerdefinierten Zeichenfolge an den |Servicepunkt meinPlatz mit der Richtlinie hohePriorität:
|VALUES DB2MQ.MQSEND('meinPlatz','hohePriorität','test')
|In diesem Fall bezieht sich die Richtlinie hohePriorität auf eine |Richtlinie, die im AMI-Repository definiert ist, die MQSeries-Priorität auf |die höchste Stufe setzt und möglicherweise andere Servicequalitäten, wie |beispielsweise den Datenbankzugriff, ebenfalls anpasst.
|Der Nachrichteninhalt kann aus beliebigen gültigen Kombinationen von SQL- |und benutzerdefinierten Daten bestehen. Dazu gehören verschachtelte |Funktionen, Operatoren und Umsetzungsausdrücke. Unter Verwendung der |Tabelle EMPLOYEE mit den VARCHAR-Spalten LASTNAME, FIRSTNAME und DEPARTMENT |gehen Sie zum Senden einer Nachricht, die diese Informationen für jeden |Mitarbeiter in Abteilung 5LGA enthält, beispielsweise wie folgt vor:
|Beispiel 5:
|SELECT DB2MQ.MQSEND(LASTNAME || ' ' || FIRSTNAME || ' ' || DEPARTMENT) | FROM EMPLOYEE | WHERE DEPARTMENT = '5LGA'
|Wenn die Tabelle eine ganzzahlige Spalte AGE enthält, kann sie wie folgt |eingefügt werden:
|Beispiel 6:
|SELECT DB2MQ.MQSEND(LASTNAME || ' ' || FIRSTNAME || ' ' || DEPARTMENT|| ' ' || char(AGE)) | FROM EMPLOYEE | WHERE DEPARTMENT = '5LGA'
|Wenn die Tabelle EMPLOYEE eine Spalte RESUME vom Typ CLOB anstelle einer |Spalte AGE hat, könnte eine Nachricht mit den Angaben für jeden Mitarbeiter in |der Abteilung 5LGA mit folgenden Informationen gesendet werden:
|Beispiel 7:
| SELECT DB2MQ.MQSEND | (clob(LASTNAME) || ' ' || clob(FIRSTNAME) || ' ' || clob(DEPARTMENT) || ' ' || RESUME)) | FROM EMPLOYEE | WHERE DEPARTMENT = '5LGA'
|Beispiel 8:
|Das folgende Beispiel zeigt schließlich, wie Nachrichteninhalt mit einem |gültigem SQL-Ausdruck abgeleitet werden kann. Unter Verwendung einer |zweiten Tabelle DEPT mit den VARCHAR-Spalten DEPT_NO und DEPT_NAME können |Nachrichten gesendet werden, die LASTNAME und DEPT_NAME für den Mitarbeiter |enthalten:
|Beispiel 8:
|SELECT DB2MQ.MQSEND(e.LASTNAME || ' ' || d.DEPTNAME) FROM EMPLOYEE e, DEPT d | WHERE e.DEPARTMENT = d.DEPTNAME
|Mit den DB2 MQSeries-Funktionen können Nachrichten empfangen oder gelesen |werden. Der Unterschied zwischen Lesen und Empfangen besteht darin, |dass die Nachricht beim Lesen an den Kopfsatz der Warteschlange zurückgegeben, |also nicht aus der Warteschlange entfernt wird. Bei Empfangsoperationen |wird die Nachricht aus der Warteschlange entfernt. Eine Nachricht, die |über eine Empfangsoperation abgerufen wird, kann nur einmal abgerufen |werden. Eine Nachricht, die über einen Lesevorgang abgerufen wird, kann |dagegen viele Male abgerufen werden. Die folgenden Beispiele |veranschaulichen dies:
|Beispiel 8:
|VALUES DB2MQ.MQREAD()
|Dieses Beispiel gibt eine VARCHAR-Zeichenfolge mit der Nachricht am |Kopfsatz der Warteschlange zurück, die über den Standardservice unter |Verwendung der Standardrichtlinie für die Servicequalität definiert |wurde. Wichtig ist zu beachten, dass ein Nullwert zurückgegeben wird, |wenn keine Nachrichten zum Lesen vorhanden sind. Die Warteschlange wird |durch diese Operation nicht geändert.
|Beispiel 9:
|VALUES DB2MQ.MQRECEIVE('Employee_Changes')
|Das obige Beispiel zeigt, wie eine Nachricht aus dem Kopfsatz der |Warteschlange entfernt werden kann, die vom Service Employee_Changes unter |Verwendung der Standardrichtlinie definiert wurde.
|Eine äußerst leistungsstarke Funktion von DB2 besteht darin, eine Tabelle |aus einer benutzerdefinierten (oder von DB2 gelieferten) Funktion zu |erstellen. Mit dieser Tabellenfunktion können Sie den Inhalt einer |Warteschlange als DB2-Tabelle speichern. Das folgende Beispiel zeigt |eine vereinfachte Form dieses Vorgangs:
|Beispiel 10:
|SELECT t.* FROM table ( DB2MQ.MQREADALL()) t
|Diese Abfrage gibt eine Tabelle zurück, die aus allen Nachrichten der vom |Standardservice definierten Warteschlange und den Metadaten zu diesen |Nachrichten besteht. Die vollständige Definition der zurückgegebenen |Tabellenstruktur ist im Anhang definiert. Die erste Spalte gibt den |Inhalt der Nachricht wieder, und die restlichen Spalten enthalten die |Metadaten. Wenn nur die Nachrichten zurückgegeben werden sollen, kann |das Beispiel wie folgt geändert werden:
|Beispiel 11:
|SELECT t.MSG FROM table (DB2MQ.MQREADALL()) t
|Die von einer Tabellenfunktion zurückgegebene Tabelle unterscheidet sich |nicht von einer Tabelle, die direkt aus der Datenbank abgerufen wird. |Für diese Tabelle gibt es folglich zahlreiche Verwendungsmöglichkeiten. |Sie können den Inhalt der Tabelle beispielsweise mit einer anderen Tabelle |verbinden oder die Anzahl der Nachrichten in einer Warteschlange zählen:
|Beispiel 12:
|SELECT t.MSG, e.LASTNAME | FROM table (DB2MQ.MQREADALL() ) t, EMPLOYEE e | WHERE t.MSG = e.LASTNAME
|Beispiel 13:
|SELECT COUNT(*) FROM table (DB2MQ.MQREADALL()) t
|Ferner können Sie die Tatsache verdecken, dass die Tabellenquelle eine |Warteschlange ist, indem Sie eine Sicht für die Tabellenfunktion |erstellen. Das folgende Beispiel erstellt beispielsweise eine Sicht |namens NEW_EMP der Warteschlange, auf die von einem Service namens |NEW_EMPLOYEES verwiesen wird:
|Beispiel 14:
|CREATE VIEW NEW_EMP (msg) AS | SELECT t.msg FROM table (DB2MQ.MQREADALL()) t
|In diesem Fall wird die Sicht nur durch eine einzelne Spalte definiert, die |eine vollständige Nachricht enthält. Wenn die Nachrichten einfach |strukturiert sind (z. B. bestehend aus zwei Feldern mit |einer festen Länge), können die integrierten DB2-Funktionen zur syntaktischen |Analyse der beiden Spalten verwendet werden. Wenn Sie beispielsweise |wissen, dass Nachrichten an eine bestimmte Warteschlange stets einen Nachnamen |aus 18 Zeichen, gefolgt von einem Vornamen aus 18 Zeichen enthalten, können |Sie wie folgt eine Sicht definieren, die jedes Feld als separate Spalte |enthält:
|Beispiel 15:
|CREATE VIEW NEW_EMP2 AS | SELECT left(t.msg,18) AS LNAME, right(t.msg,18) AS FNAME | FROM table(DB2MQ.MQREADALL()) t
|Der MQSeries-Assistent, eine neue Funktion von DB2 Stored Procedure |Builder, kann zur Erstellung neuer DB2-Tabellenfunktionen und DB2-Sichten |verwendet werden, die Spalten begrenzte Nachrichtenstrukturen zuordnen.
|Schließlich wird häufig gewünscht, den Inhalt mindestens einer Nachricht in |der Datenbank zu speichern. Hierzu kann zum Bearbeiten und Speichern |des Nachrichteninhalts die volle SQL-Funktionalität genutzt werden. Das |folgende Beispiel veranschaulicht dies vermutlich auf einfachste Weise:
|Beispiel 16:
|INSERT INTO MESSAGES | SELECT t.msg FROM table (DB2MQ.MQRECEIVEALL()) t
|Unter Verwendung der Tabelle MESSAGES, die eine einzelne |VARCHAR(2000)-Spalte enthält, fügt die obige Anweisung die Nachrichten aus der |Standard-Servicewarteschlange in die Tabelle ein. Diese Vorgehensweise |kann für unterschiedliche Situationen weiter abgewandelt werden.
|Die Anwendungsintegration ist ein allgemeiner Bestandteil vieler |Lösungen. Ob es um die Integration einer erworbenen Anwendung in eine |vorhandene Infrastruktur oder die Integration einer neu entwickelten Anwendung |in eine vorhandene Umgebung geht - in vielen Fällen stellt sich die Aufgabe, |einen heterogenen Verbund von Subsystemen als funktionierende Einheit |zusammenzufügen. MQSeries wird im Allgemeinen als notwendiges Tool für |die Anwendungsintegration erachtet. Da MQSeries von den meisten |Hardware- und Softwarekomponenten bzw. Sprachumgebungen aufgerufen |werden kann, ist eine Verbindung zwischen äußerst heterogenen |Anwendungsgruppen möglich.
|In diesem Abschnitt werden einige Anwendungsintegrationsszenarios und deren |Verwendung mit DB2 beschrieben. Da das Themengebiet sehr groß ist, kann |die Anwendungsintegration in diesem Rahmen nicht umfassend behandelt |werden. Deshalb liegt der Schwerpunkt auf zwei einfachen Themen: |R/R-Kommunikation sowie MQSeries Integrator und P/S.
|Die R/R-Kommunikation ist eine Methode, die von Anwendungen häufig zur |Anforderung von Services anderer Anwendungen verwendet wird. Eine |Möglichkeit besteht darin, dem Serviceprovider eine Nachricht mit einer |Arbeitsanforderung zu senden. Nachdem die entsprechende Arbeit |durchgeführt wurde, kann der Provider die Ergebnisse (oder nur eine |Beendigungsbestätigung) an den Anforderer zurücksenden. Bei Verwendung |der oben beschriebenen Basis-Nachrichtenübertragungsmethoden ist die |Anforderung des Senders jedoch in keiner Weise mit der Antwort des |Serviceproviders verbunden. Sofern der Anforderer vor dem Fortfahren |nicht auf eine Antwort wartet, muss für die Zuordnung der Anwort zur |entsprechenden Anforderung ein bestimmtes Verfahren verwendet werden. |Hierzu ist allerdings keine gesonderte Entwicklung notwendig, da MQSeries eine |Korrelations-ID zur Verfügung stellt, die einen Bezug zwischen den beteiligten |Nachrichten herstellt.
|Dieses Verfahren kann auf unterschiedliche Weise eingesetzt werden. |Am einfachsten ist es jedoch, wenn der Anforderer die Nachricht wie im |folgenden Beispiel gezeigt mit einer bekannten Korrelations-ID |kennzeichnet:
|Beispiel 17:
|DB2MQ.MQSEND ('meinRequester','meineRichtlinie','SendeStatus:kund1','Anf1')
|Durch diese Anweisung wird der Anweisung MQSEND der Parameter Anf1 |hinzugefügt, um die Korrelations-ID für die Anforderung anzugeben.
|Verwenden Sie zum Empfangen einer Antwort die entsprechende Anweisung |MQRECEIVE, um die erste vom angegebenen Service definierte Nachricht selektiv |abzurufen, die mit der Korrelations-ID wie folgt übereinstimmt:
|Beispiel 18:
|DB2MQ.MQRECEIVE('meinEmpfänger','meineRichtlinie','Anf1')
|Wenn die die Anforderung verarbeitende Anwendung ausgelastet ist und der |Anforderer vor dem Senden der Antwort die Anweisung MQRECEIVE ausgibt, werden |keine Nachrichten gefunden, die mit dieser Korrelations-ID |übereinstimmen.
|Zum Empfangen von Serviceanforderung und Korrelations-ID wird eine |Anweisung wie die folgende verwendet:
|Beispiel 19:
|SELECT msg, correlid FROM table (DB2MQ.MQRECEIVEALL('aServiceProvider','meineRichtlinie',1)) t
|Dadurch wird die Nachricht und die Korrelations-ID der ersten Anforderung |vom Service aServiceprovider zurückgegeben.
|Sobald der Service ausgeführt wurde, wird eine entsprechende |Antwortnachricht an die von aRequester beschriebene Warteschlange |gesendet. In der Zwischenzeit können vom Serviceanforderer andere |Tätigkeiten ausgeführt werden. Es gibt keine Sicherheit, dass die |ursprüngliche Serviceanforderung innerhalb des festgelegten Zeitraums eine |Antwort erhält. Zeitlimits auf Anwendungsebene wie diese fallen in den |Aufgabenbereich der Entwickler. Der Anforderer muss eine Abfrage |durchführen, um das Vorliegen einer Antwort zu prüfen.
|Der Vorteil dieser zeitlich unabhängigen asynchronen Verarbeitung liegt |darin, dass der Anforderer und der Serviceprovider völlig unabhängig |voneinander arbeiten können. Sie kann beispielsweise in Umgebungen |eingesetzt werden, in denen Anwendungen nur zeitweilig miteinander verbunden |sind, oder in eher stapelorientierten Umgebungen, in denen mehrere |Anforderungen oder Antworten vor der Verarbeitung in Spalten zusammengefasst |werden. Diese Art der Spaltenberechnung wird häufig in Data |Warehouse-Umgebungen verwendet, um ein Data Warehouse oder einen aktiven |Datenspeicher regelmäßig zu aktualisieren.
|Ein weiteres häufiges Szenario der Anwendungsintegration besteht darin, |dass eine Anwendung andere Anwendungen über wichtige Ereignisse |informiert. Hierzu wird einfach eine Nachricht an eine Warteschlange |gesendet, die von einer anderen Anwendung überwacht wird. Der Inhalt |der Nachricht kann aus einer benutzerdefinierten Zeichenfolge oder aus |Datenbankspalten bestehen. Oft muss nur eine Nachricht unter Verwendung |der Funktion MQSEND gesendet werden. Wenn diese Nachricht gleichzeitig |an mehrere Empfänger gesendet werden soll, kann die Verteilerfunktion von |MQSeries AMI verwendet werden.
|Ein Verteiler wird mithilfe des Verwaltungs-Tools von AMI definiert. |Ein Verteiler umfasst eine Liste individueller Services. Eine an einen |Verteiler gesendete Nachricht wird an jeden innerhalb der Liste definierten |Service gesendet. Dies ist vor allem dann besonders nützlich, wenn |einige Services immer an allen Nachrichten interessiert sind. Das |folgende Beispiel zeigt, wie eine Nachricht an die interessierten Parteien im |Verteiler gesendet wird:
|Beispiel 20:
|DB2MQ.MQSEND('interessierteGruppen','allgemein interessante Informationen');
|Wenn für Nachrichten an bestimmte Services bessere Kontrollmöglichkeiten |zur Verfügung stehen sollen, muss die P/S-Funktion verwendet werden. |P/S-Systeme bieten normalerweise eine skalierbare und sichere Umgebung, in der |sich viele Subskribenten registrieren können, um Nachrichten von mehreren |Herausgebern zu empfangen. Zur Unterstützung dieser Funktionalität kann |die MQPublish-Schnittstelle in Verbindung mit MQSeries Integrator oder der |P/S-Funktion von MQSeries verwendet werden.
|MQPublish ermöglicht dem Benutzer, der Nachricht optional ein Thema |hinzuzufügen. Mit dem Thema kann der Subskribent die zu akzeptierenden |Nachrichten genauer definieren. Zu diesem Zweck müssen die folgenden |Schritte ausgeführt werden: |
|Zum Veröffentlichen dieser Daten unter Verwendung aller |Standardeinstellungen und eines Nullthemas wird die folgende Anweisung |verwendet:
|Beispiel 21:
|SELECT DB2MQ.MQPUBLISH(LASTNAME || ' ' || FIRSTNAME || ' ' || DEPARTMENT|| ' ' ||char(AGE)) | FROM EMPLOYEE | WHERE DEPARTMENT = '5LGA'
|Bei vollständiger Angabe aller Parameter und Vereinfachung der Nachricht, |so dass nur LASTNAME enthalten ist, lautet die Anweisung wie folgt:
|Beispiel 22:
|SELECT DB2MQ.MQPUBLISH('HR_INFO_PUB', 'SPECIAL_POLICY', LASTNAME, | 'ALL_EMP:5LGA', 'MANAGER') | FROM EMPLOYEE | WHERE DEPARTMENT = '5LGA'
|Diese Anweisung veröffentlicht Nachrichten an den Veröffentlichungsservice |HR_INFO_PUB, wobei der Service SPECIAL_POLICY verwendet wird. Die |Nachrichten weisen darauf hin, dass der Sender das Thema MANAGER ist. |Die Zeichenfolge für das Thema zeigt, dass mehrere Themen angegeben werden |können, die mit einem Doppelpunkt (:) miteinander verknüpft |werden. In diesem Beispiel können sich die Subskribenten aufgrund der |Verwendung von zwei Themen für ALL_EMP oder nur für 5LGA registrieren, um die |Nachrichten zu empfangen.
|Für den Empfang veröffentlichter Nachrichten muss sich der Benutzer |zunächst für Nachrichten mit einem bestimmten Thema registrieren und den Namen |des Subskribentenservices angeben, an die die Nachrichten gesendet werden |sollen. Wichtig ist zu beachten, dass ein AMI-Subskribentenservice |einen Broker- und einen Empfängerservice definiert. Der Broker-Service |gibt an, wie der Subskribent mit dem P/S-Broker kommuniziert. Der |Empfängerservice ist der Service, an den die mit der Subskription |übereinstimmenden Nachrichten gesendet werden. Bei der folgenden |Anweisung erfolgt eine Registrierung für das Thema ALL_EMP.
|Beispiel 23:
|DB2MQ.MQSUBSCRIBE('einSubskribent', 'ALL_EMP')
|Nachdem eine Teilnehmerberechtigung für eine Anwendung eingerichtet wurde, |werden Nachrichten mit dem Betreff ALL_EMP an den vom Subskribentenservice |definierten Empfängerservice gesendet. Eine Anwendung kann über mehrere |gleichzeitig geltende Subskriptionen verfügen. Um die entsprechenden |Nachrichten für eine Subskription zu erhalten, kann eine der |Standardfunktionen für den Nachrichtenabruf verwendet werden. Wenn der |Subskribentenservice einSubskribent den Empfängerservice beispielsweise als |einSubskribentEmpfänger definiert, wird die erste Nachricht von der folgenden |Anweisung ohne Löschen gelesen:
|Beispiel 24:
|DB2MQ.MQREAD('einSubskribentEmpfänger')
|Zur Ermittlung der Nachrichten und der zugehörigen Themen kann eine der |Tabellenfunktionen verwendet werden. Die folgende Anweisung empfängt |die ersten fünf Nachrichten von einSubskribentEmpfänger und zeigt sowohl |Nachricht als auch Thema an:
|Beispiel 25:
|SELECT t.msg, t.topic | FROM table (DB2MQ.MQRECEIVEALL('aSubscriberReceiver',5)) t
|Zum Lesen aller Nachrichten mit dem Betreff ALL_EMP kann unter Verwendung |von SQL folgende Anweisung ausgegeben werden:
|Beispiel 26:
|SELECT t.msg FROM table (DB2MQ.MQREADALL('einSubskribentEmpfänger')) t | WHERE t.topic = 'ALL_EMP'
|Wenn an einem bestimmten Thema kein Interesse mehr besteht, muss die |Teilnehmerberechtigung mit einer Anweisung wie folgt explizit aufgehoben |werden:
|Beispiel 27:
|DB2MQ.MQUNSUBSCRIBE('einSubskribent', 'ALL_EMP')
|Nach Ausgabe dieser Anweisung sendet der P/S-Broker keine für diese |Subskription relevanten Nachrichten mehr.
|Ein weiteres wichtiges Verfahren der Datenbank-Nachrichtenübertragung ist |die automatisierte Veröffentlichung. Unter Verwendung des |Auslöser-Tools in DB2 können Nachrichten im Rahmen eines Auslöseraufrufs |automatisch veröffentlicht werden. Zwar können für die automatisierte |Datenveröffentlichung auch andere Verfahren verwendet werden, der |auslöserbasierte Ansatz gewährt Administratoren und Entwicklern jedoch große |Freiheit bei der Erstellung von Nachrichteninhalt und hohe Flexibilität bei |der Definition von Auslöse-Aktionen. Wie bei anderen Verfahren müssen |auch bei der Verwendung von Auslösern die Häufigkeit der Ausführung und die |diesbezüglichen Kosten berücksichtigt werden. Die folgenden Beispiele |veranschaulichen die Verwendung von Auslösern mit den DB2 |MQSeries-Funktionen.
|Das folgende Beispiel zeigt, wie einfach es ist, bei der Einstellung eines |neuen Mitarbeiters eine Nachricht zu veröffentlichen. Alle Benutzer |oder Anwendungen, die am Service HR_INFO_PUB teilnehmen und sich für NEW_EMP |registrieren, erhalten eine Nachricht mit dem Einstellungsdatum, dem Namen und |der Abteilung des neuen Mitarbeiters.
|Beispiel 28:
|CREATE TRIGGER neuer_mitarbeiterAFTER INSERT ON employee REFERENCING NEW AS n | FOR EACH ROW MODE DB2SQL | VALUES DB2MQ.MQPUBLISH('HR_INFO_PUB&', 'NEW_EMP', | current date || ' ' || LASTNAME || ' ' || DEPARTMENT)