Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Korrelation används för att relatera arbetsflödestjänstmeddelanden till varandra och till rätt arbetsflödesinstans, men om den inte är korrekt konfigurerad tas meddelanden inte emot och programmen fungerar inte korrekt. Det här avsnittet innehåller en översikt över flera metoder för att felsöka korrelationsproblem och innehåller även några vanliga problem som kan uppstå när du använder korrelation.
Hantera händelsen UnknownMessageReceived
Händelsen UnknownMessageReceived inträffar när ett okänt meddelande tas emot av en tjänst, inklusive meddelanden som inte kan korreleras till en befintlig instans. För lokalt installerade tjänster kan den här händelsen hanteras i värdprogrammet.
host.UnknownMessageReceived += delegate(object sender, UnknownMessageReceivedEventArgs e)
{
Console.WriteLine("Unknown Message Received:");
Console.WriteLine(e.Message);
};
För webbaserade tjänster kan den här händelsen hanteras genom att härleda en klass från WorkflowServiceHostFactory och åsidosätta 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;
}
}
Den här anpassade WorkflowServiceHostFactory kan sedan anges i svc-filen för tjänsten.
<% @ServiceHost Language="C#" Service="OrderServiceWorkflow" Factory="CustomFactory" %>
När den här hanteraren anropas kan meddelandet hämtas med hjälp Message av UnknownMessageReceivedEventArgsegenskapen , och liknar följande meddelande.
<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>
Att inspektera meddelanden som skickas till UnknownMessageReceived hanteraren kan ge ledtrådar om varför meddelandet inte korrelerade med en instans av arbetsflödestjänsten.
Använda spårning för att övervaka arbetsflödets förlopp
Spårning är ett sätt att övervaka förloppet för ett arbetsflöde. Som standard genererar systemet spårningsposter för arbetsflödets livscykelhändelser, aktivitetslivscykelhändelser, felspridning och återupptagande av bokmärken. Dessutom kan anpassade spårningsposter genereras av anpassade aktiviteter. De mest användbara vid felsökning av korrelation är aktivitetsloggarna, återupptagande av bokmärkesloggar och felspridningsloggarna. Aktivitetsspårningsposterna kan användas för att fastställa arbetsflödets aktuella förlopp och kan hjälpa dig att identifiera vilken meddelandeaktivitet som för närvarande väntar på meddelanden. Återupptagningsposter för bokmärken är användbara eftersom de anger att ett meddelande har tagits emot av arbetsflödet, och felspridningsposter ger en redovisning av eventuella fel i arbetsflödet. Om du vill aktivera spårning anger du önskat TrackingParticipant i WorkflowExtensions för WorkflowServiceHost. I följande exempel konfigureras ConsoleTrackingParticipant med hjälp av standardspårningsprofilen (från exemplet Anpassad Spårning).
host.WorkflowExtensions.Add(new ConsoleTrackingParticipant());
En spårningsdeltagare som ConsoleTrackingParticipant är användbar för lokala arbetsflödestjänster som har ett konsolfönster. För en webbaserad tjänst ska en spårningsdeltagare som loggar spårningsinformationen till ett beständigt arkiv användas, till exempel den inbyggda EtwTrackingParticipanteller en anpassad spårningsdeltagare som loggar informationen till en fil.
Mer information om hur du spårar och konfigurerar spårning för en webbhanterad arbetsflödestjänst finns i Arbetsflödesspårning och spårning, Konfigurera spårning för ett arbetsflöde och exempel på spårning [WF-exempel].
Använd WCF spårning
WCF-spårning ger spårning av flödet av meddelanden till och från en arbetsflödestjänst. Den här spårningsinformationen är användbar när du felsöker korrelationsproblem, särskilt för innehållsbaserad korrelation. Om du vill aktivera spårning anger du önskade spårningslyssnare i system.diagnostics avsnittet web.config i filen om arbetsflödestjänsten är webbaserad eller app.config filen om arbetsflödestjänsten är lokalt installerad. Om du vill inkludera innehållet i meddelandena i spårningsfilen, anger du true för logEntireMessage i elementet messageLogging i avsnittet diagnostics av system.serviceModel. I följande exempel konfigureras spårningsinformation, inklusive innehållet i meddelandena, att skrivas till en fil med namnet 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>
Om du vill visa spårningsinformationen som finns i service.svcloganvänds servicespårningsverktyget (SvcTraceViewer.exe) . Detta är särskilt användbart när du felsöker innehållsbaserade korrelationsproblem eftersom du kan visa meddelandeinnehållet och se exakt vad som skickas och om det matchar för den innehållsbaserade korrelationen CorrelationQuery . Mer information om WCF-spårning finns i Service Trace Viewer Tool (SvcTraceViewer.exe), Konfigurera spårning och Använda spårning för att felsöka ditt program.
Vanliga problem med kontextkorrelation i Exchange.
Vissa typer av korrelation kräver att en specifik typ av bindning används för att korrelationen ska fungera korrekt. Exempel är korrelation mellan begäran och svar, som kräver en dubbelriktad bindning, till exempel BasicHttpBinding, och korrelation för kontextutbyte, som kräver en kontextbaserad bindning, till exempel BasicHttpContextBinding. De flesta bindningar stöder dubbelriktade åtgärder, så det här är inte ett vanligt problem för korrelation mellan begäran och svar, men det finns bara en handfull kontextbaserade bindningar som BasicHttpContextBinding, WSHttpContextBindingoch NetTcpContextBinding. Om en av dessa bindningar inte används kommer det första anropet till en arbetsflödestjänst att lyckas, men efterföljande anrop kommer att misslyckas med följande FaultException.
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.
Kontextinformationen som används för kontextkorrelation kan returneras av SendReply till den Receive aktivitet som initierar kontextkorrelationen när du använder en dubbelriktad åtgärd, eller så kan den anges av anroparen om åtgärden är enkelriktad. Om kontexten inte skickas av anroparen eller returneras av arbetsflödestjänsten returneras samma FaultException som beskrivs tidigare när en efterföljande åtgärd anropas.
Vanliga korrelationsproblem vid begäran och svar
Korrelation mellan begäran och svar används med ett Receive/SendReply par för att implementera en dubbelriktad åtgärd i en arbetsflödestjänst och med ett Send/ReceiveReply par som anropar en dubbelriktad åtgärd i en annan webbtjänst. När du anropar en dubbelriktad åtgärd i en WCF-tjänst kan tjänsten antingen vara en traditionell imperativ kodbaserad WCF-tjänst eller en arbetsflödestjänst. Om du vill använda korrelation mellan begäran och svar måste en dubbelriktad bindning användas, till exempel BasicHttpBinding, och åtgärderna måste vara dubbelriktade.
Om arbetsflödestjänsten har tvåvägsoperationer parallellt, eller överlappande Receive/SendReply eller Send/ReceiveReply par, kanske den implicita hantering av korrelationshandtag som tillhandahålls av WorkflowServiceHost inte räcker, särskilt i scenarier med hög stress, och meddelandena kanske inte routas korrekt. För att förhindra att det här problemet uppstår rekommenderar vi att du alltid uttryckligen anger en CorrelationHandle när du använder korrelation mellan begäran och svar. När du använder mallarna SendAndReceiveReply och ReceiveAndSendReply från meddelandeavsnittet i verktygslådan i arbetsflödesdesignern konfigureras en CorrelationHandle explicit som standard. När du skapar ett arbetsflöde med hjälp av kod anges CorrelationHandle i CorrelationInitializers på den första aktiviteten i paret. I följande exempel konfigureras en Receive aktivitet med en explicit CorrelationHandle angiven i 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.
Beständighet tillåts inte mellan ett Receive/SendReply par eller ett Send/ReceiveReply par. En no-persist-zon skapas som varar tills båda aktiviteterna har slutförts. Om en aktivitet, till exempel en fördröjningsaktivitet, finns i en zon för icke-bevarande och gör att arbetsflödet blir vilande, kommer arbetsflödet inte att bevaras även om värdprogrammet är konfigurerat för att bevara arbetsflöden när de blir vilande. Om en aktivitet, till exempel en persistent aktivitet, försöker att explicit upprätthålla sig i en icke-beständighetszon, kastas ett kritiskt undantag, arbetsflödet avbryts omedelbart och ett FaultException returneras till anroparen. Det allvarliga undantagsmeddelandet är "System.InvalidOperationException: Persist-aktiviteter kan inte finnas inom några persistensblock". Det här undantaget returneras inte till anroparen men kan observeras om spårning är aktiverat. Meddelandet för den FaultException som returneras till anroparen är "Åtgärden kunde inte utföras eftersom WorkflowInstance '5836145b-7da2-49d0-a052-a49162adeab6' har slutförts".
Mer information om korrelation mellan begäran och svar finns i Begärandesvar.
Vanliga problem med innehållskorrelation
Innehållsbaserad korrelation används när en arbetsflödestjänst tar emot flera meddelanden och en del data i de utväxlade meddelandena identifierar den önskade instansen. Innehållsbaserad korrelation använder dessa data i meddelandet, till exempel ett kundnummer eller order-ID, för att dirigera meddelanden till rätt arbetsflödesinstans. Det här avsnittet beskriver flera vanliga problem som kan uppstå när du använder innehållsbaserad korrelation.
Se till att den identifierande datan är unik
De data som används för att identifiera instansen hashas till en korrelationsnyckel. Var noga med att garantera att de data som används för korrelation är unika, annars kan kollisioner i den hashade nyckeln inträffa och leda till att meddelanden blir felriktade. Till exempel kan en korrelation som endast baseras på ett kundnamn orsaka en kollision eftersom det kan finnas flera kunder som har samma namn. Kolonet (:) ska inte användas som en del av de data som används för att korrelera meddelandet eftersom det redan används för att avgränsa meddelandefrågans nyckel och värde för att bilda strängen som därefter hashas. Om beständighet används kontrollerar du att de aktuella identifierande data inte har använts av en tidigare bevarad instans. Att tillfälligt inaktivera beständighet kan hjälpa dig att identifiera det här problemet. WCF-spårning kan användas för att visa den beräknade korrelationsnyckeln och är användbar för felsökning av den här typen av problem.
Tävlingsförhållanden
Det finns ett litet tidsgap mellan att tjänsten tar emot ett meddelande och korrelationen som faktiskt initieras, under vilken uppföljningsmeddelanden ignoreras. Om en arbetsflödestjänst initierar den innehållsbaserade korrelationen med hjälp av data som skickas från klienten via en enkelriktad åtgärd, och anroparen skickar omedelbara uppföljningsmeddelanden, ignoreras dessa meddelanden under det här intervallet. Detta kan undvikas genom att använda en tvåvägsåtgärd för att initiera korrelationen eller med hjälp av en TransactedReceiveScope.
Problem med korrelationsfråga
Korrelationsfrågor används för att ange vilka data i ett meddelande som ska användas för att korrelera meddelandet. Dessa data anges med hjälp av en XPath-fråga. Om meddelanden till en tjänst inte skickas trots att allt verkar vara korrekt är en strategi för felsökning att ange ett literalvärde som matchar värdet för meddelandedata i stället för en XPath-fråga. Om du vill ange ett literalvärde använder du string funktionen. I följande exempel är en MessageQuerySet konfigurerad för att använda ett bokstavligt värde 11445 för OrderId och XPath-frågan kommenteras bort.
MessageQuerySet = new MessageQuerySet
{
{
"OrderId",
//new XPathMessageQuery("sm:body()/tempuri:StartOrderResponse/tempuri:OrderId")
new XPathMessageQuery("string('11445')")
}
}
Om en XPath-fråga är felaktigt konfigurerad så att inga korrelationsdata hämtas returneras ett fel med följande meddelande: "En korrelationsfråga gav en tom resultatuppsättning. Kontrollera att korrelationsfrågor för slutpunkten är korrekt konfigurerade." Ett snabbt sätt att felsöka detta är att ersätta XPath-frågan med ett literalvärde enligt beskrivningen i föregående avsnitt. Det här problemet kan inträffa om du använder XPath-frågeverktyget i dialogrutorna Lägg till korrelationsinitierare eller KorreleraPå definition och arbetsflödestjänsten använder meddelandekontrakt. I följande exempel definieras en meddelandekontraktsklass.
[MessageContract]
public class AddItemMessage
{
[MessageHeader]
public string CartId;
[MessageBodyMember]
public string Item;
}
Det här meddelandekontraktet används av en Receive aktivitet i ett arbetsflöde.
CartId i meddelandets rubrik används för att korrelera meddelandet till rätt instans. Om XPath-frågan som hämtar CartId skapas med hjälp av korrelationsdialogrutorna i arbetsflödesdesignern genereras följande felaktiga XPath-fråga.
sm:body()/xg0:AddItemMessage/xg0:CartId
Den här XPath-frågan skulle vara korrekt om aktiviteten Receive använde parametrar för data, men eftersom den använder ett meddelandekontrakt är den felaktig. Följande XPath-fråga är den korrekta för att hämta CartId från rubriken.
sm:header()/tempuri:CartId
Detta kan bekräftas genom att undersöka meddelandets brödtext.
<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>
I följande exempel visas en Receive aktivitet som konfigurerats för en AddItem åtgärd som använder det tidigare meddelandekontraktet för att ta emot data. XPath-frågan är korrekt konfigurerad.
<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>