Partager via


Optimisation de l’utilisation de la mémoire avec streaming

Cette rubrique fournit des recommandations sur l’utilisation de modèles de diffusion en continu pour réduire l’empreinte mémoire des messages lors de l’envoi ou de la réception de messages volumineux avec un transport WCF ou lors du chargement de messages dans des orchestrations.

Lorsque vous utilisez du code dans une orchestration pour lire le contenu d’un message, évitez d’utiliser des variables XmlDocument. Le chargement d’un message dans une variable XmlDocument entraîne une surcharge importante, en particulier pour les messages volumineux. Cette surcharge est liée à l’utilisation et au traitement de la mémoire pour générer les structures en mémoire. L’utilisation d’une instance XmlDocument force le chargement de l’intégralité du contenu du message en mémoire afin de générer le graphique d’objet pour le module DOM (Document Object Module). La quantité totale de mémoire utilisée par une instance de cette classe peut être d’environ 10 fois la taille réelle du message. Pour plus d’informations sur l’empreinte mémoire requise lors du chargement d’un message dans une variable XmlDocument, consultez le chapitre 9 – Amélioration des performances XML.

Le reste de cette rubrique fournit d’autres méthodes pour lire le contenu du message qui ne nécessitent pas de chargement d’un message dans une variable XmlDocument.

Utiliser la diffusion en continu lors de l’envoi ou de la réception de messages volumineux avec un transport WCF

Lors de l’envoi ou de la réception de messages volumineux avec un transport WCF, utilisez l’adaptateur WCF-Custom ou WCF-CustomIsolated et configurez avec un type de liaison qui prend en charge l’option transferMode = Streamed , comme les liaisons suivantes :

  • basicHttpBinding + BasicHttpBindingElement, mode de transfert = en continu

  • netTcpBinding + NetTcpBindingElement, transferMode = Streamed

  • customBinding + HttpTransportElement, mode de transfert = Streamed

  • customBinding + ConnectionOrientedTransportElement, mode de transfert = Streamed

    Le choix d’une carte WCF-Custom ou WCF-CustomIsolated avec une liaison qui prend en charge l’option transferMode = Streamed implémente la diffusion en continu de messages volumineux vers le système de fichiers en fonction des besoins, et atténue les problèmes potentiels de mémoire insuffisante.

Utiliser la diffusion en continu pour réduire l’empreinte mémoire requise lors du chargement des messages dans des orchestrations

Les techniques suivantes décrivent comment réduire l’empreinte mémoire d’un message lors du chargement du message dans une orchestration.

Utiliser une variable XLANGMessage pour traiter le contenu d’un message ou d’une partie de message

Lors du passage d’un message à partir d’une orchestration vers des bibliothèques de classes .NET, ne les transmettez pas en tant que variables XmlDocument, pour des raisons mentionnées précédemment dans cette rubrique ; utilisez plutôt des variables XLANGMessage. Les techniques suivantes illustrent les méthodes de lecture d’un message ou d’une partie de message à l’aide d’une variable XLANGMessage.

  • Traiter les messages avec XMLReader : pour traiter un message avec une instance XmlReader, passez le message au code .NET en tant que XLANGMessage et récupérez le contenu du composant à l’aide de XmlReader.

    public void ProcessMessage(XLANGMessage message)
    {
        try
        {
            using (XmlReader reader = message[0].RetrieveAs(typeof(XmlReader)) as XmlReader)
            if (reader != null)
            {
                ...
            }
        }
        finally
        {
            message.Dispose();
        }
    }
    
  • Récupérer le contenu d’un message dans une chaîne avec StreamReader : l’une des utilisations courantes de XmlDocument dans les orchestrations consiste à récupérer le message sous forme de chaîne XML à l’aide de XmlDocument.OuterXml(). L’exemple de code suivant illustre une autre méthode qui récupère le message sous forme de chaîne à l’aide d’une variable XLANGMessage.

    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;
    }
    
  • Récupérez le contenu des messages .NET simples dans une chaîne : si le type du message est un type .NET simple, vous pouvez récupérer le message comme ce type. Par exemple, pour obtenir le message sous forme de chaîne, transmettez le message au code .NET en tant que XLANGMessage et récupérez le contenu du composant sous forme de chaîne.

    public void ProcessMessage(XLANGMessage message)
    {
        try
        {
            string content = message[0].RetrieveAs(typeof(string)) as string;
            if (!string.IsNullOrEmpty(content))
            {
                ...
            }
        }
        finally
        {
            message.Dispose();
        }
    }
    
  • Récupérez le contenu d’un message dans un flux : pour obtenir le message en tant que flux, transmettez le message au code .NET en tant que XLANGMessage et récupérez le contenu du composant en tant que flux.

    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;
    }
    
  • Récupérez le contenu d’un message dans un objet .NET : pour obtenir le message en tant qu’objet .NET, transmettez le message au code .NET en tant que XLANGMessage et récupérez le contenu du composant en tant qu’instance d’une classe .NET. Créez cette dernière à partir du schéma XML du message à l’aide de l’outil XML Schema Definition Tool (Xsd.exe) fourni par Visual Studio 2010.

    Remarque

    Cette technique est valide uniquement lorsque les messages sont petits. Dans le cas contraire, cette approche peut entraîner une surcharge importante pour dé-sérialiser le message réel dans un objet .NET.

    public void ProcessMessage(XLANGMessage message)
    {
        try
          {
          Request request = message[0].RetrieveAs(typeof(Request)) as Request;
          if (request != null)
          {
             ...
          }
       }
       finally
       {
          message.Dispose();
       }
    
    }
    

Remarque

L'utilisation de la méthode Dispose(), exposée par le paramètre XLANGMessage, avant de revenir du code .NET, est particulièrement importante dans les scénarios de boucles et les orchestrations longues. Ces situations peuvent entraîner l'accumulation d'instances de l'objet XLANGMessage sans qu'elles soient libérées au fil du temps. Pour plus d'informations sur l'appel de la méthode message.Dispose() de cette manière, consultez Messages représentés en tant que XLANGMessage dans la documentation BizTalk Server. Cette rubrique fournit également les meilleures pratiques d’utilisation d’IStreamFactory pour construire des variables XLANGMessage dans le code utilisateur à l’aide d’une approche basée sur le flux.

Pour plus d’informations sur les différentes façons de traiter un XLANGMessage dans un composant d’assistance appelé par une orchestration, consultez les rubriques suivantes :

Utilisation de XPathReader et XPathCollection pour extraire une valeur d’un objet XLANGMessage à partir d’une méthode appelée par une orchestration

Évitez d’utiliser la classe XMLDocument pour lire le contenu des messages XML à partir de code personnalisé, tels que des composants de pipeline personnalisés ou des classes d’assistance appelées par des orchestrations. Lors de l’utilisation d’une instance XMLDocument pour charger un message XML, le message entier est chargé en mémoire, ce qui est inefficace et peut nécessiter de la mémoire jusqu’à 10 fois la taille réelle du message. Un moyen plus efficace de lire le contenu des messages XML consiste à utiliser une technique de diffusion en continu pour encapsuler le flux d’origine avec l’une des classes de flux fournies par l’assembly Microsoft.BizTalk.Streaming.dll. Cette technique est particulièrement utile lors du chargement de messages volumineux.

Si des valeurs spécifiques doivent être extraites d’un document XML, au lieu d’utiliser les méthodes SelectNodes et SelectSingleNode exposées par la classe XmlDocument, utilisez une instance de la classe XPathReader fournie par l’assembly Microsoft.BizTalk.XPathReader.dll, comme illustré dans l’exemple de code suivant.

  • Cet exemple illustre l’utilisation de XPathReader et XPathCollection pour extraire une valeur donnée d’un objet XLANGMessage à l’intérieur d’une méthode appelée par une orchestration.

    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;
    }
    

Voir aussi

Optimisation des applications BizTalk Server