Profiler des applications Go

Cette page explique comment modifier votre application Go pour capturer les données de profilage et les envoyer à votre projet Google Cloud. Pour obtenir des informations générales sur le profilage, consultez la page Concepts du profilage.

Types de profil pour Go :

  • Temps CPU
  • Tas de mémoire
  • Tas de mémoire alloué
  • Contention (mutex Go)
  • Threads (goroutine Go)

Versions de langages compatibles avec Go :

Versions d'agent de profilage compatibles :

  • La version la plus récente de l'agent est compatible. En général, les versions datant de plus d'un an ne sont pas compatibles. Nous vous recommandons d'utiliser la version la plus récente de l'agent.

Systèmes d'exploitation compatibles :

  • Linux. Le profilage d'applications Go est compatible avec les noyaux Linux dont la bibliothèque C standard est mise en œuvre avec glibc ou musl. Pour obtenir des informations de configuration spécifiques aux noyaux Linux Alpine, reportez-vous à la page Exécution sous Linux Alpine.

Environnements compatibles :

  • Compute Engine
  • Google Kubernetes Engine (GKE)
  • Environnement flexible App Engine
  • Environnement standard App Engine (nécessite Go 1.11 ou version supérieure)
  • Pour en savoir plus sur les exigences de configuration supplémentaires concernant l'exécution en dehors de Google, consultez la page Profiler des applications s'exécutant en dehors de Google Cloud.

Activer l'API Profiler

Avant d'utiliser l'agent de profilage, assurez-vous que l'API Profiler sous-jacente est activée. Vous pouvez vérifier l'état de l'API et l'activer, si nécessaire, à l'aide de Google Cloud CLI ou de Google Cloud Console :

CLI gcloud

  1. Si vous n'avez pas encore installé Google Cloud CLI sur votre poste de travail, consultez la documentation de Cloud CLI.

  2. Exécutez la commande suivante :

    gcloud services enable cloudprofiler.googleapis.com
    

Pour en savoir plus, consultez les sections sur gcloud services

Console Google Cloud

  1. Enable the required API.

    Enable the API

  2. Si API activée s'affiche, cela signifie que l'API est déjà activée. Sinon, cliquez sur le bouton Activer.

Attribuer un rôle IAM à un compte de service

Si vous déployez votre application sur des ressources Google Cloud, si vous utilisez le compte de service par défaut et que vous n'avez pas modifié les autorisations de rôle accordées à ce compte de service, vous pouvez ignorer cette section.

Si vous effectuez l'une des opérations suivantes, vous devez attribuer au compte de service le rôle IAM Agent Cloud Profiler (roles/cloudprofiler.agent):

  1. Vous utilisez le compte de service par défaut, mais vous avez modifié ses autorisations de rôle.
  2. Vous utilisez un compte de service créé par l'utilisateur.
  3. Vous utilisez Workload Identity. Accordez le rôle Agent Cloud Profiler au compte de service Kubernetes.

Vous pouvez attribuer un rôle IAM à un compte de service à l'aide de la console Google Cloud ou de Google Cloud CLI. Par exemple, vous pouvez utiliser la commande gcloud projects add-iam-policy-binding:

gcloud projects add-iam-policy-binding GCP_PROJECT_ID \
    --member serviceAccount:MY_SVC_ACCT_ID@GCP_PROJECT_ID.iam.gserviceaccount.com \
    --role roles/cloudprofiler.agent

Avant d'utiliser la commande précédente, remplacez les éléments suivants:

  • GCP_PROJECT_ID : ID de votre projet
  • MY_SVC_ACCT_ID : nom de votre compte de service.

Pour en savoir plus, consultez la page Gérer l'accès aux projets, aux dossiers et aux organisations.

Utiliser Cloud Profiler

Dans tous les environnements compatibles, vous pouvez utiliser Profiler en important le package dans votre application, puis en y initialisant Profiler le plus tôt possible.

Vous pouvez activer le profilage de contention de mutex ("Contention" dans l'interface) en définissant l'option de configuration MutexProfiling sur true.

Pour en savoir plus sur l'API Profiler, y compris sur toutes les options de configuration, consultez la documentation de l'API publique.

Compute Engine

Pour Compute Engine, dans profiler.Config, définissez Service avec le nom du service profilé et éventuellement ServiceVersion avec la version du service :


// snippets is an example of starting cloud.google.com/go/profiler.
package main

import (
	"cloud.google.com/go/profiler"
)

func main() {
	cfg := profiler.Config{
		Service:        "myservice",
		ServiceVersion: "1.0.0",
		// ProjectID must be set if not running on GCP.
		// ProjectID: "my-project",

		// For OpenCensus users:
		// To see Profiler agent spans in APM backend,
		// set EnableOCTelemetry to true
		// EnableOCTelemetry: true,
	}

	// Profiler initialization, best done as early as possible.
	if err := profiler.Start(cfg); err != nil {
		// TODO: Handle error.
	}
}

Si les dépendances de votre code source sont récupérées manuellement, vous devrez peut-être ajouter les éléments suivants à votre script de compilation ou à votre Dockerfile :

go get cloud.google.com/go/profiler

GKE

Pour GKE, dans profiler.Config, définissez Service avec le nom du service profilé et éventuellement ServiceVersion avec la version du service :


// snippets is an example of starting cloud.google.com/go/profiler.
package main

import (
	"cloud.google.com/go/profiler"
)

func main() {
	cfg := profiler.Config{
		Service:        "myservice",
		ServiceVersion: "1.0.0",
		// ProjectID must be set if not running on GCP.
		// ProjectID: "my-project",

		// For OpenCensus users:
		// To see Profiler agent spans in APM backend,
		// set EnableOCTelemetry to true
		// EnableOCTelemetry: true,
	}

	// Profiler initialization, best done as early as possible.
	if err := profiler.Start(cfg); err != nil {
		// TODO: Handle error.
	}
}

Si les dépendances de votre code source sont récupérées manuellement, vous devrez peut-être ajouter les éléments suivants à votre script de compilation ou à votre Dockerfile :

go get cloud.google.com/go/profiler

App Engine

Pour les environnements flexible et standard App Engine, les ajouts de code sont presque identiques à ceux des environnements Compute Engine et GKE. Il existe toutefois une exception. Dans les deux environnements App Engine, les paramètres Service et ServiceVersion sont dérivés de l'environnement. Vous n'avez donc pas besoin de les spécifier.


// appengine is an example of starting cloud.google.com/go/profiler on
// App Engine.
package main

import (
	"cloud.google.com/go/profiler"
)

func main() {
	// Profiler initialization, best done as early as possible.
	if err := profiler.Start(profiler.Config{
		// Service and ServiceVersion can be automatically inferred when running
		// on App Engine.
		// ProjectID must be set if not running on GCP.
		// ProjectID: "my-project",
	}); err != nil {
		// TODO: Handle error.
	}
}

Lorsque vous exécutez l'application en local, définissez les paramètres ProjectID (ID de votre projet Google Cloud) et Service dans profiler.Config, car ils ne peuvent pas être dérivés d'un environnement local. Vous n'avez pas besoin de définir ServiceVersion.

Si vous utilisez l'environnement standard App Engine, consultez la page Migrer votre application vers Go 1.11 pour obtenir des informations détaillées sur les modifications que vous devrez peut-être apporter à votre application. De plus, vous devez utiliser Google Cloud CLI en version 226.0.0 ou ultérieure. Pour mettre à jour Google Cloud CLI, exécutez la commande suivante :

gcloud components update

Pour exécuter votre application, procédez comme suit :

  1. Mettez à jour les dépendances :

    go get cloud.google.com/go/profiler
    
  2. Déployez l'application dans votre environnement flexible ou standard App Engine :

    gcloud app deploy [DEPLOYMENT]
    

    DEPLOYMENT est le chemin d'accès à votre fichier de configuration. Par exemple, DEPLOYMENT pourrait être main/app.yaml.

Analyser des données

Une fois que Profiler a collecté des données, vous pouvez les afficher et les analyser dans son interface.

Dans la console Google Cloud, accédez à la page Profiler:

Accéder à Profiler

Vous pouvez également accéder à cette page à l'aide de la barre de recherche.

Arguments de nom et de version de service

Lorsque vous chargez l'agent Profiler, vous devez spécifier un argument de nom de service et un argument facultatif de version de service pour le configurer.

Le nom de service permet à Profiler de collecter des données de profilage pour toutes les instances dupliquées de ce service. Le service du profileur assure un taux de collecte de l'ordre d'un profil par minute, en moyenne, et ce pour chaque nom de service dans chaque combinaison de zones et de versions de service.

Par exemple, si deux versions d'un service s'exécutent sur des instances dupliquées dans trois zones, le profileur créera en moyenne six profils par minute pour ce service.

Si vous utilisez différents noms de service pour vos instances dupliquées, votre service sera profilé plus souvent que nécessaire, entraînant une surcharge proportionnelle.

Lorsque vous sélectionnez un nom de service, respectez ces instructions :

  • Choisissez un nom qui représente clairement le service dans votre architecture d'application. Le choix du nom de service est moins important si vous n'exécutez qu'un seul service ou qu'une seule application. En revanche, il est plus important lorsque votre application s'exécute sous la forme d'un ensemble de microservices, par exemple.

  • Assurez-vous de ne pas utiliser de valeurs spécifiques au processus, telles qu'un ID de processus, dans la chaîne du nom de service.

  • La chaîne du nom de service doit correspondre à l'expression régulière ci-dessous :

    ^[a-z0-9]([-a-z0-9_.]{0,253}[a-z0-9])?$

Nous vous recommandons d'utiliser une chaîne statique, telle que imageproc-service, comme nom de service.

La version de service est facultative. Si vous la spécifiez, Profiler peut regrouper les informations de profilage de plusieurs instances et les afficher correctement. Vous pouvez spécifier ce paramètre pour marquer différentes versions de vos services au fur et à mesure de leur déploiement. L'interface utilisateur de Profiler vous permet de filtrer les données par version de service. De cette façon, vous pouvez comparer les performances des versions de code les plus anciennes et les plus récentes.

La valeur de l'argument service-version est une chaîne de forme libre, mais les valeurs de cet argument ressemblent généralement à des numéros de version, par exemple 1.0.0 ou 2.1.2.

Journaliser avec l'agent

L'agent de profilage peut collecter des informations de débogage dans ses journaux. Par défaut, la journalisation avec l'agent est désactivée.

Pour activer la journalisation de l'agent, définissez l'option DebugLogging sur true lors du démarrage de l'agent :

profiler.Start(profiler.Config{..., DebugLogging: true});

Dépannage

Dans cette section, vous trouverez la liste des problèmes spécifiques au profilage des applications Go. Consultez la page Dépannage pour obtenir de l'aide concernant les problèmes courants.

Comportement Cause Solution
Les profils de temps CPU ne sont pas collectés pour les applications créées avec -buildmode=c-archive. Les profils de tas de mémoire, de contention et de thread sont collectés. Problème GitHub Par défaut, le profilage du processeur n'est pas activé pour les applications Go lorsque l'option -buildmode est définie sur c-archive ou c-shared. Ajoutez un appel à
signal.Notify(make(
chan os.Signal), syscall.SIGPROF)
avant d'appeler profiler.Start.
Réponse à un problème sur GitHub.

Exécuter avec Linux Alpine

L'agent de profilage Go pour Linux Alpine n'est compatible qu'avec les configurations Google Kubernetes Engine.

Erreur d'authentification

Si vous utilisez des images Docker exécutées avec Linux Alpine (par exemple, golang:alpine ou simplement alpine), l'erreur d'authentification suivante peut s'afficher:

connection error: desc = "transport: authentication handshake failed: x509: failed to load system roots and no roots provided"

Sachez que pour que cette erreur apparaisse, vous devez avoir activé la journalisation avec l'agent. Par défaut, l'agent pour Go ne génère aucun message de journal.

L'erreur indique que lorsque les images Docker sont exécutées avec Linux Alpine, les certificats SSL racine ne sont pas installés par défaut. Ces certificats sont nécessaires pour que l'agent de profilage puisse communiquer avec l'API du profileur. Pour résoudre cette erreur, ajoutez la commande apk suivante à votre fichier Dockerfile :

FROM alpine
...
RUN apk add --no-cache ca-certificates

Vous devez ensuite recompiler et redéployer votre application.

Étape suivante