Crea perfiles de aplicaciones de Go

En esta página, se describe cómo modificar tu aplicación de Go para capturar datos de creación de perfiles y enviarlos a tu proyecto de Google Cloud. Para obtener información general sobre la creación de perfiles, consulta el artículo sobre conceptos de creación de perfiles.

Tipos de perfil para Go:

  • Tiempo de CPU
  • Montón
  • Montón asignado
  • Contención (exclusión mutua de Go)
  • Subprocesos (goroutine de Go)

Versiones de lenguaje Go compatibles:

Versiones compatibles del agente de generación de perfiles:

  • Se admite la versión más reciente del agente. Por lo general, no se admiten las actualizaciones de más de un año. Te recomendamos usar la versión más reciente del agente.

Sistemas operativos compatibles:

  • Linux. La creación de perfiles de aplicaciones de Go es compatible con kernels de Linux cuya biblioteca C estándar se implementa con glibc o musl. Para obtener información de configuración específica de los kernels Linux Alpine, consulta la sección sobre ejecución en Linux Alpine.

Entornos compatibles:

  • Compute Engine
  • Google Kubernetes Engine (GKE)
  • Entorno flexible de App Engine
  • Entorno estándar de App Engine (requiere Go 1.11 o superior)
  • Fuera de Google Cloud (para obtener información sobre los requisitos de configuración adicionales, consulta cómo generar perfiles de aplicaciones fuera de Google Cloud).

Habilita la API de Profiler

Antes de usar el agente de generación de perfiles, asegúrate de que la API de Profiler subyacente esté habilitada. Puedes verificar el estado de la API y habilitarla, si es necesario, con Google Cloud CLI o la consola de Google:

CLI de gcloud

  1. Si aún no instalaste Google Cloud CLI en tu estación de trabajo, consulta la documentación de Google Cloud CLI.

  2. Ejecuta el siguiente comando:

    gcloud services enable cloudprofiler.googleapis.com
    

Para obtener más información, consulta gcloud services

Consola de Google Cloud

  1. Enable the required API.

    Enable the API

  2. Si se muestra API habilitada, la API ya está habilitada. De lo contrario, haz clic en el botón Habilitar.

Otorga un rol de IAM a la cuenta de servicio

Si implementas tu aplicación en recursos de Google Cloud y usas la cuenta de servicio predeterminada y no modificaste los roles otorgados a esa cuenta de servicio, puedes omitir esta sección.

Si realizas alguna de las siguientes acciones, debes otorgarle a la cuenta de servicio el rol de IAM de agente de Cloud Profiler (roles/cloudprofiler.agent):

  1. Estás usando la cuenta de servicio predeterminada, pero modificaste sus otorgamientos de roles.
  2. Estás usando una cuenta de servicio creada por el usuario.
  3. Si usas Workload Identity, otorga el rol de Agente de Cloud Profiler a la cuenta de servicio de Kubernetes.

Puedes otorgar un rol de IAM a una cuenta de servicio mediante la consola de Google Cloud o Google Cloud CLI. Por ejemplo, puedes usar el comando 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

Antes de usar el comando anterior, reemplaza lo siguiente:

  • GCP_PROJECT_ID: ID del proyecto
  • MY_SVC_ACCT_ID: Es el nombre de la cuenta de servicio.

Para obtener información detallada, consulta Administra el acceso a proyectos, carpetas y organizaciones.

Usa Cloud Profiler

En todos los entornos compatibles, usarás Profiler para importar el paquete en tu aplicación y, luego, inicializarlo lo antes posible.

Puedes habilitar la creación de perfiles de contención de exclusión mutua (“Contención“ en la interfaz) si estableces la opción de configuración MutexProfiling en true.

Para obtener más información sobre la API de Profiler, incluidas todas las opciones de configuración, consulta los documentos de la API pública.

Compute Engine

Para Compute Engine, en profiler.Config, configura Service con un nombre para el servicio para el que se crea el perfil y, de manera opcional, configura ServiceVersion con la versión del servicio:


// 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 tienes dependencias en tu código fuente que se recuperan de forma manual, es posible que debas agregar lo siguiente a tu secuencia de comandos de compilación o Dockerfile:

go get cloud.google.com/go/profiler

GKE

Para GKE, en profiler.Config, configura Service con un nombre para el servicio para el que se crea el perfil y, de manera opcional, configura ServiceVersion con la versión del servicio:


// 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 tienes dependencias en tu código fuente que se recuperan de forma manual, es posible que debas agregar lo siguiente a tu secuencia de comandos de compilación o Dockerfile:

go get cloud.google.com/go/profiler

App Engine

Para el entorno flexible de App Engine y el entorno estándar de App Engine, las incorporaciones de código son casi idénticas a las de Compute Engine y GKE. Hay una excepción. En ambos entornos de App Engine, los parámetros Service y ServiceVersion derivan del entorno, por lo que no tienes que especificarlos.


// 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.
	}
}

Cuando ejecutes la aplicación de manera local, configura los parámetros ProjectID (el ID de tu proyecto de Google Cloud) y Service en profiler.Config, ya que no se pueden derivar de un entorno local. No es necesario que configures ServiceVersion.

Si usas el entorno estándar de App Engine, consulta cómo migrar tu aplicación a Go 1.11 para obtener información detallada sobre los cambios que podrías tener que realizar en tu aplicación. Además, debes usar la versión 226.0.0 o posterior de Google Cloud CLI. Para actualizar la CLI de Google Cloud, ejecuta el siguiente comando:

gcloud components update

Para ejecutar tu aplicación, sigue estos pasos:

  1. Actualiza las dependencias:

    go get cloud.google.com/go/profiler
    
  2. Implementa la aplicación en tu entorno flexible de App Engine o en tu entorno estándar de App Engine:

    gcloud app deploy [DEPLOYMENT]
    

    donde DEPLOYMENT es la ruta de acceso a tu archivo de configuración. Por ejemplo, DEPLOYMENT podría ser main/app.yaml.

Analiza datos

Una vez que Profiler haya recopilado los datos, podrás verlos y analizarlos con la interfaz de Profiler.

En la consola de Google Cloud, ve a la página Profiler:

Ve a Profiler.

También puedes usar la barra de búsqueda para encontrar esta página.

Argumentos de versión y nombre del servicio

Cuando cargas el agente de Profiler, especificas un argumento de nombre del servicio y un argumento de la versión del servicio opcional para configurarlo.

El nombre del servicio permite que Profiler recopile datos de generación de perfiles para todas las réplicas de ese servicio. El servicio del generador de perfiles garantiza una tasa promedio de recopilación de un perfil por minuto para cada nombre de servicio en cada combinación de zonas y versiones del servicio.

Por ejemplo, si tienes un servicio con dos versiones que se ejecutan en réplicas en tres zonas, el generador de perfiles creará un promedio de 6 perfiles por minuto para ese servicio.

Si usas nombres de servicio diferentes para tus réplicas, se generarán los perfiles del servicio con más frecuencia que la necesaria y con una sobrecarga más alta.

Cuando selecciones un nombre de servicio, ten en cuenta lo siguiente:

  • Elige un nombre que represente de forma clara el servicio en la arquitectura de tu aplicación. La elección del nombre del servicio es menos importante si solo ejecutas un único servicio o aplicación. Por ejemplo, es más importante si tu aplicación se ejecuta como un conjunto de microservicios.

  • Asegúrate de no usar ningún valor específico del proceso, como un ID de proceso, en la string de nombre del servicio.

  • La string de nombre del servicio debe coincidir con esta expresión regular:

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

Un buen lineamiento es usar una string estática, como imageproc-service, como nombre del servicio.

La versión del servicio es opcional. Si especificas la versión del servicio, Profiler puede agregar información de generación de perfiles de varias instancias y mostrarla correctamente. Se puede usar para marcar diferentes versiones de tus servicios a medida que se implementan. La IU de Profiler te permite filtrar los datos por versión del servicio. De esta manera, puedes comparar el rendimiento de las versiones anteriores y más recientes del código.

El valor del argumento de la versión del servicio es una string de formato libre, pero los valores de este argumento suelen verse como números de versión, por ejemplo, 1.0.0 o 2.1.2.

Registro de agente

El agente de creación de perfiles puede mostrar la información de depuración en sus registros. De forma predeterminada, el registro de agente está inhabilitado.

Para habilitar el registro de agente, configura la opción DebugLogging en true cuando inicies el agente:

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

Soluciona problemas

En esta sección, se enumeran los problemas específicos de la creación de perfiles de aplicaciones Go. Consulta la página Solución de problemas a fin de obtener ayuda para resolver problemas comunes.

Comportamiento Causa Solución
Los perfiles de tiempo de CPU no se recopilan para las aplicaciones compiladas con -buildmode=c-archive. Se recopilan perfiles de montón, contención y subprocesos. Errores de GitHub De forma predeterminada, la creación de perfiles de la CPU no está habilitado para las aplicaciones de Go cuando la marca -buildmode es c-archive o c-shared. Agrega una llamada a
signal.Notify(make(
chan os.Signal), syscall.SIGPROF)
antes de llamar a profiler.Start.
Respuesta al error de GitHub.

Ejecuta con Linux Alpine

El agente de creación de perfiles de Go para Linux Alpine solo es compatible con las configuraciones de Google Kubernetes Engine.

Error de autenticación

Si usas imágenes de Docker que se ejecutan con Linux Alpine (como golang:alpine o solo alpine), es posible que veas el siguiente error de autenticación:

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

Ten en cuenta que, para ver el error, debes tener habilitado el registro de agente. De forma predeterminada, el agente de Go no genera ningún mensaje de registro.

El error indica que las imágenes de Docker con Linux Alpine no tienen los certificados SSL raíz instalados de forma predeterminada. Esos certificados son necesarios para que el agente de creación de perfiles se comunique con la API de Profiler. Para resolver este error, agrega el siguiente comando apk a tu Dockerfile:

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

Luego, debes volver a compilar y volver a implementar tu aplicación.

¿Qué sigue?