Share via


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:

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.

Langere duur in Application Insights-logboek

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/abonnementspad
  • peer.address – volledig gekwalificeerde naamruimte
  • kind – producent, consument of klant. Producent wordt gebruikt bij het verzenden van berichten, consumenten bij ontvangst en client bij het vereffenen.
  • componentservicebus

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:

  1. IsEnabled(<OperationName>, string entity, null) bijvoorbeeld IsEnabled("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 verzonden false.

    • Voor de bewerkingen 'Proces' en 'ProcessSession' ontvangt IsEnabled(<OperationName>, string entity, Activity activity) u ook callback. Gebruik deze om gebeurtenissen te filteren op activity.Id basis van of tags-eigenschappen.
  2. IsEnabled(<OperationName>.Start) bijvoorbeeld IsEnabled("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