Elosztott nyomkövetés és korreláció Service Bus-üzenetkezelésen keresztül

A mikroszolgáltatások fejlesztésének egyik gyakori problémája az, hogy nyomon követhető a művelet az ügyféltől a feldolgozásban részt vevő összes szolgáltatáson keresztül. Hasznos hibakereséshez, teljesítményelemzéshez, A/B-teszteléshez és egyéb tipikus diagnosztikai forgatókönyvekhez. A probléma egyik része a logikai munkadarabok nyomon követése. Ez magában foglalja az üzenetfeldolgozás eredményét, a késést és a külső függőségi hívásokat. Egy másik része ezeknek a diagnosztikai eseményeknek a folyamathatárokon túli korrelációja.

Amikor egy gyártó üzenetsoron keresztül küld üzenetet, az általában valamilyen más, más ügyfél vagy szolgáltatás által kezdeményezett logikai művelet hatókörében történik. Ugyanezt a műveletet a fogyasztó folytatja, amint üzenetet kap. A termelő és a fogyasztó (és a műveletet feldolgozó egyéb szolgáltatások) feltehetően telemetriai eseményeket bocsátanak ki a művelet folyamatának és eredményének nyomon követéséhez. Az ilyen események és a nyomkövetési művelet végpontok közötti korrelációja érdekében a telemetriát jelentést tevő összes szolgáltatásnak le kell pecsételnie minden eseményt egy nyomkövetési környezettel.

A Microsoft Azure Service Bus-üzenetkezelés olyan hasznos adattulajdonságokat definiált, amelyeket a gyártóknak és a fogyasztóknak használniuk kell az ilyen nyomkövetési környezet átadásához. A protokoll a W3C trace-context-en alapul.

Tulajdonság neve Leírás
Diagnosztikai azonosító A gyártótól az üzenetsorba irányuló külső hívás egyedi azonosítója. Tekintse meg a W3C Trace-Context nyomkövetési fejlécét a formátumhoz

Service Bus .NET-ügyfél automatikus nyomkövetése

A ServiceBusProcessor .NET-hez készült Azure Messaging Service Bus-ügyfél osztály nyomkövetési rendszerállapot-pontokat biztosít, amelyek nyomkövetési rendszerekkel vagy ügyfélkóddal kapcsolhatók össze. A rendszerállapot lehetővé teszi a Service Bus üzenetkezelési szolgáltatás ügyféloldali hívásainak nyomon követését. Ha az üzenetfeldolgozás (üzenetkezelő minta) használatával ProcessMessageAsyncServiceBusProcessor történik, az üzenetfeldolgozás is eszközre kerül.

Nyomon követés Azure-alkalmazás Elemzések

A Microsoft Application Elemzések gazdag teljesítménymonitorozási képességeket biztosít, beleértve az automagikus kéréseket és a függőségek nyomon követését.

A projekt típusától függően telepítse az Application Elemzések SDK-t:

  • ASP.NET – a 2.5-béta2-es vagy újabb verzió telepítése
  • ASP.NET Core – telepítse a 2.2.0-béta2-es vagy újabb verziót. Ezek a hivatkozások részletesen ismertetik az SDK telepítését, az erőforrások létrehozását és az SDK konfigurálását (ha szükséges). Az non-ASP.NET-alkalmazásokról a konzolalkalmazások Azure-alkalmazás Elemzések című cikkben talál további információt.

Ha (üzenetkezelő minta) használja ProcessMessageAsyncServiceBusProcessor az üzenetek feldolgozását, az üzenetfeldolgozás is eszközre kerül. A szolgáltatás által végrehajtott összes Service Bus-hívás automatikusan nyomon követi és korrelál más telemetriai elemekkel. Egyéb esetben tekintse meg az alábbi példát a manuális üzenetfeldolgozás nyomon követésére.

Nyomkövetési üzenetek feldolgozása

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");
        }
    }
}

Ebben a példában a rendszer minden feldolgozott üzenethez jelentést küld a kérelem telemetriai adatairól, amelyek időbélyeget, időtartamot és eredményt (sikert) eredményeznek. A telemetria korrelációs tulajdonságokkal is rendelkezik. Az üzenetfeldolgozás során jelentett beágyazott nyomkövetéseket és kivételeket a rendszer korrelációs tulajdonságokkal is megjelöli, amelyek a "gyermekként" jelölik őket.RequestTelemetry

Ha az üzenetfeldolgozás során a támogatott külső összetevőkre irányuló hívásokat kezdeményez, azok is automatikusan nyomon lesznek követve és korrelálva. Az egyéni műveletek nyomon követése az Application Elemzések .NET SDK-val a manuális nyomon követés és korreláció érdekében.

Ha az Alkalmazás Elemzések SDK mellett bármilyen külső kódot is futtat, az alkalmazás Elemzések naplók megtekintése hosszabb ideig tart.

Longer duration in Application Insights log

Ez nem jelenti azt, hogy késés történt az üzenet fogadásában. Ebben a forgatókönyvben az üzenet már megérkezett, mivel az üzenet paraméterként lett átadva az SDK-kódnak. Az Alkalmazás Elemzések naplók (Folyamat) névcímkéje azt jelzi, hogy az üzenetet a külső eseményfeldolgozó kód dolgozza fel. Ez a probléma nem Azure-beli. Ehelyett ezek a metrikák a külső kód hatékonyságára vonatkoznak, mivel az üzenet már megérkezett a Service Bustól.

Nyomon követés OpenTelemetryvel

A Service Bus .NET-ügyfélkódtár 7.5.0-s és újabb verziója kísérleti módban támogatja az OpenTelemetria használatát. További információ: Elosztott nyomkövetés a .NET SDK-ban.

Nyomkövetési rendszer nélküli nyomon követés

Ha a nyomkövetési rendszer nem támogatja az automatikus Service Bus-hívások nyomon követését, előfordulhat, hogy ilyen támogatást szeretne hozzáadni egy nyomkövetési rendszerhez vagy az alkalmazáshoz. Ez a szakasz a Service Bus .NET-ügyfél által küldött diagnosztikai eseményeket ismerteti.

A Service Bus .NET-ügyfél a System.Diagnostics.Activity és a System.Diagnostics.DiagnosticSource .NET nyomkövetési primitívek használatával van kialakítva.

Activity nyomkövetési környezetként szolgál, míg DiagnosticSource egy értesítési mechanizmus.

Ha nincs figyelő a DiagnosticSource-eseményekhez, a rendszerállapot ki van kapcsolva, így a rendszerállapot-költségek nem lesznek zéróak. A DiagnosticSource minden vezérlést biztosít a figyelőnek:

  • a figyelő szabályozza, hogy mely forrásokra és eseményekre kell figyelni
  • a figyelő szabályozza az események gyakoriságát és mintavételezését
  • az eseményeket olyan hasznos adatokkal küldi el, amelyek teljes környezetet biztosítanak, így az esemény során elérheti és módosíthatja az Üzenet objektumot

Ismerkedjen meg a DiagnosticSource felhasználói útmutatójával, mielőtt továbblép a megvalósításra.

Hozzunk létre egy figyelőt a Service Bus-eseményekhez ASP.NET Core alkalmazásban, amely naplókat ír a Microsoft.Extension.Logger használatával. A System.Reactive.Core könyvtárat használja a DiagnosticSource-ra való feliratkozáshoz (nélküle is könnyen előfizethet a DiagnosticSource-ra)

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();
    });
}

Ebben a példában a figyelő naplózza az egyes Service Bus-műveletek időtartamát, eredményét, egyedi azonosítóit és kezdési idejét.

Events

Minden esemény a következő tulajdonságokkal rendelkezik, amelyek megfelelnek a nyitott telemetriai specifikációnak: https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/api.md.

  • message_bus.destination – üzenetsor/témakör/előfizetés elérési útja
  • peer.address – teljes névtér
  • kind – gyártó, fogyasztó vagy ügyfél. A termelőt üzenetek küldésekor, a fogyasztó a fogadáskor és az ügyfél a rendezés során használja.
  • componentservicebus

Minden esemény rendelkezik és Endpoint tulajdonságokkal is rendelkezikEntity.

  • Entity - - Az entitás neve (üzenetsor, témakör stb.)
  • Endpoint - Service Bus-végpont URL-címe

Rendszerezett műveletek

A rendszerezett műveletek teljes listája:

Művelet neve Nyomon követett 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 Processzorvisszahívás beállítása a ServiceBusProcessoron. ProcessMessageAsync tulajdonság
ServiceBusSessionProcessor.ProcessSessionMessage Processzorvisszahívás beállítása a ServiceBusSessionProcessoron. ProcessMessageAsync tulajdonság

Szűrés és mintavételezés

Bizonyos esetekben célszerű az eseményeknek csak egy részét naplózni a teljesítményterhelés vagy a tárterület-használat csökkentése érdekében. A "Stop" eseményeket csak (az előző példához hasonlóan) vagy az események százalékos arányát naplózhatja. DiagnosticSource predikátummal IsEnabled kell elérni. További információ: Környezetalapú szűrés a DiagnosticSource-ban.

IsEnabled többször is meghívható egyetlen művelethez a teljesítményre gyakorolt hatás minimalizálása érdekében.

IsEnabled a következő sorrendben hívjuk meg:

  1. IsEnabled(<OperationName>, string entity, null) például IsEnabled("ServiceBusSender.Send", "MyQueue1"). Vegye figyelembe, hogy nincs "Start" vagy "Stop" a végén. Segítségével kiszűrhet bizonyos műveleteket vagy üzenetsorokat. Ha a visszahívási falsemódszer visszatér, a művelet eseményei nem lesznek elküldve.

    • A "Process" és a "ProcessSession" műveletek esetében visszahívást is kap IsEnabled(<OperationName>, string entity, Activity activity) . Segítségével szűrheti az eseményeket a címkék tulajdonságai alapján activity.Id .
  2. IsEnabled(<OperationName>.Start) például IsEnabled("ServiceBusSender.Send.Start"). Ellenőrzi, hogy aktiválni kell-e a "Start" eseményt. Az eredmény csak a "Start" eseményre van hatással, de a további rendszerezés nem függ attól.

Nincs IsEnabled "Stop" esemény.

Ha egy művelet eredménye kivétel, IsEnabled("ServiceBusSender.Send.Exception") a rendszer meghívja. Csak "Kivétel" eseményekre iratkozhat fel, és megakadályozhatja a rendszerállapot többi részét. Ebben az esetben továbbra is kezelnie kell az ilyen kivételeket. Mivel a többi rendszerállapot le van tiltva, nem várható, hogy a nyomkövetési környezet a fogyasztótól a gyártóig áramlik az üzenetekkel.

Mintavételezési stratégiákat is alkalmazhat IsEnabled . A mintavételezés az Activity.Id összes gumiabroncs egységes mintavételezésén alapul vagy Activity.RootId biztosítja (mindaddig, amíg a nyomkövetési rendszer vagy a saját kódja propagálja).

Több figyelő jelenlétében DiagnosticSource ugyanahhoz a forráshoz elegendő, ha csak egy figyelő fogadja el az eseményt, így nincs garancia arra, hogy IsEnabled a rendszer meghívja.

Következő lépések