Hoy en día es realmente muy habitual ver las siglas CI/CD en cualquier aspecto relacionado con el ámbito del desarrollo: ya sea una conferencia, una oferta de trabajo o un simple listado de prácticas deseables para una compañía de dicho ámbito.
De hecho, las segundas de esas siglas (CD) suelen generar controversia: ¿entrega contínua o despliegue contínuo? ¿Son realmente lo mismo? ¿O son cosas diferentes? Bien, pues en este artículo no queremos centrarnos en ese debate / reflexión, sinó que lo que queremos es generar más controversia, añadiendo unas nuevas siglas al juego: CP (Continuous Profiling).
Bien, la primera de esas siglas creémos que está clara, pues es una constante también presente en las dos siglas que vimos anteriormente. La C es de continuous, por lo tanto, vamos a querer hacer algo de forma contínua, más exactamente profiling, que traducido literalmente es “perfilado”, o más exactamente, el proceso mediante el cuál obtendremos ese perfilado (o perfilaje). Pero, ¿sabemos qué significa exactamente?
¿Qué es el profiling?
Es probable que la mayoría ya hayáis visto alguna vez una imagen como esta, pero si no es el caso, os lo explicamos a continuación.
Básicamente, el profiling consiste en realizar diferentes tipos de análisis de rendimiento dinámicos sobre un programa.
Es decir, análisis realizados sobre la ejecución del programa que tienen por objetivo la mejora del mismo, ya sea en términos
de coste temporal (reducir el tiempo de ejecución) o de coste computacional (reducir el consumo de recursos). En Go, más
especificamente, podemos hacer análisis del consumo de CPU (profile
), del consumo de memoria (heap
) y del uso de
gorrutinas (goroutine
), entre otros, y se suelen usar herramientas como go tool pprof
o pprof
de Google.
¿Por qué de forma contínua?
Bien, ya sabemos qué es el profiling y qué nos aporta, pero, ¿qué implica hacerlo de forma contínua? y ¿por qué queremos hacerlo así?
Lo primero, hacerlo de forma contínua va a implicar hacerlo en el entorno de producción, pues es el entorno dónde se está ejecutando continuamente la aplicación (y como vimos anteriormente, el profiling es un análisis que se hace sobre la ejecución de la misma) y que además, como veremos a continuación, será el entorno en el que nos aportará más valor.
Lo lógico sería pensar: vale, pero ¿afectará eso al rendimiento de mi aplicación? Bien, pues como afirma Jaana B. Dogan, directamente desde Google, en este artículo: el profiling añade un sobrecoste de un 5%, que puede ser reducido con replicación (varias instancias de nuestro servicio). Es decir, un sobrecoste que debería ser asumible, sobretodo si tenemos en cuenta algunos de los beneficios de esta práctica:
-
Nos va a permitir detectar aquellos problemas de rendimiento que solo sucedan en producción, ya sea porqué nuestros entornos de pruebas no sean idénticos al de producción, o porqué el uso de la aplicación guiado por nuestras pruebas no es igual al uso realizado por los propios usuarios.
-
Nos va a proporcionar una foto más parecida al consumo real, lo que nos permitirá optimizar nuestra aplicación de una forma más eficiente.
-
Nos va a permitir identificar y entender dónde y porqué se acumula la contención así como optimizarla.
-
Nos va a permitir medir de una forma más realista el impacto en el rendimiento de las nuevas versiones, por ejemplo, comparando el rendimiento entre las canary con las versiones en producción.
-
Nos va a permitir enriquecer nuestras trazas distribuidas correlacionándolas con muestras de perfiles, para comprender mejor la o las causas raíz de la latencia.
Stackdriver Profiler (GCP)
Lo más normal sería que ahora estéis pensando: “muy bien, me habéis convencido, pero ¿por dónde empiezo?” Porqué al final, necesitamos que, de algún modo, haya una pieza conectada con nuestra aplicación, que vaya realizando esos análisis y tomando notas de los resultados, y todo de forma automática.
La primera opción, y probablemente la más habitual, es hacer uso de la herramienta Stackdriver Profiler de Google, la cuál se puede usar de forma gratuita y que, básicamente, es el resultado de mucho trabajo de investigación documentado en este paper publicado por la propia compañía.
Ésta, en lugar de usar el servidor de pprof
, como comentamos anteriormente, lo que nos permite es añadir un agente de
Stackdriver en nuestra aplicación, que, utilizando la API de pprof
internamente, ejecuta periódicamente el profiler
y envía los resultados a la nube de Google (GCP). Por esa razón, ésta no es compatible con los handlers de
net/http/pprof
. No obstante, la configuración de la misma en nuestro proyecto se limitará a
solo dos pasos muy sencillos:
- Lo primero, añadir una nueva dependencia a nuestro proyecto:
go get cloud.google.com/go/profiler
- Y segundo, inicializar dicha dependencia con los valores de configuración adecuados (servicio y version e identificador del proyecto en GCP):
if err := profiler.Start(profiler.Config{
Service: "gophersapi-service",
ServiceVersion: "1.0",
ProjectID: "gophersapi", // optional on GCP
}); err != nil {
log.Fatalf("Cannot start the profiler: %v", err)
}
Una vez iniciada nuestra aplicación con esa configuración, el paquete que hemos configurado reportará durante diez segundos en intervalos de un minuto. Una vez el profiler haya recopilado unos pocos datos, entonces podremos acceder a su portal y empezar a observar los resultados.
En él tendremos varias opciones de filtrado de datos y podremos obtener diferentes visualizaciones como las presentes en esta animación. Finalmente, “solo” nos quedará hacer nuestro trabajo, que será nada más y nada menos que interpretar esos gráficos para entender qué está sucediendo en nuestra aplicación y ver cómo podemos hacer uso de ese conocimiento para mejorar su rendimiento. Labor que daría para un artículo entero y en la que no queremos entrar en detalle aquí, pero que podéis seguir investigando en esta guía en inglés.
Además, debemos tener en cuenta que el uso de Stackdriver Profiler no nos obliga a hacer uso de su agente. Así que, si lo
que queremos es usar la herramienta en términos de filtrado y visualización, pero queremos tener una flexibilidad y autonomía
mucho mayores a la hora de enviar los resultados de nuestros profilings, entonces podemos hacer uso de la herramienta
pprof-upload
desarrollada por la propia Jaana, la cuál nos permitirá a nosotros
escoger qué profilings vamos a enviar y con qué frecuencia.
profefe
Ahora que ya tenemos el ejemplo funcionando, toca iterarlo un poquito más para terminar de afinarlo. Pues, pese a que hay otras empresas que nos van a ofrecer servicios similares, es probable que haya dos puntos que aún nos hayan quedado en el aire:
-
Por un lado, evitar el envío de datos potencialmente críticos de nuestra aplicación a un sistema de terceros, con lo que ello implica.
-
Y, por otro lado, porqué nos puede interesar tener un histórico de varios meses (Stackdriver Profiler y otras herramientas similares solo guardan los datos de hasta los últimos 30 días). Por qué, ¿quién no ha estado de on-call (guardia) y ha preferido reiniciar el servicio para estabilizarlo de nuevo que ponerse a hacer un profiling a las cuatro de la mañana? Pues contra más extenso sea el histórico, más margen tendremos para revisar lo que sucedió esa fatídica noche.
Y fueron precisamente esas dos premisas con las que Vladimir Varankin empezó su proyecto profefe, el cuál define bajo el lema de “continuously collect profiling data for long-term postmortem analysis” y que básicamente viene a ser un sistema abierto de continuous profiling desarrollado en Go.
Profefe es un sistema basado en dos componentes principales:
-
profefe-collector
, que es el encargado de exponer una API RESTful a través de la cuál se pueden almacenar los resultados de unpprof
con algunos metadatos y guardarlo en un almacenamiento indexado que posteriormente puede ser consultado. -
profefe-agent
, que es la librería que integraríamos en nuestra aplicación como sustitivo del servidorpprof
convencional, y que de un modo algo similar al agente de Stackdriver, será el encargado de ir coleccionando todos los perfiles de nuestra aplicación.
Así que no lo dudéis, si estáis pensando en empezar a hacer continuous profiling de vuestras aplicaciones, echadle un vistazo al repositorio y a este artículo, dónde el propio autor de la herramienta explica de forma más detallada el diseño y el funcionamiento de la misma.
Y para terminar, os dejamos una pregunta:
¿Cuál ha sido vuestro mayor logro / descubrimiento haciendo profiling de vuestras aplicaciones?
¡Venga va, que no hace falta que haya sido con profiling contínuo!
Ya sabéis, si tenéis cualquier duda o comentario podéis dejarlo en los comentarios o en nuestro Twitter @FriendsofGoTech.