Korelacja rozwiązywania problemów
Korelacja służy do powiązania komunikatów usługi przepływu pracy ze sobą i do poprawnego wystąpienia przepływu pracy, ale jeśli nie jest poprawnie skonfigurowany, komunikaty nie będą odbierane, a aplikacje nie będą działać poprawnie. Ten temat zawiera omówienie kilku metod rozwiązywania problemów z korelacją, a także zawiera listę typowych problemów, które mogą wystąpić podczas korzystania z korelacji.
Obsługa zdarzenia UnknownMessageReceived
Zdarzenie UnknownMessageReceived występuje, gdy nieznany komunikat jest odbierany przez usługę, w tym komunikaty, których nie można skorelować z istniejącym wystąpieniem. W przypadku samoobsługowych usług to zdarzenie można obsłużyć w aplikacji hosta.
host.UnknownMessageReceived += delegate(object sender, UnknownMessageReceivedEventArgs e)
{
Console.WriteLine("Unknown Message Received:");
Console.WriteLine(e.Message);
};
W przypadku usług hostowanych w sieci Web to zdarzenie można obsłużyć przez wyprowadzenie CreateWorkflowServiceHostklasy z klasy i WorkflowServiceHostFactory zastąpienie .
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;
}
}
Ten niestandardowy WorkflowServiceHostFactory można następnie określić w svc
pliku dla usługi.
<% @ServiceHost Language="C#" Service="OrderServiceWorkflow" Factory="CustomFactory" %>
Po wywołaniu tej procedury obsługi można pobrać komunikat przy użyciu Message właściwości UnknownMessageReceivedEventArgs, i będzie przypominać następujący komunikat.
<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>
Inspekcja komunikatów wysłanych do UnknownMessageReceived programu obsługi może dostarczyć wskazówek, dlaczego komunikat nie skorelował się z wystąpieniem usługi przepływu pracy.
Monitorowanie postępu przepływu pracy za pomocą śledzenia
Śledzenie umożliwia monitorowanie postępu przepływu pracy. Domyślnie rekordy śledzenia są emitowane dla zdarzeń cyklu życia przepływu pracy, zdarzeń cyklu życia działań, propagacji błędów i wznowienia zakładki. Ponadto niestandardowe rekordy śledzenia mogą być emitowane przez działania niestandardowe. Podczas rozwiązywania problemów z korelacją rekordy śledzenia aktywności, rekordy wznowienia zakładki i rekordy propagacji błędów są najbardziej przydatne. Rekordy śledzenia aktywności mogą służyć do określania bieżącego postępu przepływu pracy i mogą pomóc określić, które działanie obsługi komunikatów aktualnie oczekuje na komunikaty. Rekordy wznowienia zakładek są przydatne, ponieważ wskazują one, że komunikat został odebrany przez przepływ pracy, a rekordy propagacji błędów zawierają rekordy błędów w przepływie pracy. Aby włączyć śledzenie, określ żądaną TrackingParticipant wartość w elemecie WorkflowExtensionsWorkflowServiceHost. W poniższym przykładzie ConsoleTrackingParticipant
parametr (z przykładu Custom Tracking ) jest skonfigurowany przy użyciu domyślnego profilu śledzenia.
host.WorkflowExtensions.Add(new ConsoleTrackingParticipant());
Uczestnik śledzenia, taki jak ConsoleTrackingParticipant, jest przydatny w przypadku samoobsługowych usług przepływu pracy, które mają okno konsoli. W przypadku usługi hostowanej w sieci Web uczestnik śledzenia, który rejestruje informacje śledzenia w trwałym magazynie, powinien być używany, taki jak wbudowany EtwTrackingParticipantuczestnik śledzenia lub niestandardowy uczestnik śledzenia, który rejestruje informacje w pliku.
Aby uzyskać więcej informacji na temat śledzenia i konfigurowania śledzenia dla usługi przepływu pracy hostowanej w Sieci Web, zobacz Śledzenie przepływu pracy i śledzenie, Konfigurowanie śledzenia przepływu pracy i przykłady śledzenia [przykłady WF].
Korzystanie z śledzenia WCF
Śledzenie WCF zapewnia śledzenie przepływu komunikatów do i z usługi przepływu pracy. Te informacje śledzenia są przydatne podczas rozwiązywania problemów z korelacją, szczególnie w przypadku korelacji opartej na zawartości. Aby włączyć śledzenie, określ żądane odbiorniki śledzenia w system.diagnostics
sekcji web.config
pliku, jeśli usługa przepływu pracy jest hostowana w sieci Web lub app.config
plik, jeśli usługa przepływu pracy jest hostowana samodzielnie. Aby uwzględnić zawartość komunikatów w pliku śledzenia, określ true
element logEntireMessage
w messageLogging
diagnostics
sekcji system.serviceModel
. W poniższym przykładzie informacje śledzenia, w tym zawartość komunikatów, są skonfigurowane do zapisywania w pliku o nazwie 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>
Aby wyświetlić informacje dotyczące śledzenia zawarte w service.svclog
programie , jest używane narzędzie podglądu śledzenia usługi (SvcTraceViewer.exe). Jest to szczególnie przydatne podczas rozwiązywania problemów z korelacją opartą na zawartości, ponieważ można wyświetlić zawartość komunikatu i zobaczyć dokładnie to, co jest przekazywane, oraz czy jest zgodna CorrelationQuery z korelacją opartą na zawartości. Aby uzyskać więcej informacji na temat śledzenia WCF, zobacz Service Trace Viewer Tool (SvcTraceViewer.exe), Configuring Tracing and Using Tracing to Troubleshoot Your Application (Narzędzie do przeglądania śladów usług), Configuring Tracing and Using Tracing to Troubleshoot Your Application (Konfigurowanie śledzenia i Używanie śledzenia do rozwiązywania problemów z aplikacją).
Typowe problemy z korelacją wymiany kontekstu
Niektóre typy korelacji wymagają, aby określony typ powiązania był używany do poprawnego działania korelacji. Przykłady obejmują korelację odpowiedzi żądania, która wymaga powiązania dwukierunkowego, takiego jak , i korelacji wymiany kontekstu, która wymaga powiązania opartego na kontekście, takiego jak BasicHttpBindingBasicHttpContextBinding. Większość powiązań obsługuje operacje dwukierunkowe, więc nie jest to typowy problem dla korelacji odpowiedzi na żądanie, ale istnieje tylko kilka powiązań opartych na kontekście, w tym BasicHttpContextBinding, WSHttpContextBindingi NetTcpContextBinding. Jeśli jedno z tych powiązań nie jest używane, początkowe wywołanie usługi przepływu pracy powiedzie się, ale kolejne wywołania zakończy się niepowodzeniem z następującymi FaultExceptionmetodami .
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.
Informacje kontekstowe używane do korelacji kontekstu mogą być zwracane przez SendReplyReceive działanie inicjujące korelację kontekstu podczas korzystania z operacji dwukierunkowej lub może być określone przez obiekt wywołujący, jeśli operacja jest jednokierunkowa. Jeśli kontekst nie jest wysyłany przez obiekt wywołujący lub zwracany przez usługę przepływu pracy, wówczas ten sam FaultException opisany wcześniej zostanie zwrócony po wywołaniu kolejnej operacji.
Typowe problemy z korelacją Request-Reply
Korelacja odpowiedzi na żądanie jest używana z parą Receive/SendReply w celu zaimplementowania dwukierunkowej operacji w usłudze przepływu pracy i Send/ReceiveReply pary, która wywołuje operację dwukierunkową w innej usłudze sieci Web. Podczas wywoływania dwukierunkowej operacji w usłudze WCF usługa może być tradycyjną usługą WCF opartą na kodzie imperatywnej lub usługą przepływu pracy. Aby użyć korelacji odpowiedzi żądania, należy użyć powiązania dwukierunkowego, takiego jak BasicHttpBinding, a operacje muszą być dwukierunkowe.
Jeśli usługa przepływu pracy ma równoległe operacje dwukierunkowe lub nakładające się Receive/SendReply lub Send/ReceiveReply pary, niejawne zarządzanie uchwytem korelacji zapewnianym przez WorkflowServiceHost usługę może nie być wystarczające, zwłaszcza w scenariuszach o wysokim obciążeniu, a komunikaty mogą nie być prawidłowo kierowane. Aby zapobiec wystąpieniu tego problemu, zalecamy, aby zawsze jawnie określić CorrelationHandle wartość podczas korzystania z korelacji odpowiedzi na żądanie. W przypadku korzystania z szablonów SendAndReceiveReply i ReceiveAndSendReply z sekcji Obsługa komunikatów przybornika w projektancie CorrelationHandle przepływu pracy element jest jawnie skonfigurowany domyślnie. Podczas tworzenia przepływu pracy przy użyciu kodu CorrelationHandle element jest określony w CorrelationInitializers pierwszym działaniu w parze. W poniższym przykładzie Receive działanie jest konfigurowane z jawnie CorrelationHandle określonym w elemecie 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.
Trwałość nie jest dozwolona między parą lub parąReceive//SendSendReplyReceiveReply. Utworzono strefę bez trwałości, która trwa do momentu ukończenia obu działań. Jeśli działanie, takie jak działanie opóźnienia, znajduje się w tej strefie bez utrwalonej i powoduje, że przepływ pracy stanie się bezczynny, przepływ pracy nie będzie utrwalany nawet wtedy, gdy host jest skonfigurowany do utrwalania przepływów pracy, gdy staną się bezczynne. Jeśli działanie, takie jak działanie trwałe, próbuje jawnie utrwały się w strefie bez utrwalonej, zgłaszany jest wyjątek krytyczny, przerywanie przepływu pracy, a FaultException obiekt jest zwracany do obiektu wywołującego. Komunikat o wyjątku krytycznym to "System.InvalidOperationException: Działania trwałe nie mogą być zawarte w żadnych blokach trwałości". Ten wyjątek nie jest zwracany do elementu wywołującego, ale można go zaobserwować, jeśli śledzenie jest włączone. Komunikat zwrócony do obiektu wywołującego FaultException to "Nie można wykonać operacji, ponieważ usługa WorkflowInstance '5836145b-7da2-49d0-a052-a49162adeab6' została ukończona".
Aby uzyskać więcej informacji na temat korelacji odpowiedzi na żądanie, zobacz Request-Reply.
Typowe problemy z korelacją zawartości
Korelacja oparta na zawartości jest używana, gdy usługa przepływu pracy odbiera wiele komunikatów, a część danych w wymienianych komunikatach identyfikuje żądane wystąpienie. Korelacja oparta na zawartości używa tych danych w komunikacie, takich jak numer klienta lub identyfikator zamówienia, do kierowania komunikatów do poprawnego wystąpienia przepływu pracy. W tej sekcji opisano kilka typowych problemów, które mogą wystąpić podczas korzystania z korelacji opartej na zawartości.
Upewnij się, że dane identyfikujące są unikatowe
Dane używane do identyfikowania wystąpienia są zapisywane w kluczu korelacji. Należy zachować ostrożność, aby zagwarantować, że dane używane do korelacji są unikatowe lub inne kolizje w kluczu skrótu mogą wystąpić i spowodować błędne przekierowanie komunikatów. Na przykład korelacja oparta tylko na nazwie klienta może spowodować kolizję, ponieważ może istnieć wiele klientów, którzy mają taką samą nazwę. Dwukropek (:) nie należy używać jako części danych używanych do korelowania komunikatu, ponieważ jest już używany do rozdzielenia klucza i wartości zapytania komunikatu w celu utworzenia ciągu, który jest następnie skrótem. Jeśli jest używana trwałość, upewnij się, że bieżące dane identyfikujące nie zostały użyte przez wcześniej utrwalone wystąpienie. Tymczasowe wyłączenie trwałości może pomóc w zidentyfikowaniu tego problemu. Śledzenie WCF może służyć do wyświetlania obliczonego klucza korelacji i jest przydatne do debugowania tego rodzaju problemu.
Warunki wyścigu
Istnieje niewielka różnica między odebraniem komunikatu przez usługę a faktycznie zainicjowaną korelacją, podczas której komunikaty po kontynuacji zostaną zignorowane. Jeśli usługa przepływu pracy inicjuje korelację opartą na zawartości przy użyciu danych przekazywanych z klienta za pośrednictwem operacji jednokierunkowej, a obiekt wywołujący wysyła natychmiastowe komunikaty ponależące, te komunikaty będą ignorowane w tym interwale. Można to uniknąć, używając operacji dwukierunkowej w celu zainicjowania korelacji lub przy użyciu polecenia TransactedReceiveScope.
Problemy z zapytaniem korelacji
Zapytania korelacji służą do określania, jakie dane w komunikacie są używane do korelowania komunikatu. Te dane są określane przy użyciu zapytania XPath. Jeśli komunikaty do usługi nie są wysyłane, mimo że wszystko wydaje się być poprawne, jedną ze strategii rozwiązywania problemów jest określenie wartości literału zgodnej z wartością danych komunikatu zamiast zapytania XPath. Aby określić wartość literału, użyj string
funkcji . W poniższym przykładzie MessageQuerySet parametr jest skonfigurowany do używania wartości 11445
literału dla elementu OrderId
, a zapytanie XPath jest komentowane.
MessageQuerySet = new MessageQuerySet
{
{
"OrderId",
//new XPathMessageQuery("sm:body()/tempuri:StartOrderResponse/tempuri:OrderId")
new XPathMessageQuery("string('11445')")
}
}
Jeśli zapytanie XPath jest niepoprawnie skonfigurowane tak, że żadne dane korelacji nie są pobierane, zostanie zwrócony błąd z następującym komunikatem: "Zapytanie korelacji zwróciło pusty zestaw wyników. Upewnij się, że zapytania korelacji dla punktu końcowego są poprawnie skonfigurowane. Jednym z szybkich sposobów rozwiązywania problemów jest zastąpienie zapytania XPath wartością literału zgodnie z opisem w poprzedniej sekcji. Ten problem może wystąpić, jeśli używasz konstruktora zapytań XPath w oknach dialogowych Dodawanie inicjatorów korelacji lub Definicji korelowania, a usługa przepływu pracy używa kontraktów komunikatów. W poniższym przykładzie zdefiniowano klasę kontraktu komunikatów.
[MessageContract]
public class AddItemMessage
{
[MessageHeader]
public string CartId;
[MessageBodyMember]
public string Item;
}
Ten kontrakt komunikatu jest używany przez Receive działanie w przepływie pracy. Nagłówek CartId
komunikatu służy do skorelowania komunikatu z poprawnym wystąpieniem. Jeśli zapytanie XPath, które pobiera CartId
obiekt, zostanie utworzone przy użyciu okien dialogowych korelacji w projektancie przepływu pracy, zostanie wygenerowane następujące nieprawidłowe zapytanie XPath.
sm:body()/xg0:AddItemMessage/xg0:CartId
To zapytanie XPath byłoby poprawne, jeśli Receive działanie używało parametrów dla danych, ale ponieważ używa kontraktu komunikatu, jest niepoprawne. Następujące zapytanie XPath jest prawidłowym zapytaniem XPath, aby pobrać dane CartId
z nagłówka.
sm:header()/tempuri:CartId
Można to potwierdzić, sprawdzając treść wiadomości.
<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>
W poniższym przykładzie przedstawiono Receive działanie skonfigurowane dla AddItem
operacji, która używa poprzedniego kontraktu komunikatu do odbierania danych. Zapytanie XPath jest poprawnie skonfigurowane.
<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>