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.
In diesem Thema werden Richtlinien zur Optimierung der Leistung von Pipelines in einer BizTalk Server-Lösung beschrieben.
Bewährte Methoden zum Optimieren der Leistung von BizTalk Server-Pipelines
Da Pipelinekomponenten erhebliche Auswirkungen auf die Leistung haben (z. B. führt eine Pass-Through-Pipelinekomponente bis zu 30 Prozent besser aus als eine XML-Assembler-/Disassemblerpipelinekomponente), stellen Sie sicher, dass alle benutzerdefinierten Pipelinekomponenten optimal ausgeführt werden, bevor sie in Ihrer Bereitstellung implementiert werden. Minimieren Sie die Anzahl der Pipelinekomponenten in Ihren benutzerdefinierten Pipelines, wenn Sie die Gesamtleistung Ihrer BizTalk-Anwendung maximieren möchten.
Sie können auch die Gesamtleistung verbessern, indem Sie die Nachrichtenpersistenzhäufigkeit in Ihrer Pipelinekomponente verringern und die Komponente codieren, um Redundanz zu minimieren. Jede benutzerdefinierte Assembly und insbesondere Artefakte, die möglicherweise die Leistung beeinträchtigen könnten, wie z. B. benutzerdefinierte Tracking-Komponenten, sollten separat unter hoher Belastung getestet werden, um ihr Verhalten zu beobachten, wenn das System unter voller Kapazitätsauslastung läuft und um mögliche Engpässe zu identifizieren.
Wenn Sie die eingehende Nachricht in einer Pipelinekomponente lesen müssen, vermeiden Sie das Laden des gesamten Dokuments in den Arbeitsspeicher mithilfe eines XmlDocument-Objekts . Der von einer Instanz der XmlDocument-Klasse zum Laden und Erstellen einer Speicherdarstellung eines XML-Dokuments erforderliche Speicherplatz beträgt bis zu 10 Mal die tatsächliche Nachrichtengröße. Um eine Nachricht zu lesen, sollten Sie ein XmlTextReader-Objekt zusammen mit einer Instanz der folgenden Klassen verwenden:
VirtualStream (Microsoft.BizTalk.Streaming.dll) – Der Quellcode für diese Klasse befindet sich an zwei Speicherorten unter dem Pipelines SDK wie folgt: SDK\Samples\Pipelines\ArbitraryXPathPropertyHandler und SDK\Samples\Pipelines\SchemaResolverComponent\SchemaResolverFlatFileDasm.
ReadOnlySeekableStream (Microsoft.BizTalk.Streaming.dll).
SeekAbleReadOnlyStream – Der Quellcode für diese Klasse befindet sich an zwei Speicherorten unter dem Pipelines SDK wie folgt: SDK\Samples\Pipelines\ArbitraryXPathPropertyHandler und SDK\Samples\Pipelines\SchemaResolverComponent\SchemaResolverFlatFileDasm.
Verwenden Sie die PassThruReceive- und passThruTransmit-Standardpipelinen, wenn möglich. Sie enthalten keine Pipelinekomponente und führen keine Verarbeitung der Nachricht durch. Aus diesem Grund stellen sie eine maximale Leistung beim Empfangen oder Senden von Nachrichten sicher. Sie können eine PassThruReceive-Pipeline an einem Empfangsort verwenden, wenn Sie ein Binärdokument in die BizTalk MessageBox veröffentlichen müssen, und eine PassThruTransmit-Pipeline an einem Ausgangsort, wenn Sie eine Binärnachricht versenden müssen. Sie können die PassThruTransmit-Pipeline auch auf einem physischen Sendeport verwenden, der an eine Orchestrierung gebunden ist, wenn die Nachricht formatiert wurde und zur Übertragung bereit ist. Sie müssen einen anderen Ansatz verwenden, wenn Sie eine der folgenden Aktionen ausführen müssen:
Eigenschaften im Kontext einer eingehenden XML- oder Flat File-Nachricht bewerben.
Wenden Sie eine Karte innerhalb eines Empfangsstandorts an.
Wenden Sie eine Karte in einer Orchestrierung an, die eine Nachricht abonniert.
Wenden Sie ein Mapping auf einem Sendport an, der eine Nachricht empfängt.
Um eine dieser Aktionen auszuführen, müssen Sie den Dokumenttyp in der Empfangspipeline prüfen und ermitteln und den Wert (namespace#root-name) der MessageType-Kontexteigenschaft zuweisen. Dieser Vorgang wird in der Regel durch eine Zerlegungskomponente wie die Xml-Disassemblerkomponente (XmlDasmComp) oder die Flat File Disassembler-Komponente (FFDasmComp) erreicht. In diesem Fall müssen Sie eine Standardpipeline (z. B. XmlReceive-Pipeline) oder eine benutzerdefinierte Pipeline verwenden, die einen Standard oder eine benutzerdefinierte Disassemblierkomponente enthält.
Erwerben Sie Ressourcen so spät wie möglich, und geben Sie sie so früh wie möglich frei. Wenn Sie beispielsweise auf Daten in einer Datenbank zugreifen müssen, öffnen Sie die Verbindung so spät wie möglich, und schließen Sie sie so schnell wie möglich. Verwenden Sie die C#-Anweisung, um einwegbare Objekte implizit freizugeben, oder den endgültigen Block einer try-catch-finally-Anweisung, um Ihre Objekte explizit zu löschen. Instrumentieren Sie Ihren Quellcode, damit Ihre Komponenten einfach zu debuggen sind.
Entfernen Sie alle Komponenten aus Ihren Pipelines, die nicht unbedingt erforderlich sind, um die Nachrichtenverarbeitung zu beschleunigen.
Innerhalb einer Empfangspipeline sollten Sie Elemente nur dann in den Nachrichtenkontext höher stufen, wenn sie für das Nachrichtenrouting (Orchestrationen, Sendeports) oder die Herabstufung von Nachrichtenkontexteigenschaften (Sendeports) erforderlich sind.
Wenn Sie Metadaten in eine Nachricht einschließen müssen und die Metadaten nicht für Routing- oder Herabstufungszwecke verwenden, verwenden Sie die IBaseMessageContext.Write-Methode anstelle der IBaseMessageContext.Promote-Methode .
Wenn Sie Informationen aus einer Nachricht mit einem XPath-Ausdruck extrahieren müssen, vermeiden Sie das Laden des gesamten Dokuments in den Arbeitsspeicher mithilfe eines XmlDocument-Objekts , um nur die SelectNodes - oder SelectSingleNode-Methoden zu verwenden. Verwenden Sie alternativ die unter "Optimieren der Speicherauslastung mit Streaming" beschriebenen Techniken.
Verwenden des Streamings, um den erforderlichen Speicherbedarf beim Laden von Nachrichten in Pipelines zu minimieren
Die folgenden Techniken beschreiben, wie Sie den Speicherbedarf einer Nachricht beim Laden der Nachricht in eine Pipeline minimieren.
Verwenden von ReadOnlySeekableStream und VirtualStream zum Verarbeiten einer Nachricht aus einer Pipelinekomponente
Es wird als bewährte Methode angesehen, um das Laden der gesamten Nachricht in den Arbeitsspeicher innerhalb von Pipelinekomponenten zu vermeiden. Ein bevorzugter Ansatz besteht darin, den eingehenden Datenstrom mit einer benutzerdefinierten Streamimplementierung umzuschließen, und dann, wenn Leseanforderungen vorgenommen werden, liest die benutzerdefinierte Streamimplementierung den zugrunde liegenden, umschlossenen Datenstrom und verarbeitet die Daten während des Lesens (reines Streaming). Dies kann sehr schwer zu implementieren sein und ist möglicherweise nicht möglich, je nachdem, was mit dem Datenstrom getan werden muss. Verwenden Sie in diesem Fall die Von der Microsoft.BizTalk.Streaming.dllverfügbar gemachten ReadOnlySeekableStream - und VirtualStream-Klassen . Eine Implementierung dieser Elemente wird auch in Arbitrary XPath Property Handler (BizTalk Server Sample) (https://go.microsoft.com/fwlink/?LinkId=160069) im BizTalk SDK bereitgestellt.ReadOnlySeekableStream stellt sicher, dass der Cursor am Anfang des Datenstroms neu positioniert werden kann. Der VirtualStream verwendet einen MemoryStream intern, es sei denn, die Größe liegt über einem angegebenen Schwellenwert, in diesem Fall schreibt er den Datenstrom in das Dateisystem. Die Kombination dieser beiden Datenströme (unter Verwendung von VirtualStream als persistenten Speicher für ReadOnlySeekableStream) bietet sowohl Suchfunktionalität als auch die Möglichkeit, auf das Dateisystem überzulaufen. Dies ermöglicht die Verarbeitung großer Nachrichten, ohne die gesamte Nachricht in den Arbeitsspeicher zu laden. Der folgende Code kann in einer Pipelinekomponente verwendet werden, um diese Funktionalität zu implementieren.
int bufferSize = 0x280;
int thresholdSize = 0x100000;
Stream vStream = new VirtualStream(bufferSize, thresholdSize);
Stream seekStream = new ReadOnlySeekableStream(inboundStream, vStream, bufferSize);
Dieser Code stellt einen "Überlaufschwellenwert" bereit, indem Puffergröße- und Schwellenwertgröße-Variablen für jeden Empfangsort oder jede Sendeportkonfiguration verfügbar gemacht werden. Dieser Überlaufschwellenwert kann dann von Entwicklern oder Administratoren für verschiedene Nachrichtentypen und unterschiedliche Konfigurationen angepasst werden (z. B. 32-Bit im Vergleich zu 64-Bit).
Verwenden von XPathReader und XPathCollection zum Extrahieren eines bestimmten IBaseMessage-Objekts aus einer benutzerdefinierten Pipelinekomponente.
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.
Hinweis
Bei kleineren Nachrichten bietet die Verwendung eines XmlDocument mit SelectNodes oder SelectSingleNode möglicherweise eine bessere Leistung als die Verwendung von XPathReader, aber XPathReader ermöglicht Es Ihnen, ein flaches Speicherprofil für Ihre Anwendung beizubehalten.
In diesem Beispiel wird gezeigt, wie Sie mithilfe von XPathReader und XPathCollection ein bestimmtes IBaseMessage-Objekt aus einer benutzerdefinierten Pipelinekomponente extrahieren.
public IBaseMessage Execute(IPipelineContext context, IBaseMessage message)
{
try
{
...
IBaseMessageContext messageContext = message.Context;
if (string.IsNullOrEmpty(xPath) && string.IsNullOrEmpty(propertyValue))
{
throw new ArgumentException(...);
}
IBaseMessagePart bodyPart = message.BodyPart;
Stream inboundStream = bodyPart.GetOriginalDataStream();
VirtualStream virtualStream = new VirtualStream(bufferSize, thresholdSize);
ReadOnlySeekableStream readOnlySeekableStream = new ReadOnlySeekableStream(inboundStream, virtualStream, bufferSize);
XmlTextReader xmlTextReader = new XmlTextReader(readOnlySeekableStream);
XPathCollection xPathCollection = new XPathCollection();
XPathReader xPathReader = new XPathReader(xmlTextReader, xPathCollection);
xPathCollection.Add(xPath);
bool ok = false;
while (xPathReader.ReadUntilMatch())
{
if (xPathReader.Match(0) && !ok)
{
propertyValue = xPathReader.ReadString();
messageContext.Promote(propertyName, propertyNamespace, propertyValue);
ok = true;
}
}
readOnlySeekableStream.Position = 0;
bodyPart.Data = readOnlySeekableStream;
}
catch (Exception ex)
{
if (message != null)
{
message.SetErrorInfo(ex);
}
...
throw ex;
}
return message;
}
Verwenden von XMLReader und XMLWriter mit XMLTranslatorStream zum Verarbeiten einer Nachricht aus einer Pipelinekomponente
Eine weitere Methode für die Implementierung einer benutzerdefinierten Pipelinekomponente, die einen Streamingansatz verwendet, besteht darin, die .NET XmlReader - und XmlWriter-Klassen in Verbindung mit der von BizTalk Server bereitgestellten XmlTranslatorStream-Klasse zu verwenden. Beispielsweise erbt die NamespaceTranslatorStream-Klasse , die in der Assembly "Microsoft.BizTalk.Pipeline.Components" enthalten ist, von XmlTranslatorStream und kann verwendet werden, um einen alten Namespace durch einen neuen Namespace im XML-Dokument zu ersetzen, das im Datenstrom enthalten ist. Um diese Funktionalität in einer benutzerdefinierten Pipelinekomponente zu verwenden, können Sie den ursprünglichen Datenstrom des Nachrichtentextteils mit einer neuen Instanz der NamespaceTranslatorStream-Klasse umschließen und letztere zurückgeben. Auf diese Weise wird die eingehende Nachricht nicht innerhalb der Pipelinekomponente gelesen oder verarbeitet, sondern nur, wenn der Datenstrom von einer nachfolgenden Komponente in derselben Pipeline gelesen wird oder schließlich vom Nachrichten-Agent verwendet wird, bevor das Dokument im BizTalk Server MessageBox veröffentlicht wird.
Im folgenden Beispiel wird die Verwendung dieser Funktion veranschaulicht.
public IBaseMessage Execute(IPipelineContext context, IBaseMessage message)
{
IBaseMessage outboundMessage = message;
try
{
if (context == null)
{
throw new ArgumentException(Resources.ContextIsNullMessage);
}
if (message == null)
{
throw new ArgumentException(Resources.InboundMessageIsNullMessage);
}
IBaseMessagePart bodyPart = message.BodyPart;
Stream stream = new NamespaceTranslatorStream(context,
bodyPart.GetOriginalDataStream(),
oldNamespace,
newNamespace);
context.ResourceTracker.AddResource(stream);
bodyPart.Data = stream;
}
catch (Exception ex)
{
if (message != null)
{
message.SetErrorInfo(ex);
}
throw ex;
}
return outboundMessage;
}
Verwenden von ResourceTracker in benutzerdefinierten Pipelinekomponenten
Eine Pipelinekomponente sollte die Lebensdauer der von ihr erstellten Objekte verwalten und die Garbage Collection ausführen, sobald diese Objekte nicht mehr benötigt werden. Wenn die Pipelinekomponente möchte, dass die Lebensdauer der Objekte bis zum Ende der Pipelineausführung reicht, müssen Sie solche Objekte der Ressourcenverfolgung hinzufügen, die Ihre Pipeline aus dem Pipelinekontext abrufen kann.
Die Ressourcenverfolgung wird für die folgenden Objekttypen verwendet:
Stream-Objekte
COM-Objekte
IDisposable-Objekte
Das Nachrichtenmodul stellt sicher, dass alle systemeigenen Ressourcen, die der Ressourcenüberwachung hinzugefügt werden, zu einem geeigneten Zeitpunkt freigegeben werden, d. h., nachdem die Pipeline vollständig ausgeführt wurde, unabhängig davon, ob sie erfolgreich war oder fehlgeschlagen ist. Die Lebensdauer der Resource Tracker-Instanz und der Objekte, die nachverfolgt werden, wird vom Pipelinekontextobjekt verwaltet. Der Pipelinekontext wird allen Typen von Pipelinekomponenten über ein Objekt zur Verfügung gestellt, das die IPipelineContext-Schnittstelle implementiert.
Der folgende Codeausschnitt ist beispielsweise ein Beispiel, das veranschaulicht, wie Die ResourceTracker-Eigenschaft in benutzerdefinierten Pipelinekomponenten verwendet wird. Um die ResourceTracker-Eigenschaft zu verwenden, verwendet der Codeausschnitt den folgenden Parameter
IPipelineContext.ResourceTracker.AddResource
. In diesem Parameter:Die IPipelineContext-Schnittstelle definiert die Methoden, die für den Zugriff auf alle dokumentverarbeitungsspezifischen Schnittstellen verwendet werden.
Die ResourceTracker-Eigenschaft verweist auf IPipelineContext und wird verwendet, um Objekte nachzuverfolgen, die am Ende der Pipelineverarbeitung explizit verworfen werden.
ResourceTracker.AddResource-Methode wird verwendet, um COM-Objekte, Einwegobjekte und Datenströme nachzuverfolgen und sollte immer innerhalb einer benutzerdefinierten Pipelinekomponente verwendet werden, um diese Typen von Ressourcen explizit zu schließen (Datenströme), verwerfen (IDisposable-Objekte) oder freigeben (COM-Objekte), wenn eine Nachricht in BizTalk MessageBox veröffentlicht wird.
public IBaseMessage Execute(IPipelineContext pContext, IBaseMessage pInMsg)
{
IBaseMessage outMessage = pContext.GetMessageFactory().CreateMessage();
IBaseMessagePart outMsgBodyPart = pContext.GetMessageFactory().CreateMessagePart();
outMsgBodyPart.Charset = Encoding.UTF8.WebName;
outMsgBodyPart.ContentType = "text/xml";
//Code to load message content in the MemoryStream object//
MemoryStream messageData = new MemoryStream();
//The MemoryStream needs to be closed after the whole pipeline has executed, thus adding it into ResourceTracker//
pContext.ResourceTracker.AddResource(messageData);
//Custom pipeline code to load message data into xmlPayload//
XmlDocument xmlPayLoad = new XmlDocument();
xmlPayLoad.Save(messageData);
messageData.Seek(0, SeekOrigin.Begin);
//The new stream is assigned to the message part’s data//
outMsgBodyPart.Data = messageData;
// Pipeline component logic here//
return outMessage;
}
Vergleich des Ladens von Nachrichten in Pipelines mithilfe eines In-Memory-Ansatzes und eines Streaming-Ansatzes.
Die folgenden Informationen wurden aus dem Blog http://blogs.objectsharp.com/cs/blogs/nbarden/archive/2008/04/14/developing-streaming-pipeline-components-part-1.aspx von Nic Barden (https://go.microsoft.com/fwlink/?LinkId=160228) entnommen. Diese Tabelle bietet einen zusammenfassenden Vergleich des Ladens von Nachrichten in Pipelines mithilfe eines Speicheransatzes und eines Streamingansatzes.
Vergleich von... | Streamen | Im Arbeitsspeicher |
---|---|---|
Speicherauslastung pro Nachricht | Niedrig, unabhängig von der Nachrichtengröße | Hoch (variiert je nach Nachrichtengröße) |
Allgemeine Klassen zum Verarbeiten von XML-Daten | Integrierte und benutzerdefinierte Ableitungen von: XmlTranslatorStream, XmlReader und XmlWriter |
XmlDocument, XPathDocument, MemoryStream und VirtualStream |
Dokumentation | Schlecht – viele nicht unterstützte und nicht dokumentierte BizTalk-Klassen | Sehr gut - .NET Framework-Klassen |
Speicherort des Codes "Verarbeitungslogik" | - Leser und Datenströme über die Execute-Methode verbinden. – Die tatsächliche Ausführung erfolgt in den Lesern und Datenströmen, während die Daten gelesen werden. |
Direkt aus der Execute-Methode der Pipelinekomponente. |
Daten | Wird bei jeder Umbruchebene neu erstellt, während Daten durch sie gelesen werden. | Einlesen, ändern und schreiben bei jeder Komponente, bevor die nächste Komponente aufgerufen wird. |