Gliederung von Service Broker-Anwendungen
Die meisten Service Broker-Anwendungen führen dieselben grundlegenden Schritte aus, um Nachrichten zu empfangen und zu verarbeiten:
Die Anwendung beginnt eine Transaktion.
Wenn die Anwendung Statusinformationen verwaltet, ruft sie einen Konversationsgruppenbezeichner ab. Die Anwendung verwendet diesen Bezeichner, um den Status anhand einer Statustabelle wiederherzustellen. Falls keine Konversationsgruppe mit empfangsbereiten Nachrichten vorhanden ist, führt die Anwendung einen Rollback für die Transaktion aus und wird dann beendet.
Die Anwendung empfängt eine oder mehrere Nachrichten aus der Warteschlange. Wenn die Anwendung über einen Konversationsgruppenbezeichner verfügt, verwendet sie diesen, um Nachrichten für diese Konversationsgruppe zu empfangen. Falls keine weiteren zu empfangenden Nachrichten verfügbar sind, führt die Anwendung einen Commit für die Transaktion aus und kehrt zu Schritt 1 zurück.
Die Anwendung überprüft den Inhalt der Nachrichten auf der Grundlage des Nachrichtentypnamens.
Die Anwendung verarbeitet die Nachrichten auf der Grundlage des Nachrichtentypnamens und des Nachrichteninhalts.
Die Anwendung sendet alle Nachrichten, die sich aus der Verarbeitung ergeben.
Wenn die Anwendung Statusinformationen verwaltet, aktualisiert sie die Statustabelle und verwendet dabei den Konversationsgruppenbezeichner als Primärschlüssel für die Tabelle.
Die Anwendung kehrt zu Schritt 3 zurück, um zu überprüfen, ob weitere Nachrichten verfügbar sind.
Die genaue Struktur der Anwendung hängt von den Anforderungen und der Kommunikationsweise der Anwendung ab sowie davon, ob es sich bei der Anwendung um einen Zieldienst oder um einen initiierenden Dienst handelt, und ob die Anwendung von Service Broker aktiviert wird.
Eine initiierende Anwendung sendet beispielsweise eine Nachricht, bevor sie die in den Schritten oben beschriebene Verarbeitungsschleife startet. Der initiierende Dienst sendet möglicherweise eine Nachricht aus einem anderen Programm oder einer anderen gespeicherten Prozedur und verwendet dann eine gespeicherte Aktivierungsprozedur für seine zugehörige Warteschlange. Beispielsweise kann eine Anwendung für die Auftragserfassung eine externe Anwendung umfassen, die die Konversation für die Eingabe des Auftrags initiiert. Nach der Auftragseingabe muss die externe Anwendung nicht weiter ausgeführt werden. Eine gespeicherte Aktivierungsprozedur für den initiierenden Dienst sendet die Auftragsbestätigung, sobald eine Antwort vom Auftragsdienst eingeht. Die gespeicherte Aktivierungsprozedur verarbeitet auch alle Service Broker-Fehlermeldungen, die vom Zieldienst zurückgegeben werden, und sendet Benachrichtigungen mit der Information, dass der Auftrag nicht bestätigt werden konnte.
Alternativ kann die initiierende Anwendung auch eine Nachricht senden und dann die Verarbeitungsschleife als Teil desselben Programms starten, anstatt eine Nachricht aus einem anderen Programm zu senden. Unabhängig von diesen Variationen bleibt die grundlegende Gliederung gleich.
Eventuell hält eine Anwendung, die eine große Anzahl von Nachrichten in derselben Konversationsgruppe verarbeitet, die Zahl der empfangenen Nachrichten fest und führt nach der Verarbeitung einer bestimmten Nachrichtenanzahl einen Commit für eine Transaktion aus. Diese Zähl-und-Commit-Strategie ermöglicht es der Anwendung, die Transaktionen nach relativ kurzer Zeit abzuschließen und verschiedene Konversationsgruppen zu verarbeiten.
Beispiel
Durch das folgende Transact-SQL-Beispiel werden alle Nachrichten in der Warteschlange MyServiceQueue verarbeitet. Der Verarbeitungsaufwand für eine Nachricht ist minimal. Wenn es sich bei der Nachricht um eine EndDialog-Nachricht oder um eine Error-Nachricht handelt, beendet der Code die Konversation. Bei allen anderen Nachrichten erstellt der Code eine XML-Darstellung der Nachricht sowie ein Resultset, das das Konversationshandle, den Nachrichtentypnamen und den XML-Code enthält. Wenn 500 Millisekunden lang keine Nachrichten verfügbar sind, wird der Code beendet.
Zur Vereinfachung erzeugt das Skript ein Resultset für jede Nachricht. Falls beim Einlesen der Warteschlange ein Fehler auftritt, führt das Skript einen Commit für die Änderungen aus, ohne dass ein Ergebnis erstellt wird. Deshalb entfernt dieses Skript automatisch alle Nachrichten, die einen Fehler verursachen.
Hinweis |
---|
Da das Skript einfach Nachrichten anzeigt, sind nicht verarbeitbare Nachrichten für dieses Skript ausgeschlossen. Daher enthält das Skript keinen Code zur Behandlung nicht verarbeitbarer Nachrichten. Es sollte eine Produktionsanwendung zur Behandlung nicht verarbeitbarer Nachrichten geschrieben werden. Weitere Informationen zu nicht verarbeitbaren Nachrichten finden Sie unter Behandeln von nicht verarbeitbaren Nachrichten. |
USE AdventureWorks2008R2 ;
GO
-- Process all conversation groups.
WHILE (1 = 1)
BEGIN
DECLARE @conversation_handle UNIQUEIDENTIFIER,
@conversation_group_id UNIQUEIDENTIFIER,
@message_body XML,
@message_type_name NVARCHAR(128);
-- Begin a transaction, one per conversation group.
BEGIN TRANSACTION ;
-- Get next conversation group.
WAITFOR(
GET CONVERSATION GROUP @conversation_group_id FROM MyServiceQueue),
TIMEOUT 500 ;
-- Restore the state for this conversation group here
-- If there are no more conversation groups, break.
IF @conversation_group_id IS NULL
BEGIN
ROLLBACK TRANSACTION ;
BREAK ;
END ;
-- Process all messages in the conversation group.
WHILE 1 = 1
BEGIN
-- Get the next message.
RECEIVE
TOP(1)
@conversation_handle = conversation_handle,
@message_type_name = message_type_name,
@message_body =
CASE
WHEN validation = 'X' THEN CAST(message_body AS XML)
ELSE CAST(N'<none/>' AS XML)
END
FROM MyServiceQueue
WHERE conversation_group_id = @conversation_group_id;
-- If there is no message, or there is an error
-- reading from the queue, break.
IF @@ROWCOUNT = 0 OR @@ERROR <> 0
BREAK;
-- Process the message. In this case, the program ends the conversation
-- for Error and EndDialog messages. For all other messages, the program
-- produces a result set with information about the message.
SELECT @conversation_handle,
@message_type_name,
@message_body ;
-- If the message is an end dialog message or an error,
-- end the conversation. Notice that other conversations
-- in the same conversation group may still have messages
-- to process. Therefore, the program does not break after
-- ending the conversation.
IF @message_type_name =
'https://schemas.microsoft.com/SQL/ServiceBroker/EndDialog'
OR @message_type_name =
'https://schemas.microsoft.com/SQL/ServiceBroker/Error'
BEGIN
END CONVERSATION @conversation_handle ;
END ;
END ; -- Process all messages in conversation group.
COMMIT TRANSACTION ;
END ; -- Process all conversation groups.