¿Por qué es tan malo leer datos de una base de datos "propiedad" de un microservicio diferente?

64

Recientemente leí este excelente artículo sobre la arquitectura de microservicios: http://www.infoq.com/articles/microservices-intro

Establece que cuando carga una página web en Amazon, más de 100 microservicios cooperan para servir esa página.

Ese artículo describe que toda la comunicación entre microservicios solo puede pasar por una API. Mi pregunta es por qué es tan malo decir que todas las escrituras de la base de datos solo pueden pasar por una API, pero usted es libre de leer directamente desde las bases de datos de los diversos micro servicios. Se podría decir, por ejemplo, que solo se puede acceder a unas pocas vistas de la base de datos fuera del micro servicio, de modo que el equipo que mantiene el micro servicio sepa que, siempre que mantengan estas vistas intactas, pueden cambiar la estructura de la base de datos de su micro servicio tanto como sea posible. querer.

¿Me estoy perdiendo de algo? ¿Hay alguna otra razón por la cual los datos solo deberían leerse a través de una API?

No hace falta decir que mi empresa es significativamente más pequeña que Amazon (y siempre lo será) y el número máximo de usuarios que podemos tener es de unos 5 millones.

David
fuente
Un factor más general que no se menciona en las respuestas es que cuando se escribe en la base de datos, el almacenamiento en caché local, incluso el mapeo simple de O / R, puede generar datos obsoletos al acceder de inmediato a la base de datos. Si considera omitir la API de µservice por razones de velocidad, es muy posible que haya llevado la arquitectura de µservice demasiado lejos.
Joop Eggen
Al permitir lecturas de bases de datos, cada detalle de la base de datos se convierte en parte de la API pública. No me gustaría mantener la compatibilidad en una API tan compleja.
Patrick
Pero en ese caso, ¿la vista simplemente no se convierte en parte de la API, al menos para fines semánticos? Es solo una cuestión de lo que está llamando API y lo que lo obliga a mantener. (Por lo general, una capa sobre la base de datos es más fácil de mantener consistente.)
lc.
Estoy de acuerdo en que la vista sería simplemente una forma de API. Creo que la mayoría de las personas que responden a esta pregunta no leen mi idea sobre el uso de las vistas como un nivel de abstracción. Sin embargo, entiendo que mantener la vista intacta si uno cambia la tecnología de la base de datos sería un gran desafío, pero estoy dispuesto a apostar a que no necesitaremos cambiar la tecnología de nuestra base de datos durante los próximos 5 años. Además, el rendimiento no será un problema con solo 5 millones de usuarios. Entonces, dado nuestro tamaño, agradezco ir por esta solución, aunque las respuestas aquí parecen indicar que me dirijo directamente a un mundo de dolor.
David

Respuestas:

69

Las bases de datos no son muy buenas para ocultar información, lo cual es bastante plausible, porque su trabajo es realmente exponer información. Pero esto los convierte en una pésima herramienta cuando se trata de encapsulación. ¿Por qué quieres encapsulación?

Escenario: vincula un par de componentes a un RDBMS directamente, y ve que un componente en particular se convierte en un cuello de botella de rendimiento para el que es posible que desee desnormalizar la base de datos, pero no puede porque todos los demás componentes se verían afectados. Incluso puede darse cuenta de que sería mejor con un almacén de documentos o una base de datos gráfica que con un RDBMS. Si los datos están encapsulados por una pequeña API, tiene una oportunidad realista de reimplementar dicha API de la forma que necesite. Puede insertar capas de caché de forma transparente y lo que no.

Tocar con la capa de almacenamiento directamente desde la capa de aplicación es lo contrario diametral de lo que sugiere hacer el principio de inversión de dependencia .

back2dos
fuente
1
¡Es un excelente punto! Una cosa que me preocupa menos es que Postgres ahora tiene soporte para el almacén de documentos y RDBMS ( sin theloop.com/articles/2014-09-30-postgresql-nosql ). Sin embargo, su punto sigue siendo válido y lo consideraré con cuidado.
David
3
No debería preocuparte menos a @David solo porque una herramienta pueda hacer algo no significa que cambiarla no rompa muchas cosas. Ese es el punto de tener un grado de separación: puede cambiar completamente los datos detrás de una API sin cambiar lo que ve el usuario. Estoy hablando como un basador de datos aquí ... siempre que lo que el cliente vea sea lo mismo, puede cambiar el backend tanto como desee.
Ben
1
@David Si bien esta es una noticia interesante, es bastante irrelevante para el escenario que describí. Si cambia su esquema de base de datos de uno relacional a uno basado en documentos, tendrá el mismo impacto en todos los que dependen de él: deberá reescribir todas las consultas. También existe la pesadilla de tener que implementar todos estos cambios a la vez, para que la compatibilidad entre los componentes se mantenga en todo el sistema.
back2dos
1
@David: restringir el acceso a unas pocas vistas bien definidas podría significar construir otra API, con algunos de los beneficios que conlleva. Siempre que solo sean vistas, sin embargo, está restringido al acceso de solo lectura. Y tener un componente depende tanto de la API de servicio como de la API de vista, lo que lo hace muy frágil. Entonces, si está haciendo que un componente dependa de las vistas, lo ha predeterminado para que sea de solo lectura o de alto mantenimiento. Huelo deuda técnica aquí. También es posible que desee agregar particiones horizontales de una manera que su base de datos no le permita.
back2dos
2
@David: A la larga, es más importante lo fácil que es cambiar el código que lo fácil que es escribirlo. La arquitectura no dice "no deberías escribir código de tal o cual manera", dice "si lo haces, sufrirás terribles pesadillas al tratar de mantenerlo". Si habla de prototipos, entonces el mantenimiento no es un requisito. Adelante. Un prototipo debería demostrar un punto lo más fácilmente posible. Pero cuando intente integrar todos los puntos probados a un sistema sin que se convierta en tortura autoinducida por Sisyphean, es mejor que haga un esfuerzo adicional.
back2dos
55

¿Qué es más importante y significativo sobre un microservicio: su API o su esquema de base de datos? La API, porque ese es su contrato con el resto del mundo. El esquema de la base de datos es simplemente una forma conveniente de almacenar los datos administrados por el servicio, con suerte organizados de una manera que optimice el rendimiento del microservicio. El equipo de desarrollo debería ser libre de reorganizar ese esquema, o cambiar a una solución de almacén de datos completamente diferente, en cualquier momento. Al resto del mundo no debería importarle. El resto del mundo se preocupa cuando la API cambia, porque la API es el contrato.

Ahora, si echas un vistazo a su base de datos

  • Agrega una dependencia no deseada en su esquema. No pueden cambiarlo sin tener un impacto en su servicio.
  • Agrega carga no deseada e impredecible a sus componentes internos.
  • El rendimiento de su propio servicio se verá afectado por el rendimiento de su base de datos (intentarán optimizar su servicio para que funcione bien para los clientes y que su base de datos funcione bien solo para su servicio)
  • Está vinculando su implementación a un esquema que bien puede no representar de manera precisa y distintiva los recursos en su almacén de datos; puede tener detalles adicionales que solo son necesarios para rastrear el estado interno o satisfacer su implementación particular (que no debería importarle).
  • Sin darse cuenta, puede destruir o corromper el estado de su servicio (y no sabrán que está haciendo esto)
  • Puede actualizar / eliminar / eliminar recursos de su base de datos sin que ellos sepan que esto ha sucedido.

Es posible que los dos últimos puntos no sucedan si solo se le otorga acceso de lectura, pero los otros puntos son más que una razón suficiente. Las bases de datos compartidas son algo malo.

Es común que los desarrolladores menos experimentados (o aquellos que no aprenden) vean la base de datos como más importante que el servicio, que vean la base de datos como algo real y el servicio solo como una forma de llegar a ella. Ese es el camino equivocado.

itsbruce
fuente
44
Tenga en cuenta que todos los puntos anteriores son válidos incluso si usted es el único desarrollador que trabaja en todo el proyecto. Gestionar un proyecto complejo, incluso por su cuenta, invoca todas estas preocupaciones.
itsbruce
15

La arquitectura de microservicios es difícil de describir, pero la mejor manera de pensar es unir la arquitectura orientada a componentes y la arquitectura orientada a servicios. El software como conjunto está compuesto por muchos componentes de pequeñas empresas con una responsabilidad de dominio comercial muy específica. Su interfaz con el mundo exterior, ya sea en servicios prestados o servicios requeridos, es a través de una API de servicios claramente definidos.

Escribir e incluso leer desde una base de datos que está fuera del dominio comercial de sus componentes va en contra de este estilo de arquitectura.

La razón principal de esto es que una API proporcionada a través de un servicio por otro componente de software tiene la expectativa razonable de que la API probablemente sea compatible con versiones anteriores a medida que estén disponibles nuevas versiones del componente que proporciona el servicio. Si soy el desarrollador de un componente "proveedor", entonces solo tengo que preocuparme por la compatibilidad con mi API. Si sé que hay otros tres equipos de desarrollo que escribieron consultas personalizadas directamente en mi base de datos, entonces mi trabajo se ha vuelto mucho más complicado.

Peor aún, tal vez ese otro equipo que escribió esto está a mitad de carrera en un proyecto crítico y no puede aceptar este cambio ahora desde su componente. Ahora, el desarrollo de software para su componente en un dominio comercial de su propiedad está siendo impulsado por el desarrollo en otro dominio comercial.

La interacción completa a través de los servicios reduce el acoplamiento entre varios componentes de software, por lo que situaciones como esta no ocurren con tanta frecuencia. Cuando se trata de otros componentes que usan una Vista en la base de datos, entonces tiene más capacidad para hacer que la Vista sea compatible con versiones anteriores si alguien más escribió consultas en su contra. Sin embargo, sigo sintiendo que este debería ser el caso de excepción y solo debería hacerse para tal vez la presentación de informes o el procesamiento por lotes donde una aplicación necesitará leer enormes cantidades de datos.

Claramente, esto funciona bien en grandes equipos distribuidos donde los equipos de desarrollo están separados por dominio comercial como Amazon. Si usted es un pequeño taller de desarrollo, aún puede beneficiarse de este modelo, especialmente si necesita acelerar un gran proyecto rápidamente, pero también si tiene que lidiar con el software del proveedor.

árbol de arce
fuente
4

En los últimos 20 años, he visto algunos diseños de bases de datos modulares grandes y he visto el escenario sugerido por David varias veces donde las aplicaciones tienen acceso de escritura a su propio esquema / conjunto de tablas y acceso de lectura a otro esquema / Conjunto de mesas. Muy a menudo, estos datos a los que una aplicación / módulo obtiene acceso de solo lectura podrían describirse como "datos maestros" .

En ese momento no he visto los problemas que las respuestas anteriores sugieren que debería haber visto, así que creo que vale la pena echar un vistazo más de cerca a los puntos planteados en las respuestas anteriores con más detalle.

Escenario: vincula un par de componentes a un RDBMS directamente y ve que un componente en particular se convierte en un cuello de botella de rendimiento

Estoy de acuerdo con este comentario, excepto que también es un argumento para tener una copia de los datos localmente para que los lea el microservicio. Es decir, la mayoría de las bases de datos maduras admiten la replicación y, por lo tanto, sin ningún esfuerzo del desarrollador, los "datos maestros" pueden replicarse físicamente en la base de datos de microservicios si eso se desea o se necesita.

Algunos podrían reconocer esto en apariencia antigua como una "base de datos empresarial" que replica las tablas principales en una "base de datos departamental". Un punto aquí es que, en general, es bueno si una base de datos hace esto por nosotros con la replicación integrada de datos modificados (solo deltas, en forma binaria y con un costo mínimo para la base de datos de origen).

Por el contrario, cuando nuestras opciones de base de datos no permiten este soporte de replicación 'listo para usar', entonces podemos entrar en una situación en la que queremos enviar "datos maestros" a las bases de datos de microservicios y esto puede resultar en una cantidad significativa de esfuerzo del desarrollador y También será un mecanismo sustancialmente menos eficiente.

puede querer desnormalizar la base de datos, pero no puede porque todos los demás componentes se verían afectados

Para mí, esta afirmación simplemente no es correcta. La desnormalización es un cambio "aditivo" y no un "cambio de ruptura" y ninguna aplicación debería romperse debido a la desnormalización.

La única forma en que esto rompe una aplicación es cuando el código de la aplicación usa algo como "select * ..." y no maneja una columna adicional. Para mí eso sería un error en la aplicación?

¿Cómo puede la desnormalización romper una aplicación? Suena como FUD para mí.

Dependencia del esquema:

Sí, la aplicación ahora depende del esquema de la base de datos y la implicación es que esto debería ser un problema importante. Si bien agregar cualquier dependencia adicional obviamente no es ideal, mi experiencia es que una dependencia en el esquema de la base de datos no ha sido un problema, entonces, ¿por qué podría ser ese el caso? ¿Acabo de tener suerte?

Datos maestros

El esquema al que normalmente queremos que un microservicio tenga acceso de solo lectura es lo que comúnmente describiría como " datos maestros " para la empresa. Tiene los datos básicos que son esenciales para la empresa.

Históricamente, esto significa que el esquema en el que agregamos la dependencia es maduro y estable (algo fundamental para la empresa e inmutable).

Normalización

Si 3 diseñadores de bases de datos van y diseñan un esquema db normalizado, terminarán con el mismo diseño. Ok, puede haber alguna variación de 4NF / 5NF pero no mucha. Además, hay una serie de preguntas que el diseñador puede hacer para validar el modelo para que pueda estar seguro de que llegaron a 4NF (¿Soy demasiado optimista? ¿La gente está luchando para llegar a 4NF?).

actualización: por 4NF aquí quiero decir que todas las tablas en el esquema llegaron a su forma normal más alta hasta 4NF (todas las tablas se normalizaron adecuadamente hasta 4NF).

Creo que el proceso de diseño de normalización es la razón por la cual los diseñadores de bases de datos generalmente se sienten cómodos con la idea de depender de un esquema de base de datos normalizado.

El proceso de normalización lleva el diseño de la base de datos a un diseño "correcto" conocido y las variaciones a partir de ahí deberían ser la desnormalización para el rendimiento.

  1. Puede haber variaciones basadas en los tipos de base de datos compatibles (JSON, ARRAY, soporte de tipo Geo, etc.)
  2. Algunos podrían argumentar a favor de una variación basada en 4NF / 5NF
  3. Excluimos la variación física (porque eso no importa)
  4. Restringimos esto al diseño OLTP y no al diseño DW porque esos son los esquemas a los que queremos otorgar acceso de solo lectura

Si 3 programadores recibieran un diseño para implementar (como código) la expectativa sería de 3 implementaciones diferentes (potencialmente muy diferentes).

Para mí, potencialmente hay una cuestión de "fe en la normalización".

Rompiendo los cambios de esquema?

La desnormalización, la adición de columnas, la modificación de columnas para un mayor almacenamiento, la ampliación del diseño con nuevas tablas, etc., son cambios constantes y los diseñadores de bases de datos que obtuvieron la cuarta forma normal estarán seguros de ello.

Obviamente, es posible realizar cambios de ruptura colocando columnas / tablas o haciendo un cambio de tipo de ruptura. Posible sí, pero en términos prácticos no he tenido ningún problema aquí. ¿Quizás porque se entiende qué son los cambios de última hora y se han gestionado bien?

Me interesaría escuchar casos de cambios de esquema en el contexto de esquemas de solo lectura compartidos.

¿Qué es más importante y significativo sobre un microservicio: su API o su esquema de base de datos? La API, porque ese es su contrato con el resto del mundo.

Si bien estoy de acuerdo con esta afirmación, creo que hay una advertencia importante que podríamos escuchar de un arquitecto de empresa que es "Los datos viven para siempre" . Es decir, si bien la API podría ser lo más importante, los datos también son bastante importantes para la empresa en su conjunto y serán importantes durante mucho tiempo.

Por ejemplo, una vez que existe un requisito para llenar la inteligencia de Data Warehouse for Business , el esquema y el soporte de CDC se vuelven importantes desde la perspectiva de los informes comerciales, independientemente de la API.

Problemas con las API?

Ahora, si las API fueran perfectas y fáciles, todos los puntos son discutibles, ya que siempre elegiríamos una API en lugar de tener acceso local de solo lectura. Entonces, la motivación para incluso considerar el acceso local de solo lectura es que puede haber algunos problemas al usar las API que evita el acceso local.

What motivates people to desire local read-only access?

Optimización de API:

LinkedIn tiene una presentación interesante (de 2009) sobre el tema de la optimización de su API y por qué es importante para ellos a su escala. http://www.slideshare.net/linkedin/building-consistent-restful-apis-in-a-highperformance-environment

En resumen, una vez que una API tiene que soportar muchos casos de uso diferentes, puede entrar fácilmente en la situación en la que admite un caso de uso de manera óptima y el resto de manera bastante pobre desde una perspectiva de red y perspectiva de base de datos.

Si la API no tiene la misma sofisticación que LinkedIn, puede obtener fácilmente los escenarios donde:

  • La API obtiene muchos más datos de los que necesita (desperdicio)
  • Chatty API's donde tienes que llamar a la API muchas veces

Sí, podemos agregar el almacenamiento en caché a las API, por supuesto, pero en última instancia, la llamada a la API es una llamada remota y hay una serie de optimizaciones disponibles para los desarrolladores cuando los datos son locales.

Sospecho que hay un grupo de personas por ahí que podrían agregarlo como:

  • Replicación de bajo costo de datos maestros a la base de datos de microservicios (sin costo de desarrollo y técnicamente eficiente)
  • Fe en la normalización y la resistencia de las aplicaciones a los cambios de esquema
  • Capacidad para optimizar fácilmente todos los casos de uso y potencialmente evitar llamadas remotas de API remotas / derrochadoras / ineficientes
  • Además de algunos otros beneficios en términos de restricciones y diseño coherente

Esta respuesta tiene demasiado tiempo. Disculpas !!

Rob Bygrave
fuente
Agregar una columna generalmente rompe las aplicaciones. Si tiene "salario", la aplicación que suma todos los salarios se rompe cuando se introduce una nueva columna "salario_currencia".
kubanczyk
De Verdad? Depende de su definición de "descansos", supongo. Si la aplicación estuviera en producción y operando como se esperaba sin una "moneda_salarial", ¿por qué consideraría que esa aplicación ahora está rota?
Rob Bygrave el
La aplicación se ejecuta sin error y muestra algún número. Pero es inútil. Cuando el CEO vea que la suma de los salarios del mes pasado es de 6 millones en lugar de 50 mil (debido a un nuevo empleado al que se le paga en Corea del Sur), la definición de una producción útil / inútil no se discutirá mucho.
kubanczyk
0

La gestión de estado (potencialmente una base de datos) puede implementarse en el contenedor del microservicio y exponerse a través de una API. La base de datos de un microservicio no es visible para otros sistemas fuera del contenedor, solo la API. Alternativamente, podría tener otro servicio (por ejemplo, un caché) para administrar el estado a través de una API. Tener todas las dependencias de Microservice (que no sean llamadas API a otros servicios) dentro de un único contenedor desplegable es una distinción clave en la arquitectura. Si uno no lo consigue, regrese y estudie la arquitectura.

Eric Roch
fuente