Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Dieses Thema enthält Empfehlungen für die Verwendung von Streamingmustern, um den Speicherbedarf von Nachrichten beim Senden oder Empfangen großer Nachrichten mit einem WCF-Transport oder beim Laden von Nachrichten in Orchestrierungen zu minimieren.
Wenn Sie Code in einer Orchestrierung verwenden, um den Inhalt einer Nachricht zu lesen, vermeiden Sie die Verwendung von XmlDocument-Variablen. Das Laden einer Nachricht in eine XmlDocument-Variable verursacht erheblichen Aufwand, insbesondere für große Nachrichten. Dieser Aufwand bezieht sich auf die Speicherauslastung und -verarbeitung, um die In-Memory-Strukturen zu erstellen. Die Verwendung einer XmlDocument-Instanz erzwingt das Laden des gesamten Nachrichteninhalts in den Arbeitsspeicher, um das Objektdiagramm für das Document Object Module (DOM) zu erstellen. Die Gesamtmenge des von einer Instanz dieser Klasse verwendeten Arbeitsspeichers kann etwa 10 Mal die tatsächliche Nachrichtengröße betragen. Weitere Informationen zum erforderlichen Speicherbedarf beim Laden einer Nachricht in eine XmlDocument-Variable finden Sie in Kapitel 9 – Verbessern der XML-Leistung.
Im restlichen Teil dieses Themas finden Sie alternative Methoden zum Lesen von Nachrichteninhalten, für die kein Laden einer Nachricht in eine XmlDocument-Variable erforderlich ist.
Verwenden von Streaming beim Senden oder Empfangen großer Nachrichten mit einem WCF-Transport
Verwenden Sie beim Senden oder Empfangen großer Nachrichten mit einem WCF-Transport den WCF-Custom- oder WCF-CustomIsolated-Adapter und konfigurieren Sie mit einem Bindungstyp, der die Option transferMode = Streamed unterstützt, z. B. die folgenden Bindungen:
basicHttpBinding + BasicHttpBindingElement, Übertragungsmodus = Gestreamt
netTcpBinding + NetTcpBindingElement, Übertragungsmodus = gestreamt
customBinding + HttpTransportElement, transferMode = Streamed
customBinding +ConnectionOrientedTransportElement, transferMode = Streamed
Wenn Sie einen WCF-Custom- oder WCF-CustomIsolated-Adapter auswählen, zusammen mit einer Bindung, die die Option transferMode = Streamed unterstützt, wird das Streamen großer Nachrichten nach Bedarf in das Dateisystem implementiert und potenzielle Out-of-Memory-Probleme verringert.
Verwenden von Streaming, um den Speicherbedarf zu minimieren, der beim Laden von Nachrichten in Orchestrierungen erforderlich ist
Die folgenden Techniken beschreiben, wie Sie den Speicherbedarf einer Nachricht beim Laden der Nachricht in eine Orchestrierung minimieren.
Verwenden einer XLANGMessage-Variablen zum Verarbeiten des Inhalts einer Nachricht oder eines Nachrichtenteils
Wenn Sie eine Nachricht aus einer Orchestrierung an .NET-Klassenbibliotheken übergeben, übergeben Sie sie nicht als XmlDocument-Variablen, aus gründen, die weiter oben in diesem Thema erwähnt wurden; Verwenden Sie stattdessen XLANGMessage-Variablen. Die folgenden Techniken veranschaulichen Methoden zum Lesen einer Nachricht oder eines Nachrichtenteils mithilfe einer XLANGMessage-Variablen.
Verarbeiten von Nachrichten mit XMLReader – Um eine Nachricht mit einer XmlReader-Instanz zu verarbeiten, übergeben Sie die Nachricht als XLANGMessage an .NET-Code, und rufen Sie den Teilinhalt mithilfe von XmlReader ab.
public void ProcessMessage(XLANGMessage message) { try { using (XmlReader reader = message[0].RetrieveAs(typeof(XmlReader)) as XmlReader) if (reader != null) { ... } } finally { message.Dispose(); } }Abrufen des Inhalts einer Nachricht in eine Zeichenfolge mit StreamReader – Eine der allgemeinen Verwendungen von XmlDocument in Orchestrierungen besteht darin, die Nachricht als XML-Zeichenfolge mithilfe von XmlDocument.OuterXml() abzurufen. Im folgenden Codebeispiel wird eine alternative Methode veranschaulicht, mit der die Nachricht als Zeichenfolge mithilfe einer XLANGMessage-Variablen abgerufen wird.
public static string MessageToString(XLANGMessage message) { string strResults; try { using (Stream stream = message[0].RetrieveAs(typeof(Stream)) as Stream) { using (StreamReader reader = new StreamReader(stream)) { strResults = reader.ReadToEnd(); } } } finally { message.Dispose(); } return strResults; }Abrufen des Inhalts einfacher .NET-Nachrichten in eine Zeichenfolge – Wenn der Typ der Nachricht ein einfacher .NET-Typ ist, können Sie die Nachricht als diesen Typ abrufen. Um beispielsweise die Nachricht als Zeichenfolge abzurufen, übergeben Sie die Nachricht als XLANGMessage an den .NET-Code, und rufen Sie den Teilinhalt als Zeichenfolge ab.
public void ProcessMessage(XLANGMessage message) { try { string content = message[0].RetrieveAs(typeof(string)) as string; if (!string.IsNullOrEmpty(content)) { ... } } finally { message.Dispose(); } }Abrufen des Inhalts einer Nachricht in einen Datenstrom – Um die Nachricht als Datenstrom abzurufen, übergeben Sie die Nachricht als XLANGMessage an den .NET-Code, und rufen Sie den Teilinhalt als Datenstrom ab.
public Stream ProcessRequestReturnStream(XLANGMessage message, int bufferSize, int thresholdSize) { ... try { using (VirtualStream virtualStream = new VirtualStream(bufferSize, thresholdSize)) { using (Stream partStream = (Stream)message[0].RetrieveAs(typeof(Stream))) //Note that when calling this code, if the XmlDocument is quite large, keeping it in a memory with a MemoryStream may have an adverse effect on performance. //In this case, it may be worthwhile to consider an approach that uses a VirtualStream + ReadonlySeekableStream to buffer it to the file system, if its size is bigger than the thresholdSize parameter. //Keep in mind that: // - If the message size is smaller than the threshold size, the VirtualStream class buffers the stream to a MemoryStream. // - If the message size is bigger than the threshold size, the VirtualStream class buffers the stream to a temporary file. using (ReadOnlySeekableStream readOnlySeekableStream = new ReadOnlySeekableStream(partStream, virtualStream, bufferSize)) { using (XmlReader reader = XmlReader.Create(readOnlySeekableStream)) { } } } } } catch (Exception ex) { } finally { message.Dispose(); } return stream; }Abrufen des Inhalts einer Nachricht in ein .NET-Objekt – Um die Nachricht als .NET-Objekt abzurufen, übergeben Sie die Nachricht als XLANGMessage an den .NET-Code, und rufen Sie den Teilinhalt als Instanz einer .NET-Klasse ab. Erstellen Sie dies anhand des XML-Schemas der Nachricht mithilfe des xml-Schemadefinitionstools (Xsd.exe), das von Visual Studio 2010 bereitgestellt wird.
Hinweis
Diese Technik ist nur gültig, wenn Nachrichten klein sind. Andernfalls könnte dieser Ansatz zu einem erheblichen Mehraufwand führen, um die tatsächliche Nachricht in ein .NET-Objekt zu deserialisieren.
public void ProcessMessage(XLANGMessage message) { try { Request request = message[0].RetrieveAs(typeof(Request)) as Request; if (request != null) { ... } } finally { message.Dispose(); } }
Hinweis
Die Verwendung der Dispose()-Methode, die vom XLANGMessage-Parameter verfügbar gemacht wird, bevor aus dem .NET-Code zurückgekehrt wird, ist besonders wichtig in Schleifenszenarien und lang laufenden Orchestrierungen, in denen Instanzen des XLANGMessage-Objekts angesammelt werden können, ohne sie im Laufe der Zeit freizugeben. Weitere Informationen über das Aufrufen von message.Dispose() in dieser Art finden Sie in der BizTalk Server-Dokumentation unter "Nachrichten dargestellt als XLANGMessage". Dieses Thema enthält außerdem bewährte Methoden für die Verwendung von IStreamFactory zum Erstellen von XLANGMessage-Variablen im Benutzercode mithilfe eines streambasierten Ansatzes.
Weitere Informationen zu den verschiedenen Verfahren zum Verarbeiten einer XLANGMessage in einer Hilfskomponente, die von einer Orchestrierung aufgerufen wird, finden Sie in den folgenden Themen:
4 Verschiedene Möglichkeiten zum Verarbeiten einer XLANGMessage in einer Hilfskomponente, die von einem Orchestrierungsteil 1 aufgerufen wird (öffnet Blog eines Drittanbieters)
4 Verschiedene Möglichkeiten zum Verarbeiten einer XLANGMessage innerhalb einer Hilfskomponente, die von einem Orchestrierungsteil 2 aufgerufen wird (öffnet Blog von Drittanbietern)
Verwenden von XPathReader und XPathCollection zum Extrahieren eines Werts aus einem XLANGMessage-Objekt aus einer Methode, die von einer Orchestrierung aufgerufen wird
Vermeiden Sie die Verwendung der XMLDocument-Klasse zum Lesen der Inhalte von XML-Nachrichten aus benutzerdefiniertem Code, z. B. benutzerdefinierte Pipelinekomponenten oder Hilfsklassen, die von Orchestrierungen aufgerufen werden. Wenn Sie eine XMLDocument-Instanz zum Laden einer XML-Nachricht verwenden, wird die gesamte Nachricht in den Arbeitsspeicher geladen, was ineffizient ist und bis zu 10 Mal Arbeitsspeicher für die tatsächliche Größe der Nachricht benötigt. Eine effizientere Möglichkeit zum Lesen des Inhalts von XML-Nachrichten ist die Verwendung einer Streamingtechnik zum Umschließen des ursprünglichen Datenstroms mit einer der Von der Microsoft.BizTalk.Streaming.dll-Assembly bereitgestellten Streamklassen. Diese Technik ist besonders hilfreich beim Laden großer Nachrichten.
Wenn bestimmte Werte aus einem XML-Dokument abgerufen werden müssen, verwenden Sie anstelle der selectNodes- und SelectSingleNode-Methoden, die von der XmlDocument-Klasse verfügbar gemacht werden, eine Instanz der XPathReader-Klasse, die von der Microsoft.BizTalk.XPathReader.dll-Assembly bereitgestellt wird, wie im folgenden Codebeispiel dargestellt.
In diesem Beispiel wird die Verwendung von XPathReader und XPathCollection veranschaulicht, um einen bestimmten Wert aus einem XLANGMessage-Objekt innerhalb einer von einer Orchestrierung aufgerufenen Methode zu extrahieren.
public static string SelectSingleNode(XLANGMessage message, string xPath) { try { if (message == null || string.IsNullOrEmpty(xPath)) { return string.Empty; } using (XmlReader reader = (XmlReader)message[0].RetrieveAs(typeof(XmlReader))) { XPathCollection xPathCollection = new XPathCollection(); XPathReader xPathReader = new XPathReader(reader, xPathCollection); xPathCollection.Add(xPath); while (xPathReader.ReadUntilMatch()) { if (xPathReader.Match(0)) { return xPathReader.ReadString(); } } } } catch (Exception ex) { ... } finally { message.Dispose(); } return string.Empty; }