En el artículo anterior, presentábamos el problema de la configuración del siguiente modo:
Necesitamos un almacenamiento del tipo (llave, valor) de modo que guardemos en este configuraciones que usaremos en nuestro programa.
Las configuraciones en este contexto pueden ser de varios tipos:
Secretos: corresponden a valores críticos que no deben ser divulgados, por contener información crítica, como las credenciales de conexión a la base de datos, API keys, llaves de cifrado, etc.
Parámetros no funcionales, pero que son usados internamente por el programa, por ejemplo, la URL de un servicio, o la ruta de cierto directorio donde se almacenan ciertos archivos.
Parámetros funcionales o de negocio, por ejemplo ciertos valores que pueden alterar algunos cálculos, o restricciones legales como impuestos, tasas, aranceles, etc. Acá también se incluyen los “feature flags”, que definen si cierta funcionalidad va a activarse y cuáles serán sus parámetros de operación.
Por ejemplo, hace unos meses tuve que implementar cierta funcionalidad, pero el “rollout” de la funcionalidad se realizaría por regiones, y además cada región tenía ciertos parámetros específicos.
Entonces mi parametrización era de este estilo:
“region”: {“param1”: “valor1”, “param2”: “valor”}
En Uber tenemos una solución propia para resolver este problema llamada “Flipr” (se pronuncia “fliper”). Que nos permite describir nuestras configuraciones en “JSON” y cuya estructura está descrita en el blog de ingeniería de Uber.
En este sistema se pueden implementar cosas como:
“La característica #456 está implementada”
“El límite en tamaño para la entrada de texto ‘name’ es de 256 caracteres”
“La URL de la API del servicio de mapas es http://mapservice/v2”
Pero también podemos aplicar ciertas reglas o filtros en nuestras configuraciones, por ejemplo:
“Habilita la característica #456 para todos los miembros del grupo ‘admin’ que actualmente estén realizando una petición desde Nueva York”
“Restrinja las consultas a la API con un mensaje de error ‘temporalmente no disponible’ entre las 4 pm y las 5 pm del miércoles”
Esto por supuesto se codifica en un lenguaje de dominio específico que se plasma en esta configuración JSON.
La API para acceder a Flipr es del siguiente tipo:
client.get(property_key, context)
Entonces esto permite hacer cosas como esta:
enable := client.get(“enable_feature_456”, {cityId: 1, userId: 123})
if enable { /* implements feature 456 */ }
Acá el contexto está en “duro”, pero es fácil ver que este puede obtenerse dinámicamente del entorno de ejecución, de modo que podemos pasar ese contexto a flipr que resolverá adecuadamente la consulta.
Lo interesante es la arquitectura de Flipr:
La gestión es centralizada, pero se distribuye a cada host que contiene los contenedores con los servicios que usan flipr, en cada uno se guarda una copia en disco de las configuraciones requeridas por los contenedores en esos hosts. Esto es un medio de respaldo ante la pérdida de comunicación con la base de datos central.
El cliente que está enlazado al servicio que lo consume, recibe la respuesta de un agente local que retorna el valor en memoria o lo lee del disco local. Cuando se actualiza una configuración, esta se refresca hacia cada agente a través de los gateways localizados por zonas (datacenters).
El desempeño de esto es altísimo, alcanzando miles de cambios diarios, distribuidos en cientos de servicios, con millones de requests por segundo, con tiempos de respuestas medibles en nanosegundos.
Esta es una solución sofisticada para una realidad altamente distribuida como la de Uber, pero probablemente tú no necesitas algo así, aunque algunos principios de arquitectura usados en esta solución sí pueden ser aplicados en tu problema específico.
Vamos a ver en un próximo artículo cómo resolver esto de distintas formas y veremos que mucho de lo que hemos visto en la solución de Flipr lo podemos aplicar también en muchos casos distintos, con tecnologías bastante sencillas.
Gracias por los likes que recibí en el artículo previo que me animaron a continuar, si les gustó esta entrada, los invito a compartir este contenido con sus colegas o amigos interesados en este tipo de soluciones tecnológicas.
Y como siempre, sus likes y comentarios me animan a seguir adelante.