Share via


Dépannage de la corrélation

La corrélation est utilisée pour établir une relation entre des messages de service de workflow et avec l'instance de workflow appropriée, mais si elle n'est pas proprement configurée, les messages ne seront pas reçus et les applications ne fonctionneront pas correctement. Cette rubrique fournit une vue d'ensemble de plusieurs méthodes de résolution des problèmes de corrélation et présente certains problèmes courants qui peuvent se produire lorsque vous utilisez la corrélation.

Gérer l'événement UnknownMessageReceived

L'événement UnknownMessageReceived se produit lorsqu'un message inconnu est reçu par un service, notamment les messages qui ne peuvent pas être mis en corrélation avec une instance existante. Pour les services auto-hébergés, cet événement peut être géré dans l'application hôte.

host.UnknownMessageReceived += delegate(object sender, UnknownMessageReceivedEventArgs e)
{
    Console.WriteLine("Unknown Message Received:");
    Console.WriteLine(e.Message);
};

Pour les services hébergés sur le Web, cet événement peut être géré en dérivant une classe de WorkflowServiceHostFactory et en substituant CreateWorkflowServiceHost.

class CustomFactory : WorkflowServiceHostFactory
{
    protected override WorkflowServiceHost CreateWorkflowServiceHost(Activity activity, Uri[] baseAddresses)
    {
        // Create the WorkflowServiceHost.
        WorkflowServiceHost host = new WorkflowServiceHost(activity, baseAddresses);

        // Handle the UnknownMessageReceived event.
        host.UnknownMessageReceived += delegate(object sender, UnknownMessageReceivedEventArgs e)
        {
            Console.WriteLine("Unknown Message Received:");
            Console.WriteLine(e.Message);
        };

        return host;
    }
}

Ce WorkflowServiceHostFactory personnalisé peut ensuite être spécifié dans le fichier svc du service.

<% @ServiceHost Language="C#" Service="OrderServiceWorkflow" Factory="CustomFactory" %>

Lorsque ce gestionnaire est appelé, le message peut être récupéré à l'aide de la propriété Message du UnknownMessageReceivedEventArgs et ressemblera au message suivant.

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <To s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://localhost:8080/OrderService</To>
    <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/IService/AddItem</Action>
  </s:Header>
  <s:Body>
    <AddItem xmlns="http://tempuri.org/">
      <Item>Books</Item>
    </AddItem>
  </s:Body>
</s:Envelope>

L'inspection des messages distribués au gestionnaire UnknownMessageReceived peut fournir des indices permettant de comprendre pourquoi le message n'a pas été mis en corrélation avec une instance du service de workflow.

Utiliser le suivi pour surveiller la progression du workflow

Le suivi offre un moyen de surveiller la progression d'un workflow. Par défaut, des enregistrements de suivi sont émis pour les événements de cycle de vie du workflow, les événements de cycle de vie de l'activité, la propagation d'erreur et la reprise de signet. En outre, des enregistrements de suivi personnalisés peuvent être émis par des activités personnalisées. Lorsqu'il s'agit de résoudre les problèmes de corrélation, les enregistrements de suivi d'activité, de reprise de signet et de propagation d'erreur sont les plus utiles. Les enregistrements de suivi d'activité peuvent être utilisés pour déterminer la progression actuelle du workflow et contribuent à identifier l'activité de messagerie qui attend actuellement des messages. Les enregistrements de reprise de signet sont utiles parce qu'ils indiquent qu'un message a été reçu par le workflow, et les enregistrements de propagation d'erreur fournissent un enregistrement de toutes les erreurs présentes dans le workflow. Pour activer le suivi, spécifiez le TrackingParticipant voulu dans le WorkflowExtensions du WorkflowServiceHost. Dans l’exemple suivant, le ConsoleTrackingParticipant (de l’exemple Suivi personnalisé) est configuré à l’aide du modèle de suivi par défaut.

host.WorkflowExtensions.Add(new ConsoleTrackingParticipant());

Un participant de suivi tel que ConsoleTrackingParticipant est utile pour les services de workflow auto-hébergés qui ont une fenêtre de console. Pour un service hébergé sur le web, il convient d’utiliser un participant de suivi qui journalise les informations de suivi dans un magasin durable, comme le EtwTrackingParticipant intégré, ou un participant de suivi personnalisé qui journalise les informations dans un fichier.

Pour plus d’informations sur le suivi et la configuration du suivi pour un service de workflow hébergé sur le web, consultez les exemples Suivi de workflow et suivi, Configuration du suivi d’un workflow et Suivi [exemples WF].

Utiliser le suivi WCF

Le suivi WCF fournit un suivi du flux de messages à destination et en provenance d'un service de workflow. Ces informations de suivi sont utiles dans la résolution des problèmes de corrélation, en particulier lorsqu'il s'agit de corrélation basée sur le contenu. Pour activer le suivi, spécifiez les écouteurs de suivi voulus dans la section system.diagnostics du fichier web.config si le service de workflow est hébergé sur le Web ou du fichier app.config si le service de workflow est auto-hébergé. Pour inclure le contenu des messages dans le fichier de trace, spécifiez true pour logEntireMessage dans l'élément messageLogging de la section diagnostics de system.serviceModel. Dans l'exemple suivant, les informations de suivi, notamment le contenu des messages, sont configurées pour être écrites dans un fichier nommé service.svclog.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel" switchValue="Information" propagateActivity="true">
        <listeners>
          <add name="corr"/>
        </listeners>
      </source>
      <source name="System.ServiceModel.MessageLogging">
        <listeners>
          <add name="corr"/>
        </listeners>
      </source>
    </sources>

    <sharedListeners>
      <add name="corr" type="System.Diagnostics.XmlWriterTraceListener" initializeData="c:\logs\service.svclog">
      </add>
    </sharedListeners>
  </system.diagnostics>

  <system.serviceModel>
    <diagnostics>
      <messageLogging logEntireMessage="true" logMalformedMessages="false"
         logMessagesAtServiceLevel="false" logMessagesAtTransportLevel="true" maxSizeOfMessageToLog="2147483647">
      </messageLogging>
    </diagnostics>
  </system.serviceModel>
</configuration>

Pour afficher les informations de trace contenues dans service.svclog, l’outil Service Trace Viewer (SvcTraceViewer.exe) est utilisé. Celui-ci est particulièrement utile pour résoudre les problèmes de corrélation basée sur le contenu, car vous pouvez consulter le contenu des messages, voir exactement ce qui est passé, et si cela correspond au CorrelationQuery de la corrélation basée sur le contenu. Pour plus d’informations sur le suivi WCF, consultez Outil Service Trace Viewer (SvcTraceViewer.exe),, Configuration du suivi et Utilisation du suivi pour résoudre les problèmes posés par votre application.

Problèmes courants rencontrés avec la corrélation basée sur l'échange de contextes

Certains types de corrélation requièrent pour fonctionner correctement l’utilisation d’un type spécifique de liaison. C'est par exemple le cas de la corrélation demande-réponse, qui requiert une liaison bidirectionnelle telle que BasicHttpBinding et de la corrélation basée sur l'échange de contextes, qui requiert une liaison basée sur le contexte, telle que BasicHttpContextBinding. La plupart des liaisons prennent en charge des opérations bidirectionnelles, aussi cela ne constitue-t-il pas un problème courant pour la corrélation demande-réponse, mais il n’existe qu’une poignée de liaisons basées sur le contexte, notamment BasicHttpContextBinding, WSHttpContextBinding et NetTcpContextBinding. Si l’une de ces liaisons n’est pas utilisée, l’appel initial à un service de workflow réussira, mais les appels suivants échoueront avec le FaultException suivant :

There is no context attached to the incoming message for the service
and the current operation is not marked with "CanCreateInstance = true".
In order to communicate with this service check whether the incoming binding
supports the context protocol and has a valid context initialized.

Les informations de contexte utilisées pour la corrélation de contexte peuvent être retournées par le SendReply à l'activité Receive qui initialise la corrélation de contexte lors de l'utilisation d'une opération bidirectionnelle, ou elles peuvent être spécifiées par l'appelant si l'opération est unidirectionnelle. Si le contexte n'est pas envoyé par l'appelant ou retourné par le service de workflow, le FaultException décrit précédemment sera retourné lorsqu'une opération suivante sera appelée.

Problèmes courants rencontrés avec la corrélation demande-réponse

La corrélation demande-réponse est utilisée avec une paire Receive/SendReply pour implémenter une opération bidirectionnelle dans un service de workflow et avec une paire Send/ReceiveReply qui appelle une opération bidirectionnelle dans un autre service web. Lors de l’appel d’une opération bidirectionnelle dans un service WCF, le service peut être soit un service WCF basé sur le code impératif traditionnel, soit un service de workflow. Pour utiliser la corrélation demande-réponse, une liaison bidirectionnelle doit être utilisée, telle que BasicHttpBinding, et les opérations doivent être bidirectionnelles.

Si le service de workflow a des opérations bidirectionnelles en parallèle, ou des paires Receive/SendReply ou Send/ReceiveReply qui se chevauchent, la gestion de handle de corrélation implicite fournie par WorkflowServiceHost peut ne pas être suffisante, en particulier dans les scénarios soumis à un stress élevé, et les messages peuvent ne pas être routés correctement. Pour éviter la survenue de ce problème, nous vous recommandons de toujours spécifier explicitement un CorrelationHandle lors de l'utilisation de la corrélation demande-réponse. Lors de l’utilisation des modèles ReceiveAndSendReply et SendAndReceiveReply de la section Messagerie de la Boîte à outils du concepteur de workflow, un CorrelationHandle est configuré explicitement par défaut. Lors de la génération d'un workflow à l'aide de code, le CorrelationHandle est spécifié dans le CorrelationInitializers de la première activité de la paire. Dans l'exemple suivant, une activité Receive est configurée avec un CorrelationHandle explicite spécifié dans le RequestReplyCorrelationInitializer.

Variable<CorrelationHandle> RRHandle = new Variable<CorrelationHandle>();

Receive StartOrder = new Receive
{
    CanCreateInstance = true,
    ServiceContractName = OrderContractName,
    OperationName = "StartOrder",
    CorrelationInitializers =
    {
        new RequestReplyCorrelationInitializer
        {
            CorrelationHandle = RRHandle
        }
    }
};

SendReply ReplyToStartOrder = new SendReply
{
    Request = StartOrder,
    Content = ... // Contains the return value, if any.
};

// Construct a workflow using StartOrder and ReplyToStartOrder.

La persistance n’est pas autorisée entre une paire Receive/SendReply ou une paire Send/ReceiveReply. Une zone de non-persistance valide tant que les deux activités ne sont pas terminées, est créée. Si une activité, telle qu'une activité de délai, se trouve dans cette zone de non-persistance et cause une inactivité du workflow, ce dernier ne sera pas rendu persistant même si l'hôte est configuré pour rendre persistants les workflows lorsqu'ils deviennent inactifs. Si une activité, telle qu'une activité persistante, tente de persister de façon explicite dans la zone de non-persistance, une exception irrécupérable est levée, le workflow est abandonné et un FaultException est retourné à l'appelant. Le message d'exception irrécupérable est « System.InvalidOperationException : Les activités Persist ne peuvent pas être contenues au sein de blocs sans persistance ». Cette exception n'est pas retournée à l'appelant mais peut-être observée si le suivi est activé. Le message du FaultException retourné à l'appelant est « Impossible d'effectuer l'opération car WorkflowInstance '5836145b-7da2-49d0-a052-a49162adeab6' a terminé ».

Pour plus d’informations sur la corrélation demande-réponse, consultez Demande-réponse.

Problèmes courants rencontrés avec la corrélation basée sur le contenu

La corrélation basée sur le contenu est utilisée lorsqu'un service de workflow reçoit plusieurs messages et dispose de quelques données dans les messages échangés qui identifient l'instance souhaitée. La corrélation basée sur le contenu utilise ces données dans les messages, par exemple un numéro de client ou un ID de commande, pour router les messages vers l'instance de workflow appropriée. Cette section décrit plusieurs problèmes courants qui peuvent se produire lors de l'utilisation de la corrélation basée sur le contenu.

Unicité des données d'identification

Les données utilisées pour identifier l'instance sont hachées en une clé de corrélation. Il est important de s'assurer que les données utilisées pour la corrélation sont uniques, pour éviter que des conflits se produisent dans la clé hachée, entraînant des confusions dans le routage des messages. Par exemple, une corrélation basée uniquement sur un nom de client risque de provoquer un conflit, au cas où d'autres clients aient un nom identique. Les deux-points (:) ne doivent pas être utilisés à l'intérieur des données qui servent à mettre les messages en corrélation. En effet, ils servent déjà à délimiter la clé et la valeur de la requête de message pour former la chaîne qui est ensuite hachée. Si la persistance est utilisée, assurez-vous que les données d'identification actuelles n'ont pas été utilisées par une instance rendue persistante précédemment. Désactiver temporairement la persistance peut aider à identifier ce problème. Le suivi WCF peut être utilisé pour afficher la clé de corrélation calculée et est utile pour déboguer ce genre de problème.

Conditions de concurrence

Il existe un petit intervalle entre le moment où le service reçoit un message et où la corrélation est réellement initialisée, pendant lequel les messages de suivi sont ignorés. Si un service de workflow initialise la corrélation basée sur le contenu à l'aide des données transmises par le client lors d'une opération unidirectionnelle et que l'appelant envoie des messages de suivi immédiats, ces messages sont ignorés pendant cet intervalle. Cela peut être évité en utilisant une opération bidirectionnelle pour initialiser la corrélation, ou en utilisant un TransactedReceiveScope.

Problèmes de requête de corrélation

Les requêtes de corrélation permettent de spécifier les données d'un message qui servent à mettre le message en corrélation. Ces données sont spécifiées à l'aide d'une requête XPath. Si des messages adressés à un service ne sont pas distribués alors que tout semble correct, une stratégie de résolution des problèmes consiste à spécifier une valeur littérale qui correspond à la valeur des données de message au lieu d'une requête XPath. Pour spécifier une valeur littérale, utilisez la fonction string. Dans l'exemple suivant, un MessageQuerySet est configuré de façon à utiliser la valeur littérale 11445 pour l'OrderId et des marques de commentaire sont ajoutées à la requête XPath pour la supprimer.

MessageQuerySet = new MessageQuerySet
{
    {
        "OrderId",
        //new XPathMessageQuery("sm:body()/tempuri:StartOrderResponse/tempuri:OrderId")
        new XPathMessageQuery("string('11445')")
    }
}

Si une requête XPath est configurée incorrectement et aucune donnée de corrélation n’est récupérée, une erreur est retournée avec le message suivant : «  Une requête de corrélation a donné un jeu de résultats vide. Vérifiez que les requêtes de corrélation pour le point de terminaison sont correctement configurées. » Un moyen rapide de résoudre ce problème consiste à remplacer la requête XPath par une valeur littérale, comme décrit dans la section précédente. Ce problème peut se produire si vous utilisez le générateur de requêtes XPath dans les boîtes de dialogue Ajouter des initialiseurs de corrélation ou Définition CorrelatesOn et que votre service de workflow utilise des contrats de message. Dans l'exemple suivant, une classe de contrat de message est définie.

[MessageContract]
public class AddItemMessage
{
    [MessageHeader]
    public string CartId;

    [MessageBodyMember]
    public string Item;
}

Ce contrat de message est utilisé par une activité Receive dans un workflow. Le CartId dans l'en-tête du message est utilisé pour corréler le message à l'instance correcte. Si la requête XPath qui récupère le CartId est créée à l’aide de boîtes de dialogue de corrélation dans le concepteur de workflow, la requête XPath incorrecte suivante est générée.

sm:body()/xg0:AddItemMessage/xg0:CartId

Cette requête XPath serait correcte si l’activité Receive utilisait des paramètres pour les données, mais puisqu’elle utilise un contrat de message, elle est incorrecte. La requête XPath suivante est celle qu’il faut utiliser pour récupérer le CartId de l’en-tête.

sm:header()/tempuri:CartId

Ceci peut être vérifié en examinant le corps du message.

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/IService/AddItem</Action>
    <h:CartId xmlns:h="http://tempuri.org/">80c95b41-c98d-4660-a6c1-99412206e54c</h:CartId>
  </s:Header>
  <s:Body>
    <AddItemMessage xmlns="http://tempuri.org/">
      <Item>Books</Item>
    </AddItemMessage>
  </s:Body>
</s:Envelope>

L'exemple suivant illustre une activité Receive configurée pour une opération AddItem qui utilise le contrat de message précédent pour recevoir les données. La requête XPath est configurée correctement.

<Receive CorrelatesWith="[CCHandle] OperationName="AddItem" ServiceContractName="p:IService">
  <Receive.CorrelatesOn>
    <XPathMessageQuery x:Key="key1">
      <XPathMessageQuery.Namespaces>
        <ssx:XPathMessageContextMarkup>
          <x:String x:Key="xg0">http://schemas.datacontract.org/2004/07/MessageContractWFService</x:String>
        </ssx:XPathMessageContextMarkup>
      </XPathMessageQuery.Namespaces>sm:header()/tempuri:CartId</XPathMessageQuery>
  </Receive.CorrelatesOn>
  <ReceiveMessageContent DeclaredMessageType="m:AddItemMessage">
    <p1:OutArgument x:TypeArguments="m:AddItemMessage">[AddItemMessage]</p1:OutArgument>
  </ReceiveMessageContent>
</Receive>