Tenemos muchas aplicaciones y servicios web (algunos productos públicos, algunos internos y parte de un "backend" privado) que son interdependientes entre sí. Cada uno de estos componentes tiene 4 entornos (grupos de servidores / nodos que sirven para propósitos específicos):
- No producción
DEV
- Entorno de desarrollo integrado donde CI crea cambios de empuje; útil para que los ingenieros resuelvan errores difíciles de encontrar que no son reproducibles localmenteQA
- QA aislado / entorno de pruebaDEMO
- Entorno UAT estable para las partes interesadas del negocio.
- Producción
LIVE
- Nuestro entorno de producción / vida
La promoción del código va: LOCAL
(máquina del desarrollador) => DEV
=> QA
=> DEMO
=> LIVE
.
Digamos que tenemos una aplicación llamada myapp
que está respaldada por un servicio web RESTful llamado myws
, que a su vez está respaldado por un DB llamado mydb
.
Actualmente, tenemos lo que yo llamaría promoción " orquestada " entre estas dependencias: los myapp-dev
puntos a los myws-dev
que se usa mydb-dev
. Del mismo modo, myapp-qa
señala a myws-qa
qué usos mydb-qa
. Lo mismo para DEMO
y LIVE
.
El problema con esto es que cada vez que hago un cambio a, por ejemplo, myapp
esto me obliga a realizar cambios myws
y mydb
así. Pero debido a que cada DEV
entorno apunta a los entornos de sus dependencias DEV
, significa que tengo que programar y desplegar estos cambios al mismo tiempo. Además, si una compilación se vuelve inestable / rota, a menudo derriba otros componentes ascendentes; por ejemplo, si un desarrollador rompe algo al cambiar mydb-dev
, los clústeres myws-dev
y myapp-dev
generalmente también se vuelven inestables.
Para resolver esto, estoy elaborando una propuesta para lo que yo llamaría una estrategia de promoción " aislada ": todas las dependencias entre componentes siguen esta guía:
- Las dependencias ascendentes dependen del
DEMO
entorno para sus dependencias descendentes, para todos sus entornos no productivos (DEV
,QA
yDEMO
); y - Las dependencias ascendentes dependen del
LIVE
entorno para sus dependencias descendentes para su entorno de producción
Usando esta convención, myapp-dev
apuntaría a myws-demo
, cuál usaría mydb-demo
. Del mismo modo, myapp-qa
también apuntaría a myws-demo
y mydb-demo
.
La ventaja aquí que puedo encontrar es la estabilización de construcción : es mucho menos probable que el DEMO
ambiente para un componente en particular se volverá inestable, ya que el código no puede llegar a DEMO
sin pruebas rigurosas tanto en DEV
y QA
.
La única desventaja que puedo encontrar con este método es que, si DEMO
se rompe para un componente en particular, todos los entornos de no producción para todas las dependencias ascendentes se romperán repentinamente. Pero respondería que esto debería ocurrir extremadamente raramente debido a las pruebas realizadas en DEV
y QA
.
Esto ha llegado a ser un problema que muchos desarrolladores (mucho más inteligente y con experiencia que yo mismo) han resuelto, y no me sorprendería si este problema y sus soluciones ya tienen nombres a ellos (además de lo que denomino orquestada / silos). Entonces, pregunto: ¿los méritos de una estrategia de promoción aislada superan los inconvenientes, y cuáles son los inconvenientes que puedo estar pasando por alto aquí?
Respuestas:
Si estoy leyendo tu publicación correctamente, no parece que esta propuesta realmente resuelva ninguno de los supuestos problemas.
La "estrategia de promoción aislada" parece que solo empeoraría esto. Si myapp v2, myws v2 y mydb v2 solo están en DEV, y myapp v2 confía en mydb v2 para que no se bloquee, cuando intente ejecutar myapp v2 en DEV, presionaré mydb v1 DEMO y se bloqueará. Esencialmente, se vería obligado a anular constantemente los silos o implementar mydb v2 por completo antes de que incluso pueda comenzar a trabajar en myapp v2. Más importante aún, nunca estaría probando mydb v2 en DEV, por lo que si está roto, ni siquiera lo descubrirá hasta que se rompa en DEMO, y luego volverá al punto de partida.
Hasta cierto punto, el problema que describe es inevitable, sin importar cómo esté configurado su flujo de trabajo, pero puede minimizarse. El truco consiste en garantizar que la interfaz entre mydb y myws (y la interfaz entre myws y myapp) esté estrictamente definida y requiera que todas las actualizaciones de esa interfaz sean totalmente compatibles con versiones anteriores . En mi trabajo, tenemos un esquema XML que define la interfaz entre nuestras aplicaciones y servicios, y muchas de nuestras herramientas internas simplemente no nos permiten realizar actualizaciones incompatibles a esos esquemas.
Esto me parece un problema grave, pero no un problema de implementación. Una base de datos dañada evitará que el servicio y la aplicación funcionen correctamente, pero no deberían volverse "inestables". Deberían devolver mensajes de error de algún tipo, para que cualquier persona que ejecute myapp en dev vea "Lo sentimos, nuestra base de datos está teniendo problemas hoy" en lugar de simplemente fallar.
Si el problema es que una base de datos dañada causa estos problemas, entonces lo que puede hacer es configurar un sistema de "siloing temporal" que le permita decir "mydb DEV está roto ahora, enrute todas las consultas de myws DEV a mydb DEMO para de momento". Pero esto solo debería ser una forma de realizar arreglos temporales hasta que mydb DEV vuelva a funcionar normalmente. Si todo está "en silos" de esa manera por defecto, entonces estás de vuelta en los problemas que describí anteriormente porque nadie nunca se ejecuta contra mydb DEV.
Siento que probablemente estoy malinterpretando tu propuesta de alguna manera, pero espero que esta respuesta al menos haga obvio lo que se malinterpretó y la mejor forma de reformularlo.
fuente