Header Ads Widget

Ticker

6/recent/ticker-posts

Creación de un backend para frontend (BFF) para sus microservicios


 Las API están, por diseño, muy interconectadas. Con el fin de funcionar de manera efectiva y llevar a cabo los propósitos para su creación, las API están diseñadas para conectarse fácilmente a otros servicios, tanto internos como externos. Si bien esto ciertamente es beneficioso desde la perspectiva del usuario, los desarrolladores a menudo encuentran que el resultado de este tipo de desarrollo tiene algunos elementos problemáticos.

El principal de estos elementos es que cuando los microservicios se vuelven más numerosos, se vuelven más dependientes entre sí . Cada nuevo microservicio introducido en el ecosistema tiene sus propios métodos de comunicación y trabajo, y debe diseñarse específicamente para interactuar con todos los demás servicios dependientes.

Se pueden adoptar algunas estrategias para negar muchos de los puntos negativos de este aspecto del diseño de la arquitectura de microservicios. Un método es crear un shim Backend for Frontend (BFF) para ayudar a organizar las arquitecturas de microservicios y coordinar la funcionalidad en un sistema amplio y diverso.

Hoy, vamos a definir exactamente qué es un backend para frontend shim y cómo hace lo que hace. Destacaremos algunas de las mejores prácticas para tener en cuenta durante el desarrollo y discutiremos algunos puntos potenciales de falla que deben evitarse cuidadosamente.

¿Qué es un backend para frontend?

Las API son esencialmente una gran cantidad de partes que funcionan en conjunto entre sí hacia un único objetivo. Pero el diseñador de API a menudo crea sistemas que, con el tiempo, revelan grietas o debilidades que necesitan tener un pequeño fragmento de código para alinear todo como debería ser. El patrón de diseño Backend for Frontend , como lo describe Phil Calçado , se refiere al concepto de desarrollar backends especializados para la experiencia de cada usuario.

Un backend para frontend es un tipo único de ajuste que llena un vacío de diseño que es inherente al proceso de API. Un BFF es, en términos simples, una capa entre la experiencia del usuario y los recursos a los que recurre. Cuando un usuario móvil solicita datos, en una situación de BFF, su solicitud se traduce a través del BFF y en una capa general debajo de él. Lo que esto significa funcionalmente se puede demostrar en el siguiente ejemplo.

Impresión 3D: enfoque clásico

Supongamos que tiene un negocio de impresión 3D que acepta pedidos e imprime material a pedido. En el diseño tradicional, estaría viendo el siguiente flujo de API:

Este tipo de arquitectura tiene varios tipos de usuarios, cada uno con diferentes experiencias de usuario y necesidades de API. El usuario móvil utiliza una aplicación, el usuario de escritorio utiliza un cliente web y los pedidos internos los realizan los clientes que llaman al servicio de soporte, quienes manualmente agregan los pedidos a la cola mediante un programa interno.

Funcionalmente, esto se hace separando cada una de las funcionalidades en una aplicación o servicio web, cada una de las cuales llama a una API general. La API general tiene instancias de cada objeto y llamada según sea necesario para cada servicio, y responde al tipo de llamada específico (que se indica mediante una entrada de origen) con los datos requeridos.

Si bien esto es ciertamente útil, tiene algunos problemas graves. Lo primero, por supuesto, es el tamaño masivo de la API de pedidos a la que se llama. La API de pedidos no solo tiene que contener todos los procesos para el escritorio y las soluciones internas, sino que debe manejar cada llamada desde la aplicación móvil con sus propias funciones de llamada, sistemas de seguridad y funcionalidades de medios específicos.

Eso no quiere decir que la combinación de llamadas sea necesariamente el problema; el problema es específicamente la naturaleza de cómo se manejan estas llamadas. Una única API grande que navega por cada llamada y llama a la misma API monolítica es problemática y lenta. Los datos deben presentarse en un formato y un idioma específicos para la solución móvil, que está completamente separada de la solución de escritorio, lo que da como resultado múltiples funciones duplicadas con "ajustes" ligeramente modificados.

Otro gran problema es el hecho de que un solo equipo monolítico será responsable de la experiencia de usuario de tres usuarios diversos, cada uno con sus propias necesidades y experiencias específicas. Agrupar todo de esta manera es complicado y tiene el efecto de un equipo interno hinchado .

Relacionado: API asincrónicas en microservicios coreografiados

Impresión 3D: Diseño de microservicios

Podemos resolver muchos de estos problemas mediante el siguiente cambio de flujo:

En este diseño, cada tipo de cliente de aplicación tiene su propia API dedicada , lo que hace que una serie de microservicios se adapte específicamente a la experiencia de cada usuario, a diferencia del primer ejemplo, que se basó en una API general. En este caso, cada llamada se envía a través de una API específica y aislada y, luego, aprovecha los recursos del backend. Hasta aquí todo bien, ¿no? No tan rapido. Si bien muchos de los problemas se han resuelto, ha surgido un sistema de problemas completamente nuevo.

El gran problema aquí es la continuidad del microservicio . Si bien hemos separado muchas funciones de manera significativa de acuerdo con la experiencia del usuario que las utilizará, tenemos tres API distintas que llaman a las mismas funciones de backend, lo que significa mucha duplicación de código y funcionalidad. Lo más importante es que, a medida que la API se actualice y evolucione, esto significará una mayor sobrecarga tanto en términos de costos económicos y de tiempo del equipo como en el tamaño y la velocidad de la API.

Hemos cambiado un mundo de extremos por otro. Este es, en muchos sentidos, el panorama actual de API para la mayoría de los proveedores. Debido a esto, se han utilizado una amplia variedad de estrategias. Uno de ellos, y el que estamos discutiendo hoy, es la idea de un backend para frontend shim.

Lea también: 4 ajustes de diseño para mejorar las operaciones de la API

Impresión 3D: backend para frontend

De lo que estamos hablando conceptualmente es de una capa de "traductor", un calce que recibe llamadas dispares y permite que se convierta en una forma común. Si bien estamos agregando muchas capas conceptuales en este ejemplo, tenga en cuenta que los "shims" son fragmentos de código bastante pequeños, mucho más pequeños que la API en su conjunto.

Si bien este tipo de diseño puede parecer un cambio de marca de la arquitectura de microservicios, lo que en realidad está viendo aquí es una capa de servicios de traducción . Cada ajuste se mantiene en concierto con otro por un "equipo de ajuste", con la API de pedidos gestionada por un solo equipo de API. ¿No debería esto causar los mismos problemas que vimos antes?

La diferencia clave aquí está en el manejo de llamadas. En el diseño de "API general" anterior, teníamos una única API que contenía variaciones en el conjunto de datos inicial desencadenadas por identificaciones de fuente. El problema era que cada fuente tenía que tener su propia llamada de especialidad y la API tenía que manipular los datos antes de pasarlos.

En la solución de microservicios, solucionamos esto al tener API individuales para cada servicio, pero los problemas persistieron en forma de falta de continuidad y el alcance del equipo resultante y el aumento de tamaño que siguió.

En el enfoque de compensación, lo que tenemos es un grupo de llamadas dispares que se traducen en una sola llamada. Las diferentes traducciones y sistemas de tipos de datos se realizan durante el manejo de datos desde la API hasta el shim, esencialmente traduciendo la llamada específica del servicio en una llamada general *.

Esto no solo alivia el tamaño de la base del código y los problemas de alcance tanto de la API general como de los equipos que la desarrollan, sino que también cambia el poder de procesamiento y la responsabilidad a múltiples servicios que pueden ser diseñados y mantenidos por un solo equipo de compensación.

Básicamente, estamos creando una autopista y evitando todas las carreteras de superficie y de peaje, lo que significa un rendimiento mejor y más eficiente .

Mejores prácticas

Con todo esto en mente, analicemos algunas de las mejores prácticas y los errores generales que se deben evitar al desarrollar este tipo de sistema.

Evite la conversión de Shim a API

Uno de los mayores escollos en los que puede caer un desarrollador es pensar en un shim de la misma manera que uno pensaría en un microservicio. Estas dos cosas son muy diferentes y deben codificarse como tales.

Cuando hablamos de una corrección de traducción, lo que realmente estamos hablando es algo que simplemente dice "cuando se devuelvan estos datos, transfórmalos de este tipo de datos al tipo de datos especificado por la aplicación". No estamos hablando de una API autónoma y con todo incluido, estamos hablando de una capa de traducción.

Duplicación de cuñas

El objetivo de crear una corrección es aumentar la eficiencia en la base del código y eliminar la duplicación, por lo que puede parecer extraño que esto sea un error a tener en cuenta. Sin embargo, la realidad es que los nuevos en el desarrollo de calzas podrían considerar una calza necesaria para cada experiencia de usuario única. Pero, ¿cuán granular debería ser?

La pieza que falta aquí es que cada experiencia de usuario debe agruparse por tipo de experiencia , no por la fuente de la experiencia. Por ejemplo, un desarrollador puede querer desarrollar calzas separadas para los sistemas operativos iOS, Android, Windows Mobile y de terceros móviles, pensando que esto daría como resultado un mejor rendimiento.

La verdad es que la mayoría de estas experiencias móviles pueden aceptar ciertos tipos de datos comunes, ya que la experiencia del usuario es muy similar. La experiencia de la aplicación entre sistemas operativos es lo suficientemente similar como para no justificar sus propias correcciones individuales.

Si le gusta esto, consulte también: Cómo manejar la entrega continua de microservicios

Dependencia excesiva de cuñas

En relación con la idea de conversión de Shim a API, existe una clara amenaza de que un shim se convierta en una muleta. Si bien es muy tentador utilizar el concepto de calce como primera línea de seguridad, para una funcionalidad extendida y más, un calce solo está destinado a ser un calce, no está destinado a servir como nada más que una capa de traducción.

Como tal, trate de evitar depender demasiado de la cuña. La base de código de la API principal aún debe manejar todas las funciones y aún debe hacer todas las cosas que una API adecuada debe hacer: se supone que la corrección debe llenar un vacío, no agregar funcionalidad y servicios.

Proporcionar lo que se solicita

Como parte del concepto de desarrollo de BFF / shim, cada experiencia solo requerirá ciertos elementos de datos. Los desarrolladores pueden considerar que la corrección es un filtro además de un traductor , pero eso no es lo que queremos: la API solo debe proporcionar los datos solicitados por la corrección.

Imagine un frente de compras que cataloga los artículos y los coteja con datos que incluyen la fecha de fabricación, el tipo, la frecuencia de compra, etc. La aplicación móvil puede que solo necesite 10 de los 50 objetos de datos que se incluyen en cada entrada, mientras que la aplicación de escritorio necesitará 40 de ellos, y la aplicación interna necesitará los 50.

Es tentador que el shim elimine los datos innecesarios en tránsito, pero esto comienza a empujarlo a convertirse en una API funcional en lugar de un shim. Este tipo de manejo de datos debe realizarse en el nivel de API en sí , utilizando activadores de origen. Cada corrección debe notificar a la API el tipo de cliente, y la API debe responder solo a solicitudes de conjuntos de datos específicos, en lugar de proporcionar un objeto de datos completo.

Esto se hace específicamente como un enfoque a la base del código inicial: los objetos deben separarse teniendo en cuenta el concepto de calces y experiencias de usuario dispares. Hacerlo aumentará la velocidad general, reducirá el ancho de banda y aumentará la satisfacción de la experiencia.

Conclusión

Lo que es importante tener en cuenta a lo largo de todo esto es que una cuña es simplemente una solución a un problema arquitectónico casi universal. Si bien existen otras estrategias, una corrección es muy eficaz cuando se enfrenta a un backend complejo y una amplia variedad de experiencias de usuario. Para resumir los tipos de arquitecturas que hemos cubierto:

  • En el diseño clásico , tenemos una llamada móvil , una llamada de escritorio y una llamada interna . Las tres llamadas requieren sus propias entradas o al menos un conjunto de códigos para manejar la conversión dentro de la API general.
  • En el diseño de microservicios , tenemos una llamada móvil , una llamada de escritorio y una llamada interna . Estas llamadas interactúan individualmente con sus propias API, la API móvil , la API de escritorio y la API interna .
  • En el diseño de calce BFF . Tenemos una llamada móvil , una llamada de escritorio y una llamada interna . Cada una de estas llamadas son interceptadas por la calza móvil , la calza de escritorio y la calza interna . El ajuste convierte las llamadas individuales en una llamada general , que luego es devuelta y traducida por el ajuste de llamada , que es el ajuste que realizó la solicitud.

Si se puede implementar correctamente o no, es una respuesta sujeta al caso de uso específico, la arquitectura de backend y el enfoque comercial de cada servicio individual. Dicho esto, un BFF puede ser increíblemente poderoso cuando se usa como debe usarse: una capa de traducción entre servicios y experiencias API dispares.

Publicar un comentario

0 Comentarios