Modifier

Partager via


Contrôler un système distribué à l’aide d’Application Insights et d’OpenCensus

Hubs d'événements Azure
Azure Functions
Azure Service Bus
Azure Monitor

Cet article décrit un système distribué créé avec Azure Functions, Azure Event Hubs et Azure Service Bus. Il fournit des détails sur la façon de contrôler le système de bout en bout à l’aide d’OpenCensus pour Python et d’Application Insights. Cet article présente également le suivi distribué et explique son fonctionnement à l’aide d’exemples de code Python. La société fictive Contoso est utilisée dans l’architecture pour décrire le scénario.

Notes

OpenCensus et OpenTelemetry fusionnent, mais OpenCensus reste l’outil recommandé pour contrôler les Azure Functions. OpenTelemetry pour Azure est en préversion et certaines fonctionnalités ne sont pas encore disponibles.

Architecture

Ce diagramme montre l’architecture mise en place en trois étapes : requête, processus et upsert.

Téléchargez un fichier Visio de cette architecture.

Workflow

  1. Requêtes. Une fonction Azure déclenchée par le minuteur interroge l’API interne Contoso pour obtenir les dernières données de vente une fois par jour. La fonction utilise la liaison de sortie Azure Event Hubs pour envoyer les données non structurées en tant qu’événements.

  2. Traitement. Event Hubs déclenche une fonction Azure qui traite et met en forme les données non structurées dans une structure prédéfinie. La fonction publie un message par ressource dans Service Bus qui doit être importé via la liaison de sortie Service Bus.

  3. Upsert. Service Bus déclenche une fonction Azure qui consomme les messages de la file d’attente et exécute une opération upsert dans le stockage commun de l’entreprise.

Il est important de prendre en compte les éventuels échecs d’opération de cette architecture. Voici quelques exemples :

  • L’API interne n’est pas disponible, ce qui conduit à une exception qui est levée par la fonction Azure de données de requête à l’étape 1 de l’architecture.
  • Lors de l’étape 2, la fonction Azure de données de traitement rencontre des données en dehors des conditions ou paramètres de la fonction.
  • À l’étape 3, la fonction Azure upsert data échoue. Après plusieurs nouvelles tentatives, les messages de la file d’attente Service Bus passent dans la file d’attente de lettres mortes, qui est une file d’attente secondaire qui contient les messages qui ne peuvent pas être traités ou remis à un destinataire après un nombre prédéfini de nouvelles tentatives. Ensuite, les messages peuvent suivre un processus automatique établi, ou ils peuvent être gérés manuellement.

Composants

  • Azure Functions est un service serverless qui gère vos applications.
  • Application Insights est une fonctionnalité d’Azure Monitor qui contrôle les applications en développement, test et production. Application Insights analyse les performances d’une application et passe en revue les données d’exécution de l’application pour déterminer la cause d’un incident.
  • Azure Table Storage est un service qui stocke dans le cloud des données structurées non relationnelles (également appelées données NoSQL structurées) dans le cloud et qui fournit un magasin de clés/attributs reposant sur une conception sans schéma.
  • Event Hubs est un service d’ingestion des événements évolutif capable de recevoir et de traiter des millions d’événements par seconde.
  • OpenCensus est un ensemble de bibliothèques open source que vous pouvez utiliser pour collecter des traces distribuées, des mesures et des données de télémétrie de journalisation. Cette architecture utilise l’implémentation Python d’OpenCensus.
  • Service Bus est un répartiteur de messages complètement managé, avec des files d’attente de messages et des rubriques de publication/abonnement.

Détails du scénario

Les systèmes distribués sont constitués de composants faiblement couplés. Il peut être difficile de comprendre comment les composants communiquent et de percevoir pleinement le parcours de bout en bout d’une requête utilisateur. Cette architecture vous aide à voir comment les composants sont connectés.

Comme de nombreuses entreprises, Contoso doit ingérer des données locales ou tierces dans le cloud tout en collectant des données sur leurs ventes à l’aide de services et d’outils internes. Dans cette architecture, un service de Contoso a créé une API interne qui expose les données non structurées et qui ingère les données dans un stockage commun. Le stockage commun contient des données structurées de chaque service. L’architecture montre comment Contoso extrait, traite et ingère ces métadonnées dans le cloud.

Lorsque vous générez un système, en particulier un système distribué, il est important de le rendre observable. Un système observable :

  • Fournit une vue holistique de l’intégrité de l’application distribuée.
  • Mesure les performances opérationnelles du système.
  • Identifie et diagnostique les défaillances afin de pouvoir résoudre rapidement un problème.

Traçage distribué

Dans cette architecture, le système est une chaîne de micro-services. Chaque micro-service peut échouer indépendamment pour différentes raisons. Dans ce cas, il est important de comprendre ce qui s’est passé afin de pouvoir identifier et résoudre les problèmes. Il est utile d’isoler une transaction de bout en bout et de suivre le parcours à travers la pile d’applications, qui se compose de services ou de micro-services. Cette méthode est appelée suivi distribué.

Les sections suivantes décrivent comment configurer le suivi distribué dans l’architecture. Sélectionnez le bouton suivant Déployer sur Azure pour déployer l’infrastructure et l’application de fonction Azure.

Notes

Il n’existe pas d’API interne dans l’architecture. Par conséquent, une lecture d’un fichier Azure remplace l’appel à une API.

Déployer sur Azure

Traces et spans

Une transaction est représentée par une trace, qui est une collection d’étendues. Par exemple, lorsque vous sélectionnez le bouton d’achat pour passer une commande sur un site web de e-commerce, plusieurs opérations ont lieu. Quelques opérations possibles incluent :

  • Une requête POST est envoyée à l’API, qui vous redirige ensuite vers une « page d’attente ».
  • Écriture de journaux avec des informations contextuelles.
  • Appel externe à un logiciel web pour demander une page de facturation.

Chacune de ces opérations peut faire partie d’une étendue. La trace est une description complète de ce qui se passe lorsque vous sélectionnez le bouton d’achat.

De même, dans cette architecture, lorsque la fonction Azure de données de requête se déclenche pour démarrer l’ingestion quotidienne des données de vente, une trace contenant plusieurs étendues est créée :

  • Une étendue permettant de confirmer les détails du déclencheur.
  • Une étendue permettant d’interroger l’API interne.
  • Une étendue permettant de créer et d’envoyer un événement à Event Hubs.

Une étendue peut avoir des étendues enfants. Par exemple, l’image suivante montre la fonction Azure de données de requête en tant que trace :

Une image qui montre une trace complète composée d’étendues de ses étendues enfants.

  • L’étendue sendMessages est divisée en deux étendues enfants : splitToMessages et writeToEventHubs. L’étendue sendMessages nécessite ces deux sous-opérations pour envoyer des messages.

  • Toutes les étendues sont les enfants d’une étendue racine.

  • Les étendues vous permettent de décrire facilement toutes les parties impliquées dans l’étape de requête de la fonction Azure de données de requête. Chaque fonction Azure est une trace. Par conséquent, un passage de bout en bout via le système d’ingestion de Contoso est l’union de trois traces, qui sont toutes les trois des fonctions Azure. Lorsque vous combinez les trois traces et leurs données de télémétrie, vous générez le parcours de bout en bout et décrivez toutes les parties de l’architecture.

Traceurs et contexte de trace W3C

Un traceur est un objet qui contient des informations contextuelles. Dans l’idéal, ces informations contextuelles se propagent au fur et à mesure que les données transitent par les fonctions Azure. Pour propager les informations, l’extension OpenCensus utilise le contexte de trace W3C.

Comme l’indique sa documentation, le contexte de trace W3C est une « spécification qui définit les en-têtes HTTP standard et un format de valeur pour propager les informations de contexte qui permettent des scénarios de suivi distribué ».

Un composant du système, tel qu’une fonction, peut créer un traceur avec le contexte du composant précédent qui effectue l’appel en lisant le parent de trace. Le format d’une trace est le suivant :

Traceparent : [version]-[traceId]-[parentId]-[traceFlags]

Par exemple, si traceparent = 00-0af7651916cd43d8448eb211c80319c-b7ad6b7169203331-00

base16(version) = 00

base16(traceId) = 0af7651916cd43dd8448eb211c80319c

base16(parentId) = b7ad6b7169203331

base16(traceFlags) = 00

L’ID de trace et l’ID parent sont les champs les plus importants. L’ID de trace est un identificateur global unique d’une trace. L’ID parent est un identificateur global unique d’une étendue. Cette étendue fait partie de la trace que l’ID de trace identifie.

Pour plus d’informations, consultez En-tête Traceparent.

Dans les sections suivantes de cet article, il est supposé que base16(version) et base16(traceFlags) sont définis sur 00.

Créer un traceur avec l’extension OpenCensus

Utilisez l’extension OpenCensus spécifique à Azure Functions. N’utilisez pas le package OpenCensus que vous pouvez utiliser dans d’autres cas (par exemple, Python Webapps).

Azure Functions propose de nombreuses liaisons d’entrée et de sortie, et chaque liaison a une façon différente d’incorporer le parent de trace. Pour cette architecture, lorsque des événements et des messages sont consommés, deux fonctions Azure sont déclenchées.

Avant que les deux fonctions ne puissent se déclencher :

  1. Le contexte (caractérisé par l’identificateur de la trace et l’identificateur de l’étendue actuelle) doit être incorporé dans un parent de trace au format de contexte de trace W3C. Cette incorporation dépend de la nature de la liaison de sortie. Par instance, l’architecture utilise Event Hubs comme système de messagerie. Le parent de trace est encodé en octets et incorporé dans l’événement envoyé en tant que propriété d’ID de diagnostic, ce qui permet d’obtenir le contexte de trace approprié dans la liaison de sortie.

    Deux étendues peuvent être liées même si elles ne sont pas parent et enfant. Pour le suivi distribué, l’étendue actuelle pointe vers la suivante. La création d’un lien établit cette relation.

    Le package worker Azure Functions gère l’incorporation et la liaison pour vous.

  2. Une fonction Azure au milieu du flux de bout en bout extrait les informations contextuelles du parent de trace transmis. Utilisez l’extension OpenCensus pour Azure Functions pour cette étape. Au lieu d’ajouter ce processus dans le code de chaque fonction Azure, l’extension OpenCensus implémente un crochet de préinvocation au niveau de l’application de fonction.

    Le crochet de préinvocation :

    • Crée un objet de contexte d’étendue qui contient les informations de l’étendue précédente et déclenche la fonction Azure. Consultez un exemple visuel de cette étape dans la section suivante.
    • Crée un traceur qui contient le contexte d’étendue et crée une nouvelle trace pour la fonction Azure déclenchée.
    • Injecte le traceur dans le contexte d’exécution de la fonction Azure.

    Pour vous assurer que les traces apparaissent dans Application Insights, vous devez appeler la configure méthode pour créer et configurer un exportateur Azure, qui exporte les données de télémétrie.

    L’extension étant au niveau de l’application, les étapes décrites dans cette section s’appliquent à toutes les fonctions Azure d’une application de fonction.

Comprendre et structurer le code

Dans cette architecture, le code dans les fonctions Azure est structuré avec des étendues. Dans Python, créez une étendue OpenCensus à l’aide de l’instruction with pour accéder à la partie de contexte d’étendue du traceur injectée dans le contexte d’exécution de la fonction Azure. La chaîne suivante fournit les détails de l’étendue actuelle et de ses parents :

    with context.tracer.span("nameSpan"):
        # DO SOMETHING WITHIN THAT SPAN

Le code suivant montre les détails de la fonction Azure de données de requête :

import datetime
import logging

import azure.functions as func
from opencensus.extension.azure.functions import OpenCensusExtension
from opencensus.trace import config_integration

OpenCensusExtension.configure()
config_integration.trace_integrations(['requests'])
config_integration.trace_integrations(['logging'])

def main(timer: func.TimerRequest, outputEventHubMessage: func.Out[str], context: func.Context) -> None:

    utc_timestamp = datetime.datetime.utcnow().replace(
        tzinfo=datetime.timezone.utc).isoformat()

    if timer.past_due:
        logging.info('The timer is past due!')

    logging.info(f"Query Data Azure Function triggered. Current tracecontext is:      {context.trace_context.Traceparent}")
    with context.tracer.span("queryExternalCatalog"):
        logging.info('querying the external catalog')
        content = {"key_content_1": "thisisavalue1"}
        content = json.dumps(content)

    with context.tracer.span("sendMessage"):
        logging.info('reading the external catalog')

        with context.tracer.span("splitToMessages"):
            # Do sthg
            logging.info('splitting to messages')

        with context.tracer.span("setMessages"): 
            logging.info('sending messages')
            outputEventHubMessage.set(content)

    logging.info('Python timer trigger function ran at %s', utc_timestamp)

Les points principaux dans ce code sont les suivants :

  • Un OpenCensusExtension.configure appel. Effectuez cet appel dans une seule fonction Azure par application de fonction. Cette action configure l’exportateur Azure pour exporter les données de télémétrie Python, telles que les journaux, les indicateurs de performance et les traces, vers Application Insights.

  • OpenCensus requests et logging intégrations pour configurer la collection de données de télémétrie à partir des modules de requête et de journalisation pour les appels HTTP.

  • Il existe cinq étendues :

    • Une étendue racine qui fait partie du traceur injecté dans le contexte avant l’exécution
    • queryExternalCatalog
    • sendMessage
    • splitToMessages (un enfant de sendMessage)
    • setMessages(un enfant de sendMessage)

Traceurs et étendues

Le diagramme suivant montre comment chaque fois qu’une étendue est créée, le contexte d’étendue du traceur est mis à jour.

Image qui montre les lignes de code de la fonction.

Dans le diagramme précédent :

  1. Une fonction Azure est déclenchée. Un parent de trace est injecté dans l’objet de contexte traceur avec un crochet de préinvocation, appelé par le worker Python avant l’exécution de la fonction.
  2. Une fonction Azure est exécutée. La OpenCensusExtension.configure méthode est appelée, qui initialise un exportateur Azure et active l’écriture de trace dans Application Insights.

Les détails suivants expliquent la relation entre un traceur et une étendue dans cette architecture :

  • L’objet traceur du contexte de fonction Azure contient un champ span_context qui décrit l’étendue racine.
  • Chaque fois que vous créez une étendue dans le code, il crée un identificateur global unique et met à jour la propriété span_context dans l’objet traceur du contexte d’exécution.
  • Le champ span_context contient les champs trace_id et id.
  • Le trace_id n’est jamais mis à jour, mais l’ID est mis à jour vers l’identificateur unique généré.
  • Dans le diagramme précédent, l’étendue racine a deux étendues enfants : queryExternalApi et sendMessage.
    • L’étendue queryExternalApi et l’étendue sendMessage ont un nouvel ID d’étendue différent de root_span_id.
    • L’étendue sendMessage a deux étendues enfants : splitToMessages et setMessages. Leurs ID d’étendue se mettent à jour dans le champ span_context de l’objet traceur du contexte.
  • Pour capturer la relation entre une étendue enfant et son parent, le champ spans_list fournit la traçabilité des étendues sous forme de liste. Dans l’étendue splitToMessages, le champ spans_list contient sendMessage (l’étendue parente) et splitToMessages (l’étendue actuelle). Cette relation parent/enfant est la façon dont vous créez la chaîne d’opérations isolées dans l’exécution d’une fonction Azure.

Chaînez les fonctions à l’aide du champ de contexte

Maintenant que la chaîne d’opérations est organisée dans une fonction Azure, vous pouvez la chaîner aux opérations suivantes effectuées par la fonction Azure suivante.

Diagram qui montre comment les fonctions sont chaînées.

Dans le diagramme précédent :

  • L’étendue setMessages est la dernière étendue de la fonction Azure de données de requête. Le code dans l’étendue envoie un message à Event Hubs et déclenche la fonction Azure suivante. Le champ span_context de l’objet de traceur de contexte contient les informations relatives à cette étendue. Ces informations sont liées au contexte de la fonction Azure de données de requête.
  • Azure Functions Worker ajoute un ID de diagnostic codé en octets dans les propriétés de l’événement envoyé et crée un lien vers la portée racine de la fonction Azure suivante.
  • Le crochet de préinvocation de la fonction Azure de données de processus suivante lit le diagnostic-Id et définit le contexte, qui chaîne les fonctions Azure, celles-ci étant exécutées séparément.

Lorsque la fonction Azure de données de processus envoie un message à la file d’attente Service Bus, le contexte est transmis de la même manière.

Une fois les configurations de surveillance en place, utilisez les fonctionnalités d’Application Insights pour interroger et visualiser les transactions de bout en bout.

Types de données de télémétrie

Il existe plusieurs types de données de télémétrie disponibles dans Application Insights. Le code de cette architecture génère les données de télémétrie suivantes :

  • La donnée de télémétrie de requête émet lorsque vous appelez un protocole HTTP ou déclenchez une fonction Azure. L’entrée du système de Contoso a un déclencheur de minuteur pour la fonction Azure de données de requête qui émet des données de télémétrie de requête.
  • Les données de télémétrie de dépendance sont émises lorsque vous passez un appel à un service Azure ou à un service externe. Lorsque la fonction Azure écrit un événement dans Event Hubs, elle émet des données de télémétrie de dépendance.
  • La donnée de télémétrie de Trace émet à partir des journaux générés par Azure Functions runtime et Azure Functions. La journalisation à l’intérieur de la fonction Azure émet des données de télémétrie de trace.

Contributeurs

Cet article est géré par Microsoft. Il a été écrit à l’origine par les contributeurs suivants.

Auteur principal :

Autres contributeurs :

Pour afficher les profils LinkedIn non publics, connectez-vous à LinkedIn.

Étapes suivantes