lunes, 14 de mayo de 2018

Desarrollo por Microservicios


La Arquitectura de micro- servicios, conocido por las siglas MSA (del inglés Micro Services Architecture) es una aproximación para el desarrollo de software que consiste en construir una aplicación como un conjunto de pequeños servicios, los cuales se ejecutan en su propio proceso y se comunican con mecanismos ligeros (normalmente una API de recursos HTTP). Cada servicio se encarga de implementar una funcionalidad completa del negocio. Cada servicio es desplegado de forma independiente y puede estar programado en distintos lenguajes y usar diferentes tecnologías de almacenamiento de datos .

Se suele considerar la arquitectura de microservicios como una forma específica de realizar una arquitectura SOA.

Los microservicios son una arquitectura y un enfoque sobre la escritura de software en el que las aplicaciones se dividen en componentes más pequeños e independientes entre sí. A diferencia de un enfoque tradicional y monolítico sobre las aplicaciones, en el que todo se crea en una única pieza, los microservicios están separados y funcionan conjuntamente para llevar a cabo las mismas tareas. Cada uno de estos componentes, o procesos, son los microservicios. Este enfoque sobre el desarrollo de software valora la granularidad por ser liviana y la capacidad de compartir un proceso similar en varias aplicaciones.

No obstante, el mayor interrogante al respecto es por qué sería preferible utilizar una arquitectura basada en microservicios. En pocas palabras, el objetivo es entregar software de calidad más rápido. Aunque los microservicios son un medio para tal fin, se deben considerar otras cuestiones. Dividir las aplicaciones en microservicios no es suficiente; es necesario administrarlos, orquestarlos y gestionar los datos que crean y modifican.

¿Qué se puede hacer con los microservicios?

Los microservicios le permiten a su empresa reaccionar con mayor rapidez porque facilitan mucho el desarrollo y la adaptación más rápidos de las aplicaciones para satisfacer las demandas. Este enfoque sobre el diseño y la arquitectura de software le permite a su empresa huir de la "marcha de la muerte" de varios años que supone el desarrollo de software tradicional. En la actualidad, distintas partes del equipo de desarrollo pueden trabajar simultáneamente en los productos de un modo ágil, y entregar valor a los clientes de inmediato.

Comparando el enfoque “monolítico” con el de microservicios

Para comprender la arquitectura basada en microservicios, lo mejor es considerar su opuesto, su némesis, la arquitectura monolítica . En ésta, la aplicación se desarrolla como una única unidad que no necesitará de ningún componente externo para funcionar . Por ejemplo, en una aplicación que cuenta con un lado del cliente y un lado servidor, el “monolito” cliente se encargará de las peticiones HTTP, ejecutar la lógica y recibir/actualizar la información desde la base de datos.

El problema de las aplicaciones monolíticas es que todos los “ciclos de cambio” están vinculados unos a otros , por lo que la más mínima modificación en una remota sección de la app conllevaría a la creación y despliegue de una versión completamente nueva, con el gasto de recursos correspondiente. Por no hablar de si queremos escalar un apartado específico del proyecto o directamente la aplicación al completo; y aquí es donde los desarrolladores han visto el potencial de los microservicios.


Características

En el mundo real no todas las implementaciones de este estilo de arquitecturas siguen las mismas características pero la mayor parte de las arquitecturas de microservicios tienen la mayor parte de las siguientes características:

  • Los componentes son servicios. La principal manera de crear componentes (unidad de software independientemente reemplazable y actualizable) es mediante la decomposición en servicios en lugar de librerías. Los servicios son componentes separados que se comunican mediante mecanismos como los servicios web o los RPC en lugar de usar llamadas a funciones en memoria como hacen las librerías.
  • Organizada en torno a las funcionalidades del negocio. El sistema se divide en distintos servicios donde cada uno está organizado en torno a una capacidad del negocio. Es muy importante limitar la responsabilidad de cada servicio. Cada servicio implementa toda la funcionalidad del negocio que agrupa desde la interfaz de usuario, la persistencia en el almacenamiento y cualquiera de las colaboraciones externas.
  • Productos no proyectos. En esta arquitectura normalmente se sigue la idea de que un equipo debe estar a cargo de un componente (servicio) durante todo el ciclo de vida del mismo, desde la etapa de diseño y construcción, la fase de producción y hasta la de mantenimiento. Esta mentalidad se acopla bien a con la vinculación a una capacidad del negocio. En lugar de ver el software como un conjunto de funcionalidades terminadas se ve como una relación continua, donde la pregunta es cómo puede el software ayudar a sus usuarios a mejorar la funcionalidad del negocio que implementa. Esto es facilitado por el bajo nivel de granularidad que ofrecen los microservicios.
  • Extremos inteligentes tuberías bobas. Las aplicaciones creadas desde microservicios pretenden ser tan disociadas y cohesivas como sea posible, ellas poseen su propia lógica de dominio y actúan como filtros en el clásico sentido UNIX: recibe una solicitud, aplica la lógica apropiada y produce una respuesta. Estos pasos son coreografiados usando protocolos simples (típicamente HTTP con REST o mensajería liviana como RabbitMQ o ZeroMQ) en lugar de protocolos complejos como WS-BPEL.
  • Tener gobierno descentralizado permite usar tecnologías que se adapten mejor a cada funcionalidad. Con el sistema con múltiples servicios colaborativos, podemos decidir utilizar diferentes lenguajes de programación y tecnologías dentro de cada servicio. De esta forma podemos elegir la herramienta adecuada para cada tipo de trabajo en lugar de tener una estandarizada. Por ejemplo si una parte del sistema necesita mejorar su rendimiento es posible usar una tecnología, quizás más complicada, que permita alcanzar el nivel de rendimiento requerido. Otro ejemplo sería usar para ciertas cosas (reflejar interacciones entre usuarios) una base de datos orientada a grafos, y usar para otra bases de datos orientadas a documentos. la arquitectura de microservicios permite adoptar nuevas tecnologías más rápido y en aquello lugares donde se puede aprovechar su potencial ya que se acota el impacto.
  • Gestión de datos descentralizada. Los microservicios prefieren dejar a cada servicio que gestione su propia base de datos, sean estos diferentes instancias de la misma tecnología de base de datos o sistemas de base de datos completamente diferentes. Por ejemplo podríamos tener Redis para sesiones de usuarios (base de datos en memoria), MySQL (relacional) para los datos de pago, MongoDB (orientada a documentos) para el catálogo de productos, Neo4j (orientada a grafos) para las recomendaciones y Apache Cassandra (orientado a clave-valor) para el análisis de logs y analíticas. El estilo de microservicios tiene implicaciones en el manejo de las actualizaciones las cuales tradicionalmente han usado transacciones para garantizar la consistencia. las transacciones impone un acoplamiento temporal lo que se vuelve problemático cuando hay varios servicios. Como las transacciones distribuidas son mucho más difíciles de implementar, las arquitecturas de microservicios promueven la coordinación no transaccional entre servicios, con el reconocimiento explícito que la consistencia puede ser una consistencia eventual y los problemas son compensados operativamente. El sistema merece la pena siempre y cuando el costo de solucionar los errores sea menor que el costo de perder negocios por una mayor consistencia. Los microservicios no obligan a tener distintas tecnologías de almacenamiento, solo lo permiten.
  • Diseño tolerante a fallos. Las aplicaciones necesitan ser diseñadas de modo que puedan tolerar las fallas de los distintos servicios. Cualquier llamada de servicio puede fallar y el cliente tiene que ser capaz de responder a esto con la mayor facilidad y eficacia posible, evitando los muy habituales fallos en cascada de las arquitecturas distribuidas. Patrones más importantes para conseguir estabilidad que se usan en la arquitectura de microservicios:
    • Usar tiempos de espera máximos. Es un mecanismo simple que permite dejar de seguir esperando por una respuesta que consideramos que ya no vendrá. Asociado al vencimiento de un tiempo de espera es frecuente que aparezcan:
      • Reintento. Consiste en repetir una operación para el cual finalizó su tiempo de espera
      • Encolar para reintentar la operación para ser realizada más tarde
    • Disyuntores. Funcionan de forma similar a los interruptores automáticos accionados por sobrecargas que hay en las instalaciones eléctricas. En el software existen para permitir que un subsistema ante una falla no destruya el sistema entero por sobrecarga y una vez que el peligro ha pasado pueda reestablecerse. Este mecanismo se suele usar para envolver operaciones peligrosas con un componente y así poder esquivar las llamadas cuando el sistema no esté operativo. Si el disyuntor detecta que las fallas superan una frecuencia umbral el disyuntor salta abriéndose y las llamadas fallan sin realizan ningún intento de ejecutar una operación real. Después de esperar un tiempo adecuado se decide que la operación tiene una oportunidad y pasa a un estado de semiabierto en el que la próxima llamada es permitida, si tiene éxito entonces el disyuntor se vuelve a cerrar y todo vuelve a funcionar normalmente, si falla el disyuntor se vuelve a abrir y se vuelve a esperar el tiempo adecuado para intentar.
    • Compartimentos estancos para contención de daños manteniendolos aislados. La forma más común de tenerlos es usando redundancia física teniendo por ejemplo varios servidores y dentro de cada servidor varias instancias. A gran escala podríamos tener varias granjas de servidores.
  • Automatización de la infraestructura. La mayoría de los productos y sistemas desarrollados con el enfoque de microservicios han sido construidos por equipo que usan entrega continua y su precursor la integración continua. Para conseguir esto es necesario:
    • Automatizar todo el proceso, desde el chequeo del código, pruebas, despliegue,...
    • Control de versiones y gestión de configuración. Todo el software tiene que estar versionado y poder gestionar las distintas configuraciones para conseguir la entrega continua.
    • Arquitectura adecuada. La arquitectura tiene que permitir realizar cambios sin que afecten al resto del sistema. La arquitectura de microservicios lo hace posible.
  • Diseño evolutivo. Cuando se divide el sistema en servicios hay que tener en cuenta que cada uno tiene que poder ser reemplazado o actualizado de forma independiente. Es decir, tiene que permitir una fácil evolución. El diseño del servicio tiene que ser de tal forma que evite en lo posible que la evolución de los servicios afecte a sus consumidores.

Cuando utilizar una arquitectura de microservicios

Deberíamos utilizar una arquitectura de microservicios para cualquier producto o proyecto con estos dos enfoques:

Únicamente monolítico o con un primer enfoque monolítico. Normalmente, cuando una aplicación monolítica tiene éxito o necesita ayuda para escalar y mejorar el rendimiento, podemos optar por una arquitectura de microservicios de dos maneras:
  • Extender los componentes modulares bien diseñados de la aplicación monolítica.
  • Crear la aplicación de microservicios desde cero y volcar en ella la aplicación monolítica existente.
Un primer enfoque de microservicios. Debemos optar por la primera aproximación a los microservicios cuando:
  • La modularidad y la descentralización son un aspecto importante desde el inicio de cualquier proyecto.
  • Prevemos que la aplicación tendrá un alto volumen de transacciones o de tráfico.
  • Tenemos preferencia por beneficios a largo plazo en comparación con los de corto plazo.
  • Disponemos de un conjunto adecuado de personas para diseñar, desarrollar e implementar aplicaciones rápidamente, sobre todo durante la fase inicial.
  • Tenemos el compromiso de utilizar herramientas y tecnologías de vanguardia.

Cómo utilizar una arquitectura de microservicios

Desafortunadamente, la mayor parte de la información disponible sobre arquitectura de microservicios explica por qué deberían usarse, pero no cómo hacerlo. Es bueno saber que los microservicios podrían revolucionar el diseño, la implementación y la operación de las aplicaciones. ¿Pero exactamente cómo construyes un microservicio individual? Es necesario comprender los componentes fundamentales de un microservicio si deseas que el resultado funcione correctamente y no acabe pareciendo la misma aplicación monolítica antigua con una nueva capa de pintura.

Estos son los cinco elementos que un microservicio necesitará antes de que pueda utilizarse en una arquitectura de aplicación distribuida:

  1. Funcionalidad con un alcance adecuado. El primer elemento de un microservicio es definir lo que debe hacer. Una forma de definir el ámbito adecuado es particionar los servicios a lo largo de las líneas de funcionalidad lógica. Otro enfoque de alcance es reflejar la estructura de la organización de desarrollo. Un tercer enfoque es minimizar un servicio a la cantidad de código que podría ser reintroducido por el equipo en un período de dos semanas.
  2. Preparación de una API. Una vez que descomponemos una aplicación en múltiples servicios que cooperan, ¿cómo deben hablar esos servicios entre sí? Normalmente, esto se hace con llamadas a API de servicios web REST, aunque también pueden utilizar otros mecanismos de transporte. Una buena idea es evitar saltar a la codificación de la API de forma inmediata. En su lugar es mejor hacer algún trabajo en papel o pizarra para definir lo que un servicio específico debe exponer para funcionar correctamente.
  3. Gestión del tráfico. Desde la perspectiva del servicio de llamada, siempre debe realizar un seguimiento de sus llamadas y estar preparado para terminar si la respuesta toma demasiado tiempo. Desde la perspectiva del servicio llamado, el diseño de API debe incluir la posibilidad de enviar una respuesta que indique sobrecarga. Los servicios deben ser capaces también de generar y matar nuevas instancias de servicio según sea necesario para acomodar variaciones en la carga de tráfico.
  4. Descarga de datos. Tener necesidad de una operación continua es muy diferente de lo que necesitan las aplicaciones tradicionales, que a menudo dejan de funcionar si falla la infraestructura subyacente. Para asegurarse de que los usuarios pueden seguir trabajando cuando falla una instancia, se pueden migrar datos específicos del usuario fuera de las instancias de servicio a un sistema compartido de almacenamiento redundante accesible desde todas las instancias de servicio. Otro enfoque de descarga de almacenamiento es insertar un sistema compartido de caché basado en memoria entre un servicio dado y el almacenamiento asociado con ese servicio.
  5. Monitorización. El sistema de monitorización de una aplicación basada en una arquitectura de microservicios debe permitir el cambio continuo de recursos, ser capaz de capturar datos de monitorización en una ubicación central y mostrar información que refleje la naturaleza con frecuencia cambiante de las aplicaciones de microservicios.

Ventajas

  1. Eficiencia y simplicidad-> al ser servicios pequeños y especializados
  2. Heterogeneidad -> diferentes microservicios en diferentes tecnologías
  3. Escalabilidad -> eficiente, elástica y horizontal, bajo demanda, lo que permite ahorrar costes
  4. Independencia -> de funcionalidad, funcionalidades aisladas e independientes
  5. Time to market -> cada funcionalidad puede ser tratada y probada por separado y al ser corta puede entregarse en menos tiempo
  6. Alta disponibilidad -> al facilitar las posibilidades de escalado y replicación

Contras:

  1. Las pruebas o testeos pueden resultar complicados debido al despliegue distribuido. 
  2. Un gran número de servicios puede dar lugar a grandes bloques de información que gestionar. 
  3. Será labor de los desarrolladores lidiar con aspectos como la latencia de la red, tolerancia a fallos, balanceo de carga, cantidad de formatos admitidos, etc… 
  4. Sistema distribuido puede llegar a significar doble trabajo. 
  5. Si se cuenta con un gran número de servicios, integrarlos y gestionarlos puede resultar muy complejo. 
  6. Esta tecnología suele incurrir en un alto consumo de memoria. 
  7. Fragmentar una aplicación en diferentes microservicios puede llevar muchas horas de planificación (y casi podría considerarse un arte).

Retos y consejos

Una arquitectura de microservicios puede parecer muy beneficiosa, pero como todo, tiene sus pros y contras. Como cualquier arquitectura software.

Además, está muy extendida la idea de que solo con microservicios se puede llegar al despliegue continuo o a la entrega continua, pero esto no es así. Empresas como Facebook tienen despliegue continuo sin tener una arquitectura de microservicios.

Lo que hay que tener en cuenta es que los microservicios introducen complejidad, que hay que gestionar. Hay que hacer un gran esfuerzo en despliegues automáticos (si tienes 300 microservicios no puedes estar desplegando cada uno de ellos a mano), monitorización (si falla uno, no puedes ir mirando uno a uno a ver qué pasa), gestionar fallos, consistencia de datos, estrategia de pruebas y más factores que introducen los sistemas distribuidos.

Como dice Martin Fowler: “hay formas conocidas de gestionar todo esto, pero es esfuerzo extra, y nadie que conozco en desarrollo software parece tener muchísimo tiempo libre.”

Por otra parte, si el software es muy simple, no te metieras en un enfoque de microservicios. En cambio, si ya se vuelve muy complejo de gestionar y vale la pena invertir esfuerzo en ello, adelante. Empresas muy grandes lo han hecho.

Puede que haya gente que desarrolle una aplicación nueva utilizando microservicios, pero el enfoque que más me he encontrado es de empresas que han visto que gestionar su software como “monolito” es tan complejo, que han empezado a separar la aplicación en microservicios o a gestionar desarrollos nuevos de esa manera.

En este caso, si aconsejaría evolucionar la arquitectura hacia microservicios, pero poco a poco, manteniendo una parte monolítica, combinada con ciertos microservicios separados (las zonas más urgentes de la aplicación que necesitan ser desacopladas). Para hacer esto, por ejemplo, podemos utilizar la técnica de Branch By Abstraction, entre otras estrategias.

Ejemplos de Microservicios.

No hay mejor forma de conocer el alcance que ha tenido este método de desarrollo que ver quiénes lo han implementado. Multitud de webs que sirven aplicaciones a gran escala han decidido invertir en la evolución hacia los microservicios en vistas de un futuro donde el mantenimiento y escalabilidad de sus productos es mucho más simple, efectivo y rápido. Vamos a destacar algunas de estas compañías, que lo mismo hasta os suenan:
  • Netflix : Esta plataforma tiene una arquitectura generalizada que desde hace ya un par de años (coincidiendo con su “boom” en U.S.A.) se pasó a los microservicios para el funcionamiento de sus productos. A diario recibe una media de mil millones de llamadas a sus diferentes servicios (se dice que es responsable del 30% del tráfico de Internet) y es capaz de adaptarse a más de 800 tipos de dispositivos mediante su API de streaming de vídeo, la cual para ofrecer un servicio más estable, por cada solicitud que le pedimos, ésta realiza cinco solicitudes a diferentes servidores para no perder nunca la continuidad de la transmisión.
  • Amazon : No soporta tantos dispositivos como Netflix, pero tampoco es que sea fundamental para cubrir su sector. Migró hace tres años a la arquitectura de microservicios siendo una de las primeras grandes compañías que la implementaban en producción. No hay cifra aproximada de la cantidad de solicitudes que pueden recibir a diario, pero no son pocas. Entre éstas encontramos multitud de aplicaciones, las API del servicio web que ofrecen o la propia web de Amazon, cuyos ingenieros reconocen que habría sido imposible sobre la arquitectura monolítica con la que trabajaban previamente.
  • Ebay : Cómo no, una de las empresas con mayor visión de futuro, siendo pionera en la adopción de tecnologías como Docker o ésta que nos ocupa. Su aplicación principal comprende varios servicios autónomos, y cada uno ejecutará la lógica propia de cada área funcional que se ofrece a los clientes.
La velocidad gana en el mercado y la idea de Microservicios es ganar en velocidad, también. Microservicios parece un estilo muy potente e interesante, sobretodo para aplicaciones enterprise, o proyectos que seguro van a escalar. Pero Microservicios no es para todos. Si se va a usar microservicios, puede que sea buena idea integrar primero DevOps y las herramientas de DevOps en la organización.

No hay comentarios:

Publicar un comentario