Uno de los servicios más utilizados en AWS es el de base de datos denominado RDS, por sus siglas Relational Database Service. RDS tiene soporte para múltiples motores de bases de datos relacionales y, usualmente, he observado que las aplicaciones desplegadas en AWS se conectan a este servicio de manera directa, mediante los endpoints que RDS nos expone, tanto para las instancias de escritura como para las instancias de lectura. Esto en sí no está mal, pero varios equipos de desarrollo desconocen la existencia de RDS Proxy y los beneficios que este nos brinda.
El objetivo del presente artículo es elaborar respecto a esos beneficios mediante una serie de pruebas sintéticas que comparan el acceso directo a la base de datos, en contraposición a usar el servicio de Proxy como intermediario. Antes de abordar los resultados de estas pruebas, vamos a repasar qué es RDS Proxy.
En el mundo actual, la demanda de aplicaciones y servicios en la nube está creciendo exponencialmente. Como resultado, es esencial contar con bases de datos altamente disponibles y escalables para garantizar un rendimiento óptimo y una experiencia sin interrupciones para los usuarios. AWS ofrece una solución efectiva para manejar este desafío: AWS RDS Proxy.
¿Qué es AWS RDS Proxy?
AWS RDS Proxy es un servicio de proxy totalmente administrado diseñado para mejorar la escalabilidad, la disponibilidad y el rendimiento de las bases de datos administradas de Amazon RDS. El servicio actúa como un intermediario entre las aplicaciones y las bases de datos, mejorando la capacidad de manejo de conexiones y optimizando la utilización de recursos, especialmente en aplicaciones con múltiples conexiones concurrentes.
Beneficios de AWS RDS Proxy
-
Mayor rendimiento: El servicio de proxy administra y multiplexa automáticamente las conexiones de la aplicación a la base de datos, reduciendo la carga en las instancias de base de datos y mejorando la escalabilidad. Nos brinda un pool de conexiones hacia la base de datos, reduciendo la carga de cómputo en la base de datos, ya que abrir una conexión requiere recursos de CPU y memoria. RDS Proxy mantiene una conexión persistente con la base de datos, permitiendo una reutilización eficiente de las conexiones y reduciendo la latencia en comparación con el enfoque tradicional de abrir y cerrar conexiones con cada solicitud.
-
Resiliencia y alta disponibilidad: RDS Proxy facilita el proceso de failover en situaciones de error, permitiendo que la aplicación se recupere rápidamente y minimizando el tiempo de inactividad. Según la documentación de RDS Proxy, la reducción en el tiempo de recuperación es de hasta un 66%.
-
Autenticación simplificada: RDS Proxy es compatible con la autenticación IAM, lo que permite una gestión más sencilla y segura de las credenciales de acceso.
-
Servicio Administrado: Es un servicio totalmente administrado y ‘serverless’, por lo cual no tenemos que ocuparnos de labores de actualización, parchado, entre otras, que normalmente deberíamos gestionar si desplegamos alguna solución tipo proxy. Además, es compatible con los protocolos que soportan las bases de datos, lo que significa que no tenemos que hacer cambios en nuestro código para conectarnos a este servicio; simplemente apuntamos al ‘endpoint’ correspondiente.
Cómo activar RDS Proxy?
Vamos a emplear la consola de AWS. En el menú de la izquierda de la consola de RDS, seleccionamos ‘Proxies’ y damos clic al botón de ‘Create Proxy’.
En la siguiente pantalla, seleccionamos el tipo de motor relacional (en nuestro caso PostgreSQL), un nombre para el proxy y el tiempo de espera de conexión inactiva (es decir, el tiempo que debe transcurrir para cerrar una conexión inactiva). Por omisión son 30 minutos, pero podemos ajustarlo a nuestras necesidades.
Lo siguiente que debemos hacer es seleccionar la base de datos o cluster sobre el cual vamos a asociar el proxy. Observen que podemos definir que el proxy emplee un porcentaje de las conexiones máximas del cluster que tenemos asociado. Normalmente empleo el 100%, pero puede haber casos en donde tenemos procesos o programas que se conectan directamente a RDS y no queremos que potencialmente no tengan conexiones que poder emplear. También podemos definir el tiempo de espera máximo para obtener una conexión y un SQL para validar la conexión.
Posteriormente, damos los datos para la autenticación. Noten que podemos hacer que solo se pueda hacer autenticación por medio de IAM.
El último punto sería dar los datos para la configuración de conectividad.
Con esto, ya tenemos desplegado nuestro Proxy de RDS. Solo resta que tomemos nota de los ‘endpoints’ de escritura y lectura. Estos se ven en los detalles del proxy, como se ve en la siguiente imagen. Y no se preocupen, para cuando publique este artículo, tanto el proxy, RDS como VPC ya estarán destruidos.
Recuerden que si su aplicación esta creada para separar el tráfico transaccional del de lectura, deben usar ambos ‘endpoints’.
Anteriormente, un desarrollador me preguntó si enviando todas las peticiones al endpoint de escritura/lectura, Proxy se encargaba de canalizar los ‘SELECT’ a las réplicas de lectura y no es así. Enviaría todo a la instancia de escritura/lectura, por eso es importante que nuestras aplicaciones separen este tipo de peticiones y así aprovechar al máximo la infraestructura con la que contamos.
Cómo se cobra RDS Proxy?
Este servicio se factura por la cantidad de vCPU que tenemos asociadas a nuestra base de datos, siendo el mínimo de 2 vCPU. Si empleamos Aurora Serverless v2, el costo se calcula por ACU por hora. Al día de hoy, el costo por vCPU es de $0.015 por hora. En nuestro caso, empleamos un clúster con instancias de tipo db.r6g.large, esta instancia tiene 2 vCPU y la tenemos desplegada en 2 zonas. Por lo que nuestro precio sería:
Max (2 vCPUs, 2 ) = 2 vCPUs
2 instancias x 2 vCPU x 730 horas en un mes x 0.015 USD = 43.80 USD
Costo Mensual de RDS Proxy: 43.80 USD
Pruebas comparativas con AWS RDS Proxy
Ahora bien, después de este preámbulo, explicaré la serie de pruebas comparativas que realicé, utilizando para ello una aplicación sencilla que realiza operaciones clásicas de INSERT y SELECT. El objetivo es evaluar los beneficios del uso de AWS RDS Proxy en términos de tiempo de conexión hacia la base de datos y cuánto demora en recuperarse nuestra aplicación en caso de que la instancia de escritura que estamos usando falle y RDS deba hacer un failover hacia una de las instancias de lectura.
Antes de ver los resultados, utilicé las siguientes premisas:
-
Desplegamos una base de datos RDS Aurora PostgreSQL versión 15.4 con el template de producción, almacenamiento Aurora Standard, instancias de tipo db.r6g.large, Multi-AZ, con ‘Performance Insights’ activado.
-
El aplicativo está escrito en Java 17, sin el uso de JPA u otro ‘framework’ de gestión de entidades y pool de conexiones.
-
La aplicación es ejecutado por línea de comandos desde una instancia de EC2 con sistema operativo Amazon Linux 2023.
-
No apliqué ninguna técnica de optimización que normalmente emplearía en una carga productiva. Por ejemplo, no tengo capas de caché de ningún tipo.
-
El objetivo no es analizar el comportamiento de la aplicación o de la base de datos bajo stress.
-
Cada prueba fue ejecutada 10 veces. El aplicativo emplea 6 threads, cada uno ejecutando 10,000 operaciones de SQL. Los resultados corresponden al promedio de estas ejecuciones.
Prueba de rendimiento de conexiones
Para este caso, realizamos la ejecución del programa bajo las mismas condiciones descritas previamente y antes de iniciar cada conjunto de pruebas reinicié la instancia de escritura de RDS.
Como observamos en la siguiente tabla, obtener una conexión desde RDS Proxy fue virtualmente idéntico a pedirla directamente a RDS. El promedio fue 39 ms para RDS Proxy y 32 ms para RDS.
Me sorprendió una diferencia tan escasa, considerando que RDS Proxy genera una capa adicional entre nuestro sistema y la base de datos, por lo que entendería que existe una mayor latencia; notoriamente baja al ser de unos 7 ms adicionales.
RDS | RDS Proxy | |
---|---|---|
Promedio Tiempo Conexión | 32 ms | 39 ms |
Promedio Tiempo Respuesta | 34 ms | 41 ms |
Al revisar las métricas desde Performance Insights observamos que la aplicación tuve un pico de 11 conexiones y cerca de 176 consultas por segundo.
En contraposición, al conectarnos a RDS Proxy, notamos de inmediato que la cantidad de conexiones subió hasta 24 y curiosamente alcanzamos las 308 consultas por segundo. Aquí comenzamos a notar cómo Proxy mantiene abiertas una cantidad de conexiones a la base de datos y gestiona ese ‘pool’ por nosotros.
Si vemos las métricas de proxy, es claro como se tienen 6 conexiones de cliente (recordemos que nuestro programa emplea 6 hilos) y como estás equivalen a entre 15 y 17 conexiones hacia la base de datos.
Observen cómo al terminar la prueba las conexiones cliente caen a cero, pero las conexiones abiertas a la base permanecen abiertas. Esto se debe a que configuramos un timeout de inactividad de 30 minutos en RDS Proxy.
Resultado
Con RDS Proxy, observamos que el tiempo de conexión aumentó levemente en comparación con una conexión directa a RDS. En la prueba resultó llamativo un aumento en la cantidad de consultas por segundo que se pudieron gestionar.
En términos generales, esta prueba no evidencia un beneficio importante al contraponerlo con el precio a pagar.
Prueba de failover
Para simular un fallo, procedimos a ejecutar un ‘failover’ desde la consola de RDS mientras ejecutamos la misma aplicación y medimos la cantidad de peticiones que fallaron en nuestro aplicativo y los promedios de conexión y respuesta.
RDS | RDS Proxy | |
---|---|---|
Promedio Tiempo Conexión | 39 ms | 38 ms |
Promedio Tiempo Respuesta | 41 ms | 41 ms |
Cantidad de Fallos | 6,116/10,000 | 1/10,000 |
Resultado
La evidencia es elocuente, con RDS Proxy no solo mantuvimos un excelente tiempo para obtener una conexión y obtener datos, sino que virtualmente el fallo de la base de datos fue imperceptible, apenas una falla en 10,000 peticiones.
Por su parte, al conectarnos directamente a RDS, tuvimos un 61% de peticiones fallidas. Y esto tiene sentido, pues debemos esperar que la entrada de DNS interna se actualice para apuntar a la instancia de réplica que fue promocionada como instancia de escritura. En tanto que RDS Proxy pudo gestionar el fallo de una manera mucho más conveniente para nuestra aplicación, sin tener que escribir código elaborado de nuestra parte para manejar escenarios como ese.
Es claro que en este apartado RDS Proxy sobresale de manera notoria.
Prueba de Mala Práctica de Programación
En este ejercicio, pongo a prueba RDS Proxy para casos en donde tenemos una aplicación que tiene un error en su lógica y no libera conexiones a la base de datos.
Aunque no es un caso de uso normal, ya antes he tenido que recurrir a esto cuando un cliente tiene problemas de esa índole y le toma tiempo poder hacer las correcciones pertinentes.
Veamos como la cantidad de conexiones abiertas sube hasta 248, recordemos que con el código debidamente programado llegamos a unas 11 conexiones.
Cuando la aplicación se conecta a RDS Proxy tenemos un pico constante de 334 conexiones y al igual que antes, una mayor tasa de consultas por segundo.
Si analizamos las métricas de proxy, podemos ver ese pico de hasta 100 conexiones de clientes, cuando previamente eran 6 con la aplicación bien programada.
Conclusión
AWS RDS Proxy se presenta como una herramienta sumamente beneficiosa para optimizar el rendimiento y la disponibilidad de bases de datos en entornos de nube. Al simplificar la gestión de conexiones y perfeccionar el proceso de failover, esta solución posibilita que las aplicaciones mantengan su resiliencia incluso en circunstancias adversas.
La implementación de RDS Proxy garantiza a las organizaciones la capacidad de escalar sus aplicaciones de manera eficiente, satisfaciendo las crecientes demandas de los usuarios y proporcionando una experiencia óptima y sin interrupciones.
En las pruebas realizadas, se observó una notable equiparación en los tiempos de conexión entre RDS y Proxy. Sin embargo, se destacó de manera innegable el beneficio de RDS Proxy en situaciones de fallo en la base de datos. Este mismo beneficio se hace evidente al enfrentarse a aplicaciones con ‘leaks de conexiones’, donde se vuelve imperativo proporcionar una solución temporal mientras se trabaja en una solución definitiva.
Aunque la adopción de este servicio conlleva un costo adicional, considero que para muchas cargas de trabajo, dicho monto pasa fácilmente desapercibido al contrastarse con los innumerables beneficios que ofrece.
Confío en que este artículo haya resultado de utilidad para ustedes.
Comentarios