Gedistribueerde tracering en correlatie via Service Bus-berichten
Een van de veelvoorkomende problemen bij het ontwikkelen van microservices is de mogelijkheid om bewerkingen van een client te traceren via alle services die betrokken zijn bij de verwerking. Het is handig voor foutopsporing, prestatieanalyse, A/B-tests en andere typische diagnostische scenario's. Een deel van dit probleem is het bijhouden van logische werkstukken. Het omvat berichtverwerkingsresultaten en latentie en externe afhankelijkheidsaanroepen. Een ander onderdeel is correlatie van deze diagnostische gebeurtenissen buiten procesgrenzen.
Wanneer een producent een bericht via een wachtrij verzendt, vindt dit meestal plaats in het bereik van een andere logische bewerking, geïnitieerd door een andere client of service. Dezelfde bewerking wordt voortgezet door de consument zodra deze een bericht ontvangt. Zowel producent als consument (en andere services die de bewerking verwerken), verzenden waarschijnlijk telemetriegebeurtenissen om de bewerkingsstroom en het resultaat te traceren. Om dergelijke gebeurtenissen en traceringsbewerkingen end-to-end te correleren, moet elke service die telemetrie rapporteert elke gebeurtenis voorzien van een traceringscontext. Een bibliotheek waarmee ontwikkelaars al deze telemetrie standaard kunnen verzenden, is NServiceBus.
Microsoft Azure Service Bus Messaging heeft nettoladingeigenschappen gedefinieerd die producenten en consumenten moeten gebruiken om dergelijke traceringscontext door te geven. Het protocol is gebaseerd op de W3C Trace-Context.
Eigenschapsnaam | Beschrijving |
---|---|
Diagnostische id | Unieke id van een externe aanroep van producent naar de wachtrij. Raadpleeg W3C Trace-Context traceparent header voor de indeling |
Service Bus .NET Client automatisch aftrekken
De ServiceBusProcessor
klasse van de Azure Messaging Service Bus-client voor .NET biedt tracerings instrumentatiepunten die kunnen worden gekoppeld door traceringssystemen of stukje clientcode. Met de instrumentatie kunnen alle aanroepen naar de Service Bus-berichtenservice vanaf de clientzijde worden bijgehouden. Als berichtverwerking wordt uitgevoerd met behulp ProcessMessageAsync
van ServiceBusProcessor
(berichthandlerpatroon), wordt de berichtverwerking ook geïnstrueerd.
Bijhouden met Azure-toepassing Inzichten
Microsoft Application Insights biedt uitgebreide mogelijkheden voor prestatiebewaking, waaronder automatisch aanvragen en bijhouden van afhankelijkheden.
Installeer Application Insights SDK, afhankelijk van uw projecttype:
- ASP.NET - versie 2.5-beta2 of hoger installeren
- ASP.NET Core : installeer versie 2.2.0-beta2 of hoger. Deze koppelingen bevatten informatie over het installeren van SDK, het maken van resources en het configureren van SDK (indien nodig). Raadpleeg het artikel Azure-toepassing Insights for Console Applications voor non-ASP.NET-toepassingen.
Als u gebruikmaakt ProcessMessageAsync
van ServiceBusProcessor
(berichthandlerpatroon) om berichten te verwerken, wordt de berichtverwerking ook geïnstrumenteerd. Alle Service Bus-aanroepen die door uw service worden uitgevoerd, worden automatisch bijgehouden en gecorreleerd met andere telemetrie-items. Raadpleeg anders het volgende voorbeeld voor het handmatig bijhouden van berichten.
Berichtverwerking traceren
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");
}
}
}
In dit voorbeeld wordt aanvraagtelemetrie gerapporteerd voor elk verwerkt bericht, met een tijdstempel, duur en resultaat (geslaagd). De telemetrie heeft ook een set correlatie-eigenschappen. Geneste traceringen en uitzonderingen die tijdens de verwerking van berichten worden gerapporteerd, worden ook gestempeld met correlatie-eigenschappen die ze vertegenwoordigen als 'onderliggende' van de RequestTelemetry
.
Als u tijdens het verwerken van berichten aanroept naar ondersteunde externe onderdelen, worden ze ook automatisch bijgehouden en gecorreleerd. Raadpleeg Aangepaste bewerkingen bijhouden met Application Insights .NET SDK voor handmatig bijhouden en correlatie.
Als u een externe code uitvoert naast de Application Insights SDK, verwacht u een langere duur bij het weergeven van Application Insights-logboeken.
Het betekent niet dat er een vertraging is opgetreden bij het ontvangen van het bericht. In dit scenario is het bericht al ontvangen sinds het bericht wordt doorgegeven als een parameter aan de SDK-code. En de naamtag in de App Insights-logboeken (proces) geeft aan dat het bericht nu wordt verwerkt door uw externe gebeurtenisverwerkingscode. Dit probleem heeft geen betrekking op Azure. In plaats daarvan verwijzen deze metrische gegevens naar de efficiëntie van uw externe code omdat het bericht al is ontvangen van Service Bus.
Bijhouden met OpenTelemetry
Service Bus .NET Client library versie 7.5.0 en hoger ondersteunt OpenTelemetry in experimentele modus. Zie gedistribueerde tracering in .NET SDK voor meer informatie.
Bijhouden zonder traceringssysteem
Als uw traceringssysteem geen ondersteuning biedt voor het automatisch bijhouden van Service Bus-oproepen, kunt u dergelijke ondersteuning toevoegen aan een traceringssysteem of in uw toepassing. In deze sectie worden diagnostische gebeurtenissen beschreven die zijn verzonden door de Service Bus .NET-client.
De Service Bus .NET-client wordt geïnstrueerd met behulp van .NET-traceringsprimitief System.Diagnostics.Activity en System.Diagnostics.DiagnosticSource.
Activity
fungeert als een traceringscontext terwijl DiagnosticSource
het een meldingsmechanisme is.
Als er geen listener is voor de DiagnosticSource-gebeurtenissen, is instrumentatie uitgeschakeld, waardoor er geen instrumentatiekosten in rekening worden gebracht. DiagnosticSource geeft alle controle over de listener:
- listener bepaalt naar welke bronnen en gebeurtenissen moeten worden geluisterd
- listener bepaalt de gebeurtenissnelheid en steekproeven
- gebeurtenissen worden verzonden met een nettolading die volledige context biedt, zodat u het berichtobject tijdens de gebeurtenis kunt openen en wijzigen
Maak uzelf vertrouwd met de Gebruikershandleiding voor Diagnostische bronnen voordat u doorgaat met de implementatie.
Laten we een listener maken voor Service Bus-gebeurtenissen in ASP.NET Core-app die logboeken schrijft met Microsoft.Extension.Logger. Het maakt gebruik van system.Reactive.Core-bibliotheek om u te abonneren op DiagnosticSource (het is ook eenvoudig om u te abonneren op DiagnosticSource zonder deze)
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();
});
}
In dit voorbeeld registreert de listener de duur, het resultaat, de unieke id en de begintijd voor elke Service Bus-bewerking.
gebeurtenis
Alle gebeurtenissen hebben de volgende eigenschappen die voldoen aan de open telemetriespecificatie: https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/api.md.
message_bus.destination
– wachtrij/onderwerp/abonnementspadpeer.address
– volledig gekwalificeerde naamruimtekind
– producent, consument of klant. Producent wordt gebruikt bij het verzenden van berichten, consumenten bij ontvangst en client bij het vereffenen.component
–servicebus
Alle gebeurtenissen hebben Entity
ook en Endpoint
eigenschappen.
Entity
- Naam van de entiteit (wachtrij, onderwerp, enzovoort.)Endpoint
- URL van Service Bus-eindpunt
Geïnstrueerde bewerkingen
Hier volgt de volledige lijst met geïnstrueerde bewerkingen:
Naam van bewerking | Bijgehouden 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 | Callback van processor ingesteld op ServiceBusProcessor. Eigenschap ProcessMessageAsync |
ServiceBusSessionProcessor.ProcessSessionMessage | Callback van processor ingesteld op ServiceBusSessionProcessor. Eigenschap ProcessMessageAsync |
Filteren en steekproeven
In sommige gevallen is het wenselijk om slechts een deel van de gebeurtenissen vast te leggen om de overhead van de prestaties of het opslagverbruik te verminderen. U kunt gebeurtenissen alleen 'Stoppen' registreren (zoals in het vorige voorbeeld) of het voorbeeldpercentage van de gebeurtenissen.
DiagnosticSource
een manier bieden om het te bereiken met IsEnabled
predicaat. Zie Filteren op basis van context in DiagnosticSource voor meer informatie.
IsEnabled
kan meerdere keren worden aangeroepen voor één bewerking om de invloed van de prestaties te minimaliseren.
IsEnabled
wordt in de volgende volgorde aangeroepen:
IsEnabled(<OperationName>, string entity, null)
bijvoorbeeldIsEnabled("ServiceBusSender.Send", "MyQueue1")
. Houd er rekening mee dat er geen 'Start' of 'Stop' aan het einde is. Gebruik deze om bepaalde bewerkingen of wachtrijen uit te filteren. Als de callback-methode wordt geretourneerd, worden er geen gebeurtenissen voor de bewerking verzondenfalse
.- Voor de bewerkingen 'Proces' en 'ProcessSession' ontvangt
IsEnabled(<OperationName>, string entity, Activity activity)
u ook callback. Gebruik deze om gebeurtenissen te filteren opactivity.Id
basis van of tags-eigenschappen.
- Voor de bewerkingen 'Proces' en 'ProcessSession' ontvangt
IsEnabled(<OperationName>.Start)
bijvoorbeeldIsEnabled("ServiceBusSender.Send.Start")
. Controleert of de gebeurtenis Start moet worden geactiveerd. Het resultaat is alleen van invloed op de gebeurtenis Start, maar verdere instrumentatie is niet afhankelijk van de gebeurtenis.
Er is geen IsEnabled
'Stop'-gebeurtenis.
Als een bewerkingsresultaat uitzondering is, IsEnabled("ServiceBusSender.Send.Exception")
wordt deze aangeroepen. U kunt zich alleen abonneren op uitzonderingsevenementen en de rest van de instrumentatie voorkomen. In dit geval moet u dergelijke uitzonderingen nog steeds afhandelen. Omdat andere instrumentatie is uitgeschakeld, moet u niet verwachten dat de traceringscontext met de berichten van de consument naar de producent stroomt.
U kunt ook samplingstrategieën implementeren IsEnabled
. Steekproeven op basis van de Activity.Id
of Activity.RootId
zorgen voor consistente steekproeven voor alle banden (zolang deze worden doorgegeven door het traceringssysteem of door uw eigen code).
In aanwezigheid van meerdere DiagnosticSource
listeners voor dezelfde bron is het voldoende voor slechts één listener om de gebeurtenis te accepteren, dus er is geen garantie dat IsEnabled
wordt aangeroepen.
Volgende stappen
- Application Insights-correlatie
- Application Insights Monitor-afhankelijkheden om te zien of REST, SQL of andere externe resources u vertragen.
- Aangepaste bewerkingen bijhouden met Application Insights .NET SDK