Śledzenie rozproszone i korelacja za pośrednictwem obsługi wiadomości usługi Service Bus
Jednym z typowych problemów związanych z opracowywaniem mikrousług jest możliwość śledzenia operacji od klienta za pośrednictwem wszystkich usług, które są zaangażowane w przetwarzanie. Jest to przydatne w przypadku debugowania, analizy wydajności, testowania A/B i innych typowych scenariuszy diagnostycznych. Jedną z części tego problemu jest śledzenie logicznych elementów pracy. Obejmuje on wynik i opóźnienie przetwarzania komunikatów oraz wywołania zależności zewnętrznych. Inną częścią jest korelacja tych zdarzeń diagnostycznych poza granice procesu.
Gdy producent wysyła komunikat za pośrednictwem kolejki, zwykle występuje w zakresie innej operacji logicznej zainicjowanej przez innego klienta lub usługę. Ta sama operacja jest kontynuowana przez użytkownika po otrzymaniu komunikatu. Zarówno producent, jak i konsument (oraz inne usługi, które przetwarzają operację), prawdopodobnie emitują zdarzenia telemetryczne w celu śledzenia przepływu operacji i wyniku. Aby skorelować takie zdarzenia i kompleksową operację śledzenia, każda usługa, która raportuje dane telemetryczne, musi oznaczać każde zdarzenie kontekstem śledzenia. Jedną z bibliotek, które mogą pomóc deweloperom mieć wszystkie te dane telemetryczne emitowane domyślnie, jest NServiceBus.
Obsługa komunikatów usługi Microsoft Azure Service Bus ma zdefiniowane właściwości ładunku, których producenci i odbiorcy powinni używać do przekazywania takiego kontekstu śledzenia. Protokół jest oparty na kontekście śledzenia W3C.
Nazwa właściwości | Opis |
---|---|
Identyfikator diagnostyczny | Unikatowy identyfikator wywołania zewnętrznego od producenta do kolejki. Zapoznaj się z nagłówkem trace-context trace-context w formacie W3C |
Autotracing klienta .NET usługi Service Bus
ServiceBusProcessor
Klasa klienta usługi Azure Messaging Service Bus dla platformy .NET udostępnia punkty instrumentacji śledzenia, które można podłączyć przez systemy śledzenia lub fragment kodu klienta. Instrumentacja umożliwia śledzenie wszystkich wywołań usługi obsługi komunikatów usługi Service Bus po stronie klienta. Jeśli przetwarzanie komunikatów odbywa się przy użyciu ( ProcessMessageAsync
wzorzec obsługi komunikatów), przetwarzanie komunikatów ServiceBusProcessor
jest również instrumentowane.
Śledzenie za pomocą usługi aplikacja systemu Azure Insights
Usługa Microsoft Application Insights oferuje zaawansowane funkcje monitorowania wydajności, w tym automatyczne żądanie i śledzenie zależności.
W zależności od typu projektu zainstaluj zestaw SDK usługi Application Insights:
- ASP.NET — zainstaluj wersję 2.5-beta2 lub nowszą
- ASP.NET Core — zainstaluj wersję 2.2.0-beta2 lub nowszą. Te linki zawierają szczegółowe informacje dotyczące instalowania zestawu SDK, tworzenia zasobów i konfigurowania zestawu SDK (w razie potrzeby). W przypadku aplikacji non-ASP.NET zapoznaj się z artykułem aplikacja systemu Azure Insights for Console Applications (Szczegółowe informacje o aplikacjach konsoli).
Jeśli używasz ProcessMessageAsync
(wzorca obsługi komunikatów) do przetwarzania ServiceBusProcessor
komunikatów, przetwarzanie komunikatów jest również instrumentowane. Wszystkie wywołania usługi Service Bus wykonywane przez usługę są automatycznie śledzone i skorelowane z innymi elementami telemetrii. W przeciwnym razie zapoznaj się z poniższym przykładem śledzenia ręcznego przetwarzania komunikatów.
Przetwarzanie komunikatów śledzenia
async Task ProcessAsync(ProcessMessageEventArgs args)
{
ServiceBusReceivedMessage message = args.Message;
if (message.ApplicationProperties.TryGetValue("Diagnostic-Id", out var objectId) && objectId is string diagnosticId)
{
var activity = new Activity("ServiceBusProcessor.ProcessMessage");
activity.SetParentId(diagnosticId);
// If you're using Microsoft.ApplicationInsights package version 2.6-beta or higher, you should call StartOperation<RequestTelemetry>(activity) instead
using (var operation = telemetryClient.StartOperation<RequestTelemetry>("Process", activity.RootId, activity.ParentId))
{
telemetryClient.TrackTrace("Received message");
try
{
// process message
}
catch (Exception ex)
{
telemetryClient.TrackException(ex);
operation.Telemetry.Success = false;
throw;
}
telemetryClient.TrackTrace("Done");
}
}
}
W tym przykładzie dane telemetryczne żądań są zgłaszane dla każdego przetworzonego komunikatu, mając znacznik czasu, czas trwania i wynik (powodzenie). Dane telemetryczne mają również zestaw właściwości korelacji. Zagnieżdżone ślady i wyjątki zgłaszane podczas przetwarzania komunikatów są również oznaczane właściwościami korelacji reprezentującymi je jako "elementy podrzędne" elementu RequestTelemetry
.
W przypadku wykonywania wywołań do obsługiwanych składników zewnętrznych podczas przetwarzania komunikatów są one również automatycznie śledzone i skorelowane. Zapoznaj się z tematem Śledzenie operacji niestandardowych za pomocą zestawu SDK platformy .NET usługi Application Insights, aby uzyskać instrukcje ręcznego śledzenia i korelacji.
Jeśli używasz dowolnego kodu zewnętrznego oprócz zestawu SDK usługi Application Insights, spodziewaj się dłuższego czasu trwania podczas wyświetlania dzienników usługi Application Insights.
Nie oznacza to, że wystąpiło opóźnienie podczas odbierania komunikatu. W tym scenariuszu komunikat został już odebrany, ponieważ komunikat jest przekazywany jako parametr do kodu zestawu SDK. Tag nazwy w dziennikach usługi App Insights (proces) wskazuje, że komunikat jest teraz przetwarzany przez kod przetwarzania zdarzeń zewnętrznych. Ten problem nie jest związany z platformą Azure. Zamiast tego te metryki odnoszą się do wydajności kodu zewnętrznego, ponieważ komunikat został już odebrany z usługi Service Bus.
Śledzenie za pomocą funkcji OpenTelemetry
Biblioteka klienta .NET usługi Service Bus w wersji 7.5.0 lub nowszej obsługuje funkcję OpenTelemetry w trybie eksperymentalnym. Aby uzyskać więcej informacji, zobacz Śledzenie rozproszone w zestawie SDK platformy .NET.
Śledzenie bez systemu śledzenia
Jeśli system śledzenia nie obsługuje automatycznego śledzenia wywołań usługi Service Bus, możesz rozważyć dodanie takiej obsługi do systemu śledzenia lub do aplikacji. W tej sekcji opisano zdarzenia diagnostyczne wysyłane przez klienta .NET usługi Service Bus.
Klient .NET usługi Service Bus jest instrumentowany przy użyciu elementów pierwotnych śledzenia platformy .NET System.Diagnostics.Activity i System.Diagnostics.DiagnosticSource.
Activity
służy jako kontekst śledzenia, podczas gdy DiagnosticSource
jest mechanizmem powiadamiania.
Jeśli nie ma odbiornika zdarzeń DiagnosticSource, instrumentacja jest wyłączona, zachowując zerowe koszty instrumentacji. Narzędzie DiagnosticSource zapewnia całą kontrolę odbiornikowi:
- odbiornik steruje źródłami i zdarzeniami do nasłuchiwania
- odbiornik kontroluje częstotliwość zdarzeń i próbkowanie
- zdarzenia są wysyłane z ładunkiem, który zapewnia pełny kontekst, dzięki czemu można uzyskać dostęp do obiektu komunikatu i zmodyfikować go podczas zdarzenia
Zapoznaj się z podręcznikiem użytkownika DiagnosticSource przed kontynuowaniem implementacji.
Utwórzmy odbiornik zdarzeń usługi Service Bus w aplikacji ASP.NET Core, która zapisuje dzienniki w pliku Microsoft.Extension.Logger. Używa biblioteki System.Reactive.Core do subskrybowania elementu DiagnosticSource (można również łatwo zasubskrybować źródło diagnostyczne bez niego)
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory factory, IApplicationLifetime applicationLifetime)
{
// configuration...
var serviceBusLogger = factory.CreateLogger("Azure.Messaging.ServiceBus");
IDisposable innerSubscription = null;
IDisposable outerSubscription = DiagnosticListener.AllListeners.Subscribe(delegate (DiagnosticListener listener)
{
// subscribe to the Service Bus DiagnosticSource
if (listener.Name == "Azure.Messaging.ServiceBus")
{
// receive event from Service Bus DiagnosticSource
innerSubscription = listener.Subscribe(delegate (KeyValuePair<string, object> evnt)
{
// Log operation details once it's done
if (evnt.Key.EndsWith("Stop"))
{
Activity currentActivity = Activity.Current;
serviceBusLogger.LogInformation($"Operation {currentActivity.OperationName} is finished, Duration={currentActivity.Duration}, Id={currentActivity.Id}, StartTime={currentActivity.StartTimeUtc}");
}
});
}
});
applicationLifetime.ApplicationStopping.Register(() =>
{
outerSubscription?.Dispose();
innerSubscription?.Dispose();
});
}
W tym przykładzie odbiornik rejestruje czas trwania, wynik, unikatowy identyfikator i godzinę rozpoczęcia dla każdej operacji usługi Service Bus.
Zdarzenia
Wszystkie zdarzenia będą miały następujące właściwości zgodne ze specyfikacją otwartej telemetrii: https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/api.md.
message_bus.destination
— kolejka/temat/ścieżka subskrypcjipeer.address
– w pełni kwalifikowana przestrzeń nazwkind
– producent, konsument lub klient. Producent jest używany podczas wysyłania komunikatów, odbiorcy podczas odbierania i klienta podczas ustalania.component
–servicebus
Wszystkie zdarzenia mają Entity
również właściwości i Endpoint
.
Entity
— Nazwa jednostki (kolejka, temat itd.)Endpoint
— Adres URL punktu końcowego usługi Service Bus
Operacje instrumentowane
Oto pełna lista operacji instrumentowanych:
Nazwa operacji | Śledzony interfejs API |
---|---|
ServiceBusSender.Send | ServiceBusSender.SendMessageAsync ServiceBusSender.SendMessagesAsync |
ServiceBusSender.Schedule | ServiceBusSender.ScheduleMessageAsync ServiceBusSender.ScheduleMessagesAsync |
ServiceBusSender.Cancel | ServiceBusSender.CancelScheduledMessageAsync ServiceBusSender.CancelScheduledMessagesAsync |
ServiceBusReceiver.Receive | ServiceBusReceiver.ReceiveMessageAsync ServiceBusReceiver.ReceiveMessagesAsync |
ServiceBusReceiver.ReceiveDeferred | ServiceBusReceiver.ReceiveDeferredMessagesAsync |
ServiceBusReceiver.Peek | ServiceBusReceiver.PeekMessageAsync ServiceBusReceiver.PeekMessagesAsync |
ServiceBusReceiver.Abandon | ServiceBusReceiver.AbandonMessagesAsync |
ServiceBusReceiver.Complete | ServiceBusReceiver.CompleteMessagesAsync |
ServiceBusReceiver.DeadLetter | ServiceBusReceiver.DeadLetterMessagesAsync |
ServiceBusReceiver.Defer | ServiceBusReceiver.DeferMessagesAsync |
ServiceBusReceiver.RenewMessageLock | ServiceBusReceiver.RenewMessageLockAsync |
ServiceBusSessionReceiver.RenewSessionLock | ServiceBusSessionReceiver.RenewSessionLockAsync |
ServiceBusSessionReceiver.GetSessionState | ServiceBusSessionReceiver.GetSessionStateAsync |
ServiceBusSessionReceiver.SetSessionState | ServiceBusSessionReceiver.SetSessionStateAsync |
ServiceBusProcessor.ProcessMessage | Wywołanie zwrotne procesora ustawione w usłudze ServiceBusProcessor. Właściwość ProcessMessageAsync |
ServiceBusSessionProcessor.ProcessSessionMessage | Wywołanie zwrotne procesora ustawione w usłudze ServiceBusSessionProcessor. Właściwość ProcessMessageAsync |
Filtrowanie i próbkowanie
W niektórych przypadkach pożądane jest rejestrowanie tylko części zdarzeń w celu zmniejszenia obciążenia związanego z wydajnością lub zużycia magazynu. Można rejestrować tylko zdarzenia "Zatrzymaj" (jak w poprzednim przykładzie) lub przykładowy procent zdarzeń.
DiagnosticSource
zapewnić sposób osiągnięcia go z IsEnabled
predykatem. Aby uzyskać więcej informacji, zobacz Filtrowanie oparte na kontekście w źródle diagnostycznym.
IsEnabled
może być wywoływana wiele razy dla pojedynczej operacji w celu zminimalizowania wpływu na wydajność.
IsEnabled
jest wywoływana w następującej sekwencji:
IsEnabled(<OperationName>, string entity, null)
na przykładIsEnabled("ServiceBusSender.Send", "MyQueue1")
. Pamiętaj, że na końcu nie ma "Start" ani "Stop". Służy do filtrowania określonych operacji lub kolejek. Jeśli metoda wywołania zwrotnego zwracafalse
wartość , zdarzenia dla operacji nie są wysyłane.- W przypadku operacji "Process" i "ProcessSession" otrzymasz
IsEnabled(<OperationName>, string entity, Activity activity)
również wywołanie zwrotne. Służy do filtrowania zdarzeń naactivity.Id
podstawie właściwości tagów lub .
- W przypadku operacji "Process" i "ProcessSession" otrzymasz
IsEnabled(<OperationName>.Start)
na przykładIsEnabled("ServiceBusSender.Send.Start")
. Sprawdza, czy zdarzenie "Start" powinno zostać wyzwolone. Wynik ma wpływ tylko na zdarzenie "Start", ale dalsza instrumentacja nie zależy od niego.
Nie ma IsEnabled
zdarzenia "Zatrzymaj".
Jeśli jakiś wynik operacji jest wyjątkiem, IsEnabled("ServiceBusSender.Send.Exception")
jest wywoływany. Można subskrybować tylko zdarzenia "Wyjątek" i zapobiegać pozostałej części instrumentacji. W takim przypadku nadal trzeba obsługiwać takie wyjątki. Ponieważ inne instrumentacje są wyłączone, nie należy oczekiwać, że kontekst śledzenia będzie przepływać z komunikatami od konsumenta do producenta.
Można również zaimplementować IsEnabled
strategie próbkowania. Próbkowanie na Activity.Id
podstawie metody lub Activity.RootId
zapewnia spójne próbkowanie we wszystkich oponach (o ile jest propagowane przez system śledzenia lub własny kod).
W obecności wielu DiagnosticSource
odbiorników dla tego samego źródła wystarczy, aby tylko jeden odbiornik zaakceptował zdarzenie, więc nie ma gwarancji, że IsEnabled
jest wywoływany.
Następne kroki
- Korelacja usługi Application Insights
- Zależności monitora usługi Application Insights, aby sprawdzić, czy rest, SQL lub inne zasoby zewnętrzne spowalniają.
- Śledzenie operacji niestandardowych za pomocą zestawu SDK platformy .NET usługi Application Insights