Ésta puede ser una buena pregunta, ¿Cómo diseño una aplicación para que pueda aprovecharse de todas las ventajas de la nube? o dicho de otra manera ¿Cómo hacer una native cloud app?.

Y no me estoy refiriendo en esta ocasión a cómo utilizar un lenguaje o plataforma específicos, ni siquiera si usar una base de datos noSql orientada a documentos o a clave-valor. Estamos en una fase previa ¿qué principios tengo que tener en cuenta cuenta para diseñar la aplicación?

En el mundillo este es bastante conocido la lista de principios o factores a tener en mente cuando se diseña una aplicación de este tipo. Me refiero a 12factors.net que fue creada por varias personas que han trabajando en Heroku construyendo literalmente cientos de aplicaciones de este tipo.

A mí me gusta especialmente porque es una de esas listas de principios que cuando las lees, piensas que sólo dice algo obvio, algo de sentido común. Precisamente ese es su gran mérito, sintetizar en una lista de 12 puntos los aspectos que un a vez leídos pueden resultar obvios pero que seguramente no tendríamos en cuenta si nos ponemos a ello directamente.

Los 12 factores

  1. Base de código fuente
    Siempre debe haber una relación una a una entre el código fuente y la app. Es decir, en un repositorio de código sólo puede haber una aplicación o componente y no puede haber un repositorio con varias aplicaciones o componentes. Además, desde un repositorio se puede desplegar varias veces, en diferentes entornos, de tal manera que el mismo código correspondiente a una versión es desplegado en todos sitios
  2. Declarar y aislar explícitamente las dependencias
    La aplicación no puede depender de las librerías que haya instaladas en el sistema, debe declararlas absolutamente todas de manera explícita mediante un fichero de manifiesto. Además, el uso de estas dependencias, típicamente librerías de código no deben afectar al resto de aplicaciones.
  3. Guardar la configuración en el entorno
    Entendemos como configuración todo lo que puede variar entre despliegues (entre entornos), típicamente se refiere a direcciones o paths a recursos, contraseñas, etc.
    Esta configuración nunca se debe guardar en el propio código si no que hay que usar las variables de entorno
  4. Tratar los backend services como recursos conectables
    Se refiere como backend service a cualquier recurso que se pueda consumir a través de la red como una base de daos o un servidor SMTP de email. Para este tipo de servicios, no se hace distinción entre si son propios de la aplicación o son de terceros, se gestionan igual. De tal manera que se podría cambiar fácil una base de datos on-premise por otra en una nube pública, únicamente cambiando la configuración.
  5. Separar completamente la etapa de construcción de la etapa de ejecución
    Se establecen tres fases o etapas para poner un código en producción:
    La etapa de construcción que convierte el código fuente en un artefacto ejecutable
    En la fase de distribución se combina este artefacto con la configuración del despliegue
    En la fase de ejecución (runtime) ejecuta la aplicación en el entorno de ejecución
    Siempre tiene que haber una separación completa en estas tres fases. Por ejemplo, nunca se debe cambiar el código cuando está en ejecución, porque de esta manera no se reflejarían los cambios en la fase de construcción.
  6. Ejecutar la aplicación como uno o más procesos sin estado
    Los procesos no tienen estado y no comparten nada (ni memoria ni disco) con otros procesos. Esto se traduce en que un programa en ejecución se puede matar y levantar una nueva instancia sin tener que ocuparse de la sesión ni nada parecido.
    Los datos únicamente se persisten en los servicios “backing service” como una base de datos.
    Amigo, si todavía estás trabajando con la sesión web (HTTPSession), mejor que la vayas olvidando 😉
  7. Asignación de puertos
    Las aplicaciones son completamene auto-contenidas y no dependen de un servidor web o servidor de aplicaciones para su ejecución. Dicho de otro modo, se acabo aquello de tener un Tomcat o un Jboss e ir desplegando ahí las aplicaciones.
    Si la aplicación necesita un servidor, este tiene que ir embebido en la propia aplicación (como es el caso de Spring Boot).
    Lo único que se ve desde fuera de la aplicación, es el puerto por donde responde, por ejemplo el puerto 80 para HTTP.
  8. Concurrencia
    Cada servicio o componente se ejecuta en su propio proceso de manera independiente del resto de procesos. Esto encaja completamente en un modelo de contenedores como docker, donde cada instancia de contenedor es un proceso del sistema operativo tal que el contenedor cree que tiene todo el sistema operativo para él.
  9. Desechabilidad
    Los procesos de las aplicaciones son desechables, lo que significa que se pueden matar o levantar de nuevo cuando se considere necesario.
    Para esto es necesario minimizar el tiempo de arranque y también tienen que estar preparados para finalizaciones no esperadas.
  10. Mantener desarrollo, preproducción y producción tan parecidos como sea posible
    Históricamente el entorno de desarrollo y el de producción han sido muy diferentes convirtiendo en todo un clásico aquello de que en mi máquina funciona y luego en el entorno de producción no lo hace.
    Hay que lograr que no haya diferencias entre los diferentes entornos para lograr una ejecución más estable y sin fallos. Con esto se logra que los despliegues puedan ser más seguros y se puedan hacer más a menudo.
  11. Historiales o logs de eventos
    Mediante el historial es posible observar el comportamiento de una aplicación durante su ejecución. Los eventos relevantes de la ejecución de la aplicación son volcados a un fichero o una cola en modo streaming que pueden ser explotados por herramientas de dashboards, análisis de eventos, lanzamiento de alertas o lucha contra el fraude por poner algunos ejemplos.
  12. Administración de procesos
    Los procesos de administración o mantenimiento se pueden necesitar para todo tipo de tareas como migrar bases de datos ejecutar scripts en la consola, etc. Este tipo de procesos deben ejecutarse en un entorno idéntico al que usa la aplicación, con una distribución concreta y con el mismo código base.

 

Hasta aquí los 12 factores… para considerarlos una lista de características a tener en cuenta para el diseño de una aplicación, en mi opinión son de bastante bajo nivel ocupándose de lo que podríamos considerar como cuestiones internas de la infraestructura. Para que sea una lista completa, me faltaría añadir algunos patrones de diseño y otras características que considero básicas para una aplicación cloud nativa. Me refiero a Domain Design Drive, a la infraestructura como servicio, al API management, etc. etc… pero eso es harina de otro post 😉

Anuncios