BLOG | NGINX

Elección de una estrategia de implementación de microservicios

NGINX - Parte de F5 - horizontal, negro, tipo RGB
Miniatura de Chris Richardson
Chris Richardson
Publicado el 10 de febrero de 2016

Editor – Esta serie de siete artículos ya está completa:

  1. Introducción a los microservicios
  2. Construyendo microservicios: Uso de una API Gateway
  3. Construyendo microservicios: Comunicación entre procesos en una arquitectura de microservicios
  4. Descubrimiento de servicios en una arquitectura de microservicios
  5. Gestión de datos basada en eventos para microservicios
  6. Cómo elegir una estrategia de implementación de microservicios (este artículo)
  7. Refactorización de un monolito en microservicios

También puede descargar el conjunto completo de artículos, además de información sobre la implementación de microservicios utilizando NGINX Plus, como un libro electrónico: Microservicios: Desde el diseño hasta la implementación . Y consulte nuestra serie sobre la Arquitectura de referencia de microservicios y la página de Soluciones de microservicios .

Este es el sexto artículo de una serie sobre la creación de aplicações con microservicios. El primer artículo presenta el patrón de arquitectura de microservicios y analiza los beneficios y desventajas de utilizar microservicios. Los siguientes artículos analizan diferentes aspectos de la arquitectura de microservicios: uso de una API Gateway , comunicación entre procesos , descubrimiento de servicios y gestión de datos basada en eventos . En este artículo, analizamos estrategias para implementar microservicios.

Motivaciones

Implementar una aplicação monolítica significa ejecutar varias copias idénticas de una única aplicação, normalmente de gran tamaño. Normalmente, se aprovisionan N servidores (físicos o virtuales) y se ejecutan M instancias de la aplicação en cada uno. La implementación de una aplicação monolítica no siempre es completamente sencilla, pero es mucho más simple que implementar una aplicação de microservicios.

Una aplicação de microservicios consta de decenas o incluso cientos de servicios. Los servicios están escritos en una variedad de lenguajes y marcos. Cada una es una aplicação con sus propios requisitos específicos de implementación, recursos, escalamiento y monitoreo. Por ejemplo, necesita ejecutar una determinada cantidad de instancias de cada servicio en función de la demanda de ese servicio. Además, cada instancia de servicio debe contar con los recursos de CPU, memoria y E/S adecuados. Lo que es aún más desafiante es que, a pesar de esta complejidad, la implementación de servicios debe ser rápida, confiable y rentable.

Hay algunos patrones diferentes de implementación de microservicios. Veamos primero el patrón de múltiples instancias de servicio por host.

Patrón de múltiples instancias de servicio por host

Una forma de implementar sus microservicios es utilizar el patrón Múltiples instancias de servicio por host . Al utilizar este patrón, se aprovisionan uno o más hosts físicos o virtuales y se ejecutan múltiples instancias de servicio en cada uno. En muchos sentidos, este es el enfoque tradicional para la implementación de aplicação . Cada instancia de servicio se ejecuta en un puerto conocido en uno o más hosts. Las máquinas host son comúnmente tratadas como mascotas .

El siguiente diagrama muestra la estructura de este patrón.

Patrón de múltiples instancias de servicio por host para implementar aplicações basadas en la arquitectura de microservicios

Hay un par de variantes de este patrón. Una variante es que cada instancia de servicio sea un proceso o un grupo de procesos. Por ejemplo, puede implementar una instancia de servicio Java como una aplicação web en un servidor Apache Tomcat . Una instancia de servicio Node.js puede constar de un proceso principal y uno o más procesos secundarios.

La otra variante de este patrón es ejecutar múltiples instancias de servicio en el mismo proceso o grupo de procesos. Por ejemplo, puede implementar múltiples aplicações web Java en el mismo servidor Apache Tomcat o ejecutar múltiples paquetes OSGI en el mismo contenedor OSGI.

El patrón de múltiples instancias de servicio por host tiene ventajas y desventajas. Una ventaja importante es que el uso de recursos es relativamente eficiente. Varias instancias de servicio comparten el servidor y su sistema operativo. Es aún más eficiente si un proceso o grupo de procesos ejecuta múltiples instancias de servicio, por ejemplo, múltiples aplicações web que comparten el mismo servidor Apache Tomcat y JVM.

Otro beneficio de este patrón es que implementar una instancia de servicio es relativamente rápido. Simplemente copia el servicio a un host y lo inicia. Si el servicio está escrito en Java, copia un archivo JAR o WAR. Para otros lenguajes, como Node.js o Ruby, copia el código fuente. En cualquier caso, la cantidad de bytes copiados a través de la red es relativamente pequeña.

Además, debido a la falta de gastos generales, iniciar un servicio suele ser muy rápido. Si el servicio es un proceso propio, simplemente lo inicias. De lo contrario, si el servicio es una de varias instancias que se ejecutan en el mismo proceso contenedor o grupo de procesos, debe implementarlo dinámicamente en el contenedor o reiniciarlo.

A pesar de su atractivo, el patrón de múltiples instancias de servicio por host tiene algunos inconvenientes importantes. Una desventaja importante es que hay poco o ningún aislamiento de las instancias de servicio, a menos que cada instancia de servicio sea un proceso separado. Si bien puede monitorear con precisión la utilización de recursos de cada instancia de servicio, no puede limitar los recursos que utiliza cada instancia. Es posible que una instancia de servicio con mal funcionamiento consuma toda la memoria o CPU del host.

No existe ningún aislamiento si varias instancias de servicio se ejecutan en el mismo proceso. Todas las instancias podrían, por ejemplo, compartir el mismo montón de JVM. Una instancia de servicio que funciona mal podría fácilmente dañar otros servicios que se ejecutan en el mismo proceso. Además, no tienes forma de monitorear los recursos utilizados por cada instancia de servicio.

Otro problema importante con este enfoque es que el equipo de operaciones que implementa un servicio debe conocer los detalles específicos de cómo hacerlo. Los servicios se pueden escribir en una variedad de lenguajes y marcos, por lo que hay muchos detalles que el equipo de desarrollo debe compartir con operaciones. Esta complejidad aumenta el riesgo de errores durante la implementación.

Como puede ver, a pesar de su familiaridad, el patrón de múltiples instancias de servicio por host tiene algunas desventajas importantes. Veamos ahora otras formas de implementar microservicios que eviten estos problemas.

Patrón de instancia de servicio por host

Otra forma de implementar sus microservicios es el patrón de instancia de servicio por host . Cuando utiliza este patrón, ejecuta cada instancia de servicio de forma aislada en su propio host. Hay dos especializaciones diferentes de este patrón: Instancia de servicio por máquina virtual e instancia de servicio por contenedor.

Instancia de servicio por patrón de máquina virtual

Al usar el patrón "Instancia de Servicio por Máquina Virtual" , cada servicio se empaqueta como una imagen de máquina virtual (VM), como una AMI de Amazon EC2 . Cada instancia de servicio es una VM (por ejemplo, una instancia EC2) que se inicia usando esa imagen de VM. El siguiente diagrama muestra la estructura de este patrón:

El patrón de instancia de servicio por máquina virtual para implementar aplicações basadas en la arquitectura de microservicios

Este es el enfoque principal utilizado por Netflix para implementar su servicio de transmisión de video. Netflix empaqueta cada uno de sus servicios como una AMI EC2 utilizando Aminator . Cada instancia de servicio en ejecución es una instancia EC2.

Existen diversas herramientas que puedes usar para crear tus propias máquinas virtuales. Puedes configurar tu servidor de integración continua (CI) (por ejemplo, Jenkins ) para que invoque Aminator y empaquete tus servicios como una AMI de EC2. Packer.io es otra opción para la creación automatizada de imágenes de máquinas virtuales. A diferencia de Aminator, admite una variedad de tecnologías de virtualización, incluidas EC2, DigitalOcean, VirtualBox y VMware.

La empresa Boxfuse tiene una forma convincente de crear imágenes de VM, que supera los inconvenientes de las VM que describo a continuación. Boxfuse empaqueta su aplicação Java como una imagen de VM mínima. Estas imágenes se crean rápidamente, se inician rápidamente y son más seguras ya que exponen una superficie de ataque limitada.

La empresa CloudNative tiene Bakery, una oferta SaaS para crear AMI EC2. Puede configurar su servidor CI para invocar Bakery después de que pasen las pruebas para su microservicio. The Bakery empaqueta su servicio como una AMI. Usar una oferta SaaS como The Bakery significa que no tendrá que perder tiempo valioso configurando la infraestructura de creación de AMI.

El patrón de instancia de servicio por máquina virtual tiene una serie de beneficios. Una de las principales ventajas de las máquinas virtuales es que cada instancia de servicio se ejecuta de forma completamente aislada. Tiene una cantidad fija de CPU y memoria y no puede robar recursos de otros servicios.

Otro beneficio de implementar sus microservicios como máquinas virtuales es que puede aprovechar la infraestructura de nube madura. Las nubes como AWS ofrecen funciones útiles como equilibrio de carga y escalamiento automático.

Otro gran beneficio de implementar su servicio como una máquina virtual es que encapsula la tecnología de implementación de su servicio. Una vez que un servicio se ha empaquetado como una máquina virtual, se convierte en una caja negra. La API de administración de la VM se convierte en la API para implementar el servicio. La implementación se vuelve mucho más sencilla y confiable.

Sin embargo, el patrón de instancia de servicio por máquina virtual tiene algunas desventajas. Una desventaja es la utilización menos eficiente de los recursos. Cada instancia de servicio tiene la sobrecarga de una máquina virtual completa, incluido el sistema operativo. Además, en una IaaS pública típica, las máquinas virtuales tienen tamaños fijos y es posible que estén subutilizadas.

Además, una IaaS pública normalmente cobra por las máquinas virtuales independientemente de si están ocupadas o inactivas. Una IaaS como AWS proporciona escalamiento automático, pero es difícil reaccionar rápidamente a los cambios en la demanda . Por lo tanto, a menudo es necesario aprovisionar en exceso las máquinas virtuales, lo que aumenta el coste de implementación.

Otra desventaja de este enfoque es que la implementación de una nueva versión de un servicio suele ser lenta. Las imágenes de máquinas virtuales suelen tardar mucho en crearse debido a su tamaño. Además, las máquinas virtuales suelen ser lentas de instanciar, nuevamente debido a su tamaño. Además, un sistema operativo normalmente tarda cierto tiempo en iniciarse. Sin embargo, tenga en cuenta que esto no es universalmente cierto, ya que existen máquinas virtuales livianas como las creadas por Boxfuse.

Otra desventaja del patrón de instancia de servicio por máquina virtual es que, generalmente, usted (o alguna otra persona en su organización) es responsable de una gran cantidad de trabajo pesado e indiferenciado. A menos que utilice una herramienta como Boxfuse que se encargue de la sobrecarga de creación y administración de las máquinas virtuales, entonces es su responsabilidad. Esta actividad necesaria pero que consume mucho tiempo distrae de su negocio principal.

Veamos ahora una forma alternativa de implementar microservicios que es más liviana pero que aún tiene muchos de los beneficios de las máquinas virtuales.

Instancia de servicio por patrón de contenedor

Cuando se utiliza el patrón Instancia de servicio por contenedor , cada instancia de servicio se ejecuta en su propio contenedor. Los contenedores son un mecanismo de virtualización a nivel de sistema operativo . Un contenedor consta de uno o más procesos que se ejecutan en un entorno aislado. Desde la perspectiva de los procesos, tienen su propio espacio de nombres de puerto y sistema de archivos raíz. Puede limitar los recursos de CPU y memoria de un contenedor. Algunas implementaciones de contenedores también tienen limitación de velocidad de E/S. Algunos ejemplos de tecnologías de contenedores son Docker y Solaris Zones .

El siguiente diagrama muestra la estructura de este patrón:

El patrón de instancia de servicio por contenedor para implementar aplicações basadas en la arquitectura de microservicios

Para utilizar este patrón, empaquete su servicio como una imagen de contenedor. Una imagen de contenedor es una imagen del sistema de archivos que consta de las aplicações y bibliotecas necesarias para ejecutar el servicio. Algunas imágenes de contenedores constan de un sistema de archivos raíz de Linux completo. Otros son más ligeros. Para implementar un servicio Java, por ejemplo, usted crea una imagen de contenedor que contiene el entorno de ejecución de Java, quizás un servidor Apache Tomcat y su aplicação Java compilada.

Una vez que haya empaquetado su servicio como una imagen de contenedor, podrá lanzar uno o más contenedores. Normalmente se ejecutan varios contenedores en cada host físico o virtual. Puede utilizar un administrador de clústeres como Kubernetes o Marathon para administrar sus contenedores. Un administrador de clúster trata a los hosts como un grupo de recursos. Decide dónde colocar cada contenedor en función de los recursos requeridos por el contenedor y los recursos disponibles en cada host.

El patrón de instancia de servicio por contenedor tiene ventajas y desventajas. Las ventajas de los contenedores son similares a las de las máquinas virtuales: aíslan las instancias de servicio entre sí. Puede supervisar fácilmente los recursos consumidos por cada contenedor. Además, al igual que las máquinas virtuales, los contenedores encapsulan la tecnología utilizada para implementar sus servicios. La API de gestión de contenedores también sirve como API para administrar sus servicios.

Sin embargo, a diferencia de las máquinas virtuales, los contenedores son una tecnología liviana. Las imágenes de contenedores suelen crearse muy rápidamente. Por ejemplo, en mi computadora portátil, toma apenas 5 segundos empaquetar una aplicação Spring Boot como un contenedor Docker. Los contenedores también se inician muy rápidamente ya que no hay un mecanismo de arranque del sistema operativo prolongado. Cuando se inicia un contenedor, lo que se ejecuta es el servicio.

El uso de contenedores presenta algunas desventajas. Si bien la infraestructura de contenedores está madurando rápidamente, no es tan madura como la infraestructura para máquinas virtuales. Además, los contenedores no son tan seguros como las máquinas virtuales, ya que comparten el kernel del sistema operativo host.

Otra desventaja de los contenedores es que usted es responsable del trabajo pesado e indiferenciado de administrar las imágenes de los contenedores. Además, a menos que utilice una solución de contenedor alojado, como Google Container Engine o Amazon EC2 Container Service (ECS), deberá administrar la infraestructura del contenedor y posiblemente la infraestructura de VM en la que se ejecuta.

Además, los contenedores a menudo se implementan en una infraestructura que tiene precios por máquina virtual. En consecuencia, como se describió anteriormente, es probable que incurra en el costo adicional de aprovisionar en exceso las máquinas virtuales para poder manejar picos de carga.

Curiosamente, es probable que la distinción entre contenedores y máquinas virtuales se desdibuje. Como se mencionó anteriormente, las máquinas virtuales de Boxfuse son rápidas de construir e iniciar. El proyecto Clear Containers busca crear máquinas virtuales ligeras. [Editor: Como se anunció en diciembre de 2017, el desarrollo de Clear Containers continúa en el proyecto de código abierto Kata Containers ]. También existe un creciente interés en los unikernels . Docker, Inc. adquirió recientemente Unikernel Systems.

También existe el concepto más nuevo y cada vez más popular de implementación sin servidor, un enfoque que evita tener que elegir entre implementar servicios en contenedores o máquinas virtuales. Analicémoslo a continuación.

Implementación sin servidor

AWS Lambda es un ejemplo de tecnología de implementación sin servidor. Admite servicios Java, Node.js y Python. Para implementar un microservicio, debe empaquetarlo como un archivo ZIP y cargarlo en AWS Lambda. También debe proporcionar metadatos que, entre otras cosas, especifican el nombre de la función que se invoca para manejar una solicitud (también conocida como evento). AWS Lambda ejecuta automáticamente suficientes instancias de su microservicio para manejar las solicitudes. Simplemente se le factura cada solicitud en función del tiempo empleado y la memoria consumida. Por supuesto, el diablo está en los detalles y pronto verás que AWS Lambda tiene limitaciones. Pero la idea de que ni usted como desarrollador ni nadie en su organización necesita preocuparse por ningún aspecto de los servidores, las máquinas virtuales o los contenedores es increíblemente atractiva.

Una función Lambda es un servicio sin estado. Generalmente maneja solicitudes invocando servicios de AWS. Por ejemplo, una función Lambda que se invoca cuando se carga una imagen en un bucket S3 podría insertar un elemento en una tabla de imágenes de DynamoDB y publicar un mensaje en una secuencia de Kinesis para activar el procesamiento de la imagen. Una función Lambda también puede invocar servicios web de terceros.

Hay cuatro formas de invocar una función Lambda:

  1. Directamente, mediante una solicitud de servicio web
  2. Automáticamente, en respuesta a un evento generado por un servicio de AWS como S3, DynamoDB, Kinesis o Simple Email Service
  3. Automáticamente, a través de una API Gateway de AWS para gestionar solicitudes HTTP de los clientes de la aplicação
  4. Periódicamente, según una programación similar a la de un cron

Como puede ver, AWS Lambda es una forma conveniente de implementar microservicios. El precio basado en solicitudes significa que usted solo paga por el trabajo que sus servicios realmente realizan. Además, como no eres responsable de la infraestructura de TI, puedes concentrarte en desarrollar tu aplicação.

Sin embargo, existen algunas limitaciones importantes. No está destinado a utilizarse para implementar servicios de larga duración, como un servicio que consume mensajes de un agente de mensajes de terceros. Las solicitudes deben completarse dentro de los 300 segundos. Los servicios deben ser sin estado, ya que en teoría AWS Lambda podría ejecutar una instancia separada para cada solicitud. Deben estar escritos en uno de los idiomas admitidos. Los servicios también deben iniciarse rápidamente; de lo contrario, podrían agotar el tiempo de espera y finalizar.

resumen

Implementar una aplicação de microservicios es un desafío. Hay decenas o incluso cientos de servicios escritos en una variedad de lenguajes y marcos. Cada una es una aplicação con sus propios requisitos específicos de implementación, recursos, escalamiento y monitoreo. Hay varios patrones de implementación de microservicios, incluida la instancia de servicio por máquina virtual y la instancia de servicio por contenedor. Otra opción interesante para implementar microservicios es AWS Lambda, un enfoque sin servidor. En la próxima y última parte de esta serie, veremos cómo migrar una aplicação monolítica a una arquitectura de microservicios.

Editor – Esta serie de siete artículos ya está completa:

  1. Introducción a los microservicios
  2. Construyendo microservicios: Uso de una API Gateway
  3. Construyendo microservicios: Comunicación entre procesos en una arquitectura de microservicios
  4. Descubrimiento de servicios en una arquitectura de microservicios
  5. Gestión de datos basada en eventos para microservicios
  6. Cómo elegir una estrategia de implementación de microservicios (este artículo)
  7. Refactorización de un monolito en microservicios

También puede descargar el conjunto completo de artículos, además de información sobre la implementación de microservicios utilizando NGINX Plus, como un libro electrónico: Microservicios: Desde el diseño hasta la implementación . Y consulte nuestra serie sobre la Arquitectura de referencia de microservicios y la página de Soluciones de microservicios .

El bloguero invitado Chris Richardson es el fundador del CloudFoundry.com original, una de las primeras PaaS (plataforma como servicio) de Java para Amazon EC2. Ahora asesora a organizaciones para mejorar la forma en que desarrollan e implementan aplicações. También escribe periódicamente sobre microservicios en https://microservices.io .


"Esta publicación de blog puede hacer referencia a productos que ya no están disponibles o que ya no reciben soporte. Para obtener la información más actualizada sobre los productos y soluciones F5 NGINX disponibles, explore nuestra familia de productos NGINX . NGINX ahora es parte de F5. Todos los enlaces anteriores de NGINX.com redirigirán a contenido similar de NGINX en F5.com.