Blog de Amazon Web Services (AWS)

YouCanBook.me optimiza sus aplicaciones gracias a Amazon CodeGuru

Por Sergio Delgado, Engineering Team Lead en YouCanBook.me

 

En YouCanBook.me nos gusta decir que somos “una empresa pequeña que hace grandes cosas”. De un lema en principio tan simple se derivan muchos aspectos de nuestra cultura del día a día, pero especialmente un gran énfasis en la eficiencia de nuestras operaciones. Aunque quedan lejos los primeros años en los que nuestro CTO programó él solo toda la primera versión de nuestra herramienta SaaS, cuando entré en la empresa éramos únicamente cinco desarrolladores, de los cuales sólo tres se encargaban de los servicios back-end, y ninguno se dedicaba a ello al 100%. Las tareas diarias de un programador en una start-up como la nuestra son increíblemente variadas, desde contestar peticiones de soporte de nuestros clientes a refinar el backlog de tareas, definir infraestructura o ayudar con la toma de requisitos. Es un trabajo tan exigente como gratificante, donde los retos nunca terminan, pero que nos obliga a buscar la eficiencia en todo lo que hacemos. Un proyecto no muy bien definido, donde no tenemos muy claro el camino a seguir y que nos puede llevar meses de investigación es un reto para un equipo como el nuestro, y probablemente sea aplazado una y otra vez para priorizar desarrollos más urgentes que aporten valor a nuestros clientes lo antes posible. Para nosotros es muy importante extraer el máximo beneficio a cada desarrollo que hacemos, en el menor tiempo posible.

Fruto de esta filosofía es nuestra implicación con Amazon Web Services y sus diferentes plataformas y herramientas. Aunque las primeras versiones de nuestros servicios de back-end no se ejecutaban en AWS, la migración a cloud nos permitió dejar de preocuparnos de administrar servidores físicos en una empresa de hosting y enfocar nuestros esfuerzos en nuestra lógica de negocio y nuestro código.

Actualmente, nuestros servidores de back-end se basan en tecnología Java y se ejecutan en Elastic Beanstalk, mientras que para el front-end tenemos una mezcla de páginas JSP y aplicaciones cliente React. En las JVM desplegamos ficheros WAR, que compilamos desde el código fuente que almacenamos en repositorios de AWS CodeCommit mediante scripts de AWS CodeBuild. Así mismo, toda nuestra monitorización está basada en logs y métricas de Amazon CloudWatch.

Una característica interesante es que tenemos los distintos entornos (desarrollo, pre-producción, producción, analíticas, etc.) totalmente separados pero los gestionamos mediante AWS Organizations. Los usuarios de AWS Identity and Access Management (IAM) se crean en una cuenta raíz, y luego asumen roles para operar en el resto de ellas.

Con todo esto, tres personas gestionamos una media docena de servicios, sobre cuatro entornos distintos, corriendo en decenas de instancias y, sencillamente, todo funciona.

Nuestro problema

Aunque nuestros servicios están todos desarrollados con tecnología Java, la verdad es que no todos ellos comparten el mismo stack tecnológico. A lo largo de los años se han ido migrando a frameworks más modernos y estandarizando su diseño, pero no todos ellos han podido ser puestos al día todavía. Éramos conscientes de que algunos servicios tenían claros problemas de rendimiento y nos generaban cuellos de botella cuando había grandes picos de carga, sobre todo la parte del código más antigua y basada en tecnologías legacy. Nuestra solución a corto plazo era sobredimensionar esos servicios concretos, con el consiguiente gasto extra, y a largo plazo reimplementarlos siguiendo la arquitectura de nuestras aplicaciones más modernas. Pero al mismo tiempo estábamos seguros de que podríamos conseguir mejoras muy rápidas si invertíamos en alguna herramienta de análisis de rendimiento, o APM (Application Performance Monitoring). Sabíamos que existían muchas en el mercado y algunos de nosotros teníamos experiencia trabajando con alguna de ellas, y buenas referencias de otras. Así que creamos un proyecto de mejoras de rendimiento en nuestro roadmap, investigamos un poco qué productos tenían mejor pinta y… no mucho más. El día a día siempre nos podía y nunca encontrábamos el tiempo para poder dedicarle semanas a contactar con un par de proveedores, instalar las herramientas, analizar nuestros servicios en el periodo de prueba, comparar los resultados, etc. Por eso las tareas de rendimiento constantemente se iban postergando, siempre a la espera de alguna época del año donde no tuviéramos mucho más que hacer. Lo que no iba a pasar nunca.

 

Llega Amazon CodeGuru Profiler

Una de las buenas costumbres que tenemos es estar muy atentos a todas las novedades de Amazon Web Services y generalmente somos muy rápidos poniéndolas a prueba, sobre todo cuando no conllevan modificaciones en el código de nuestras aplicaciones.

Además, apoyarnos en los productos de AWS nos ofrece una ventaja extra. Como política de empresa, nos encanta poder definir nuestro modelo de seguridad sobre los usuarios, roles y permisos de IAM, en lugar de tener que crear cuentas y usuarios independientes en otras plataformas. Esta rigurosidad a la hora de gestionar los accesos y permisos de los usuarios de nuestra infraestructura nos permite someternos a auditorías de seguridad regularmente y superarlas con éxito sin invertir demasiado esfuerzo para una empresa de nuestro tamaño. De hecho, nuestras certificaciones de seguridad son uno de nuestros valores diferenciales con respecto a nuestra competencia.

Es por esto que inmediatamente reconocimos la oportunidad que nos ofrecía CodeGuru Profiler cuando fue anunciado en la conferencia re:Invent a finales de 2019. Sobre el papel, otras de las herramientas APM que queríamos evaluar parecían ofrecer más información o un mayor conjunto de métricas pero la gran pregunta era si nos serían útiles. ¿De qué nos serviría tener pantallas y pantallas de informes si no estábamos seguros de lo que significaban o no nos ofrecían recomendaciones que pudiéramos implementar inmediatamente? CodeGuru parecía simple, pero en lugar de verlo como una desventaja teníamos la intuición de que podría ser un gran beneficio para nosotros. Probándolo podríamos analizar los resultados en horas, no semanas, y averiguar si de verdad nos aportaba valor a la hora de descubrir las partes del código que nos era más necesario optimizar.

Lo mejor de CodeGuru Profiler es que nos llevaría más tiempo debatir sobre si usarlo o no que simplemente instalarlo y ver qué tal. Un único desarrollador, el responsable de la infraestructura, fue capaz de instalar el agente de CodeGuru en todas nuestras JVM en una tarde. Ejecutamos CodeGuru Profiler directamente en el entorno de producción, lo que nos permitió desde un principio analizar las latencias e identificar los cuellos de botella usando datos reales de producción, especialmente después de sufrir un pico de carga. Nos hemos dado cuenta que nos es mucho más fácil y realista que simular carga de trabajo sintética, y no hay posibilidad de que la definamos de manera incorrecta o bajo supuestos que no sean ciertos. Todo lo que encontramos en CodeGuru es el comportamiento auténtico de nuestros sistemas.

 

Pre-optimización

 

Post-optimización

 

Análisis

Los flame graphs de CodeGuru Profiler nos fueron muy fáciles de entender. Simplemente seleccionamos el intervalo de tiempo en el que hemos detectado un problema de escalado o un pico de carga de trabajo y, para cada aplicación de servidor, vemos las clases y métodos Java que han contribuido más a las latencias de las peticiones de nuestros usuarios. Como nuestro negocio se basa en integrarnos con distintos sistemas de calendarios externos (Google, Outlook, CalDAV…) gran parte de esa latencia es inevitable, pero rápidamente encontramos dos estrategias claras a la hora de optimizar nuestro código:

  • Identificar métodos que no hacen peticiones a sistemas de terceros pero que sin embargo sumaban un tiempo significativo a las latencias. En estos casos, CodeGuru Profiler además nos ofrecía recomendaciones para optimizar el código y mejorar su rendimiento.
  • Ver exactamente qué porcentaje de los tiempos de respuesta se debían a qué tipo de peticiones a los calendarios subyacentes. Algunas peticiones (como crear un evento) no tienen mucho margen de mejora, pero sí descubrimos consultas que se realizaban con mucha más frecuencia de lo que habíamos estimado, y que podrían evitarse en gran medida con una política de cacheo más adecuada.

Nos pusimos manos a la obra y en un par de semanas generamos unos quince tickets en nuestro backlog, la mayoría de los cuales estuvieron desplegados en producción durante el primer mes. Típicamente, cada ticket ha requerido horas de desarrollo, en lugar de días, y no hemos tenido que deshacer ninguno de ellos ni hemos identificado ningún falso positivo en las recomendaciones que nos da CodeGuru.

 

Resultados

Hemos sido capaces de optimizar nuestro servicio más antiguo y con peor rendimiento de forma que su latencia se ha reducido en un 15% para el percentil 95 en un día laboral típico. Además, nuestras gráficas de tiempos de respuesta son mucho más planas que antes, ya que hemos eliminado picos de latencia que ocurrían de forma semi-regular.

La mejora es tal que estamos encantados de haber descubierto que, en uno de los últimos picos de carga que hemos tenido en la plataforma, este servicio ya no fue el cuello de botella del sistema, aguantando todas las peticiones sin problema y sin bloquear al resto de nuestras APIs.

Esto nos ha ahorrado probablemente no sólo el dinero que costaban las instancias extra que ya no necesitamos, y que teníamos en ejecución sólo para ser capaces de dar servicio en estos escenarios, sino decenas de horas-persona en refactorizaciones más profundas sobre el código legacy, justo lo que estábamos tratando de evitar.

Otro de nuestros servicios de back-end, que normalmente sostiene una carga de trabajo muy elevada en horario laboral, ha mejorado aún más, reduciendo su latencia en hasta un 40%. De hecho, en una ocasión introdujimos un error en la configuración de su autoescalado y redujimos el número de instancias de ejecución a sólo una máquina. ¡Tardamos un par de horas en darnos cuenta de nuestro fallo porque esa única instancia pudo encargarse de todas las peticiones de nuestros usuarios sin problema alguno!

 

El futuro

Nuestro uso de CodeGuru Profiler es muy simple pero nos ha sido tremendamente valioso. A medio plazo estamos pensando hacer un muestreo de parte de nuestros servidores o de las peticiones de usuarios en lugar de analizar todo el tráfico de producción, por eficiencia. No obstante, no es una tarea demasiado urgente para nosotros, ya que nuestros servicios están funcionando perfectamente bien con el análisis de rendimiento activado, y el impacto sobre los tiempos de respuesta para nuestros usuarios es imperceptible.

¿Hasta cuándo pensamos tener activado CodeGuru Profiler? La respuesta es clara: indefinidamente. El haber mejorado partes problemáticas de nuestros servicios que más o menos ya conocíamos es un muy buen resultado, pero la visibilidad que nos va a ofrecer en futuros picos de carga es extraordinariamente valiosa. Porque, no nos engañemos, hemos eliminado varios cuellos de botella pero tendremos otros ocultos, o los introduciremos con nuevos desarrollos. Con las métricas y alarmas de AWS CloudWatch detectaremos cuando esto suceda y sabremos qué es lo que ha pasado, pero a partir de ahora, AWS CodeGuru nos ayudará a saber el porqué.

Si tiene un problema similar al nuestrode nosotros, o quiere prevenirlo, le invitamos a que se familiarice másmas con Amazon CodeGuru.

 

Sobre YouCanBook.me

YouCanBook.me permite agendar reuniones de manera online para tu negocio o equipo, sea del tamaño que sea. Elimina la necesidad de buscar huecos libres mandando y respondiendo emails, permitiendo que tu cliente cree la cita directamente en tu calendario.

Desde su concepción en 2011, nuestra empresa sigue siendo pequeña, eficiente, autofinanciada, 100% remota y dedicada a resolver problemas de agenda para usuarios de todo el mundo. Con apenas 15 empleados entre el Reino Unido, España y Estados Unidos, conseguimos dar servicio a decenas de miles de clientes, gestionando más de un millón de reuniones cada mes.

 


Sobre el autor

Sergio Delgado se define como programador de vocación. En veinticinco años desarrollando software, ha pasado por hacer videojuegos en C++, máquinas tragaperras en Java, plataformas de e-learning en PHP, pelearse con el Dreamweaver, automatizar llamadas en un call-center o dirigir un departamento de I+D. Un día empezó a trabajar en el cloud, y ya no quiere volver a la tierra. Actualmente es líder del equipo de Ingeniería y arquitecto back-end en YouCanBook.me.

Colabora con la comunidad dando charlas en meet-ups o entrevistas en diversos podcasts, y se le puede encontrar en https://www.linkedin.com/in/sergio-antonio-delgado-quero/.

 

Rodney Bozo es un arquitecto de soluciones con AWS que tiene más de 20 años de experiencia apoyando a clientes con la administración de recursos locales y también soluciones basadas en la nube.