Spring Microservices in Action
Spring Microservices in Action
Sobre el código
Spring Microservices in Action incluye código en cada capítulo. Todos los ejemplos de código están
disponibles en mi repositorio de GitHub, y cada capítulo tiene su propio repositorio. Puede encontrar
una página de resumen con enlaces al repositorio de código de cada capítulo en
https://github.com/carnellj/spmia_overview. También está disponible un código postal que contiene
todo el código fuente en el sitio web del editor en www.manning.com/books/spring-microservices-in-
action.
Todo el código en este libro está diseñado para ejecutarse en Java 8 usando Maven como la
herramienta de compilación principal. Consulte el apéndice A de este libro para obtener detalles
completos sobre las herramientas de software que necesitará para compilar y ejecutar los ejemplos
de código.
Este libro contiene muchos ejemplos de código fuente tanto en listados numerados como en línea con
el texto normal. En ambos casos, el código fuente está formateado en una fuente de ancho fijo como
este para separarlo del texto ordinario. A veces, el código también está en negrita para resaltar el
código que ha cambiado desde los pasos anteriores del capítulo, como cuando una nueva
característica se agrega a una línea de código existente.
En muchos casos, el código fuente original ha sido reformateado; agregamos saltos de línea y
rediseñamos la sangría para acomodar el espacio de página disponible en el libro. En casos raros,
incluso esto no fue suficiente, y los listados incluyen marcadores de continuación de línea (➥).
Además, los comentarios en el código fuente a menudo se han eliminado de los listados cuando el
código se describe en el texto. Las anotaciones de código acompañan a muchos de los listados,
destacando conceptos importantes.
Autor en línea
La compra de Spring Microservices in Action incluye acceso gratuito a un foro web privado
administrado por Manning Publications donde puede hacer comentarios sobre el libro, hacer preguntas
técnicas y recibir ayuda del autor y de otros usuarios. Para acceder al foro y suscribirse, dirija su
navegador web a www.manning.com/books/spring-microservices-in-action. Esta página proporciona
información sobre cómo ingresar al foro una vez que se haya registrado, qué tipo de ayuda está
disponible y las reglas de conducta en el foro.
El compromiso de Manning con nuestros lectores es proporcionar un lugar donde pueda tener lugar
un diálogo significativo entre lectores individuales y entre lectores y el autor. No es un compromiso
con una cantidad específica de participación por parte del autor, cuyas contribuciones a la AO siguen
siendo voluntarias (y no remuneradas). Le sugerimos que haga preguntas desafiantes al autor, ¡para
que su interés no se pierda!
Sobre el Autor
JOHN CARNELL es ingeniero de nube senior en Genesys, donde trabaja en la división PureCloud de
Genesys. John pasa la mayor parte de su día desarrollando microservicios basados en telefonía
utilizando la plataforma AWS. Su trabajo diario se centra en diseñar y construir microservicios en una
serie de plataformas tecnológicas, incluidas Java, Clojure y Go.
John es un prolífico orador y escritor. Habla regularmente en grupos de usuarios locales y ha sido un
orador habitual en el "Simposio de software No Fluff Just Stuff". Durante los últimos 20 años, John ha
sido autor, coautor y ha sido un revisor técnico para una serie de programas basados en Java libros
de tecnología y publicaciones de la industria.
John tiene una Licenciatura en Artes (BA) de la Universidad Marquette y una Maestría en
Administración de Empresas (MBA) de la Universidad de Wisconsin Oshkosh.
Durante su tiempo libre (del cual hay muy poco), John corre, persigue a sus hijos y estudia artes
marciales filipinas.
Sobre la ilustración de la portada
La figura en la portada de Spring Microservices in Action está titulada "Un hombre de Croacia". Esta
ilustración está tomada de una reimpresión reciente de las imágenes y descripciones de Balthasar
Hacquet de Wenda, ilirios y eslavos del sudoeste y este, publicados por el Museo Etnográfico. en Split,
Croacia, en 2008. Hacquet (1739-1815) fue un médico y científico austriaco que pasó muchos años
estudiando la botánica, la geología y la etnografía de muchas partes del Imperio austríaco, así como
el Véneto, los Alpes Julianos, y los Balcanes occidentales, habitados en el pasado por pueblos de las
tribus ilirias. Las ilustraciones dibujadas a mano acompañan a los numerosos artículos y libros
científicos que Hacquet publicó.
La rica diversidad de los dibujos en las publicaciones de Hacquet habla vívidamente de la singularidad
e individualidad de las regiones alpinas orientales y de los Balcanes del noroeste hace solo 200 años.
Este fue un momento en que los códigos de vestimenta de dos pueblos separados por unas pocas
millas identificaban a personas que pertenecían únicamente a uno u otro, y cuando los miembros de
una clase social o comercio podían distinguirse fácilmente por lo que llevaban puesto. Los códigos de
vestimenta han cambiado desde entonces y la diversidad por región, tan rica en ese momento, se ha
desvanecido. Ahora a menudo es difícil distinguir al habitante de un continente de otro, y hoy los
habitantes de las pintorescas ciudades y pueblos de los Alpes eslovenos o las ciudades costeras de
los Balcanes no se distinguen fácilmente de los residentes de otras partes de Europa.
La única constante en el campo del desarrollo de software es que nosotros, como desarrolladores de
software, nos sentamos en medio de un mar de caos y cambio. Todos sentimos la agitación cuando
nuevas tecnologías y enfoques aparecen repentinamente en la escena, lo que nos hace reevaluar
cómo construimos y brindamos soluciones para nuestros clientes. Un ejemplo de este abandono es la
rápida adopción por parte de muchas organizaciones de la creación de aplicaciones utilizando
microservicios. Los microservicios son servicios de software distribuidos y poco acoplados que
realizan una pequeña cantidad de tareas bien definidas.
Este libro le presenta la arquitectura de microservicios y por qué debería considerar construir sus
aplicaciones con ellos. Vamos a ver cómo construir microservicios utilizando Java y dos proyectos de
Spring Framework: Spring Boot y Spring Cloud. Si usted es un desarrollador de Java, Spring Boot y
Spring Cloud proporcionarán una ruta de migración fácil desde la creación de aplicaciones Spring
tradicionales y monolíticas hasta aplicaciones de microservicios que se pueden implementar en la
nube.
Si bien una aplicación puede implementarse como una sola unidad de trabajo, la mayoría de las veces
habrá múltiples equipos de desarrollo trabajando en la aplicación. Cada equipo de desarrollo tendrá
sus propias piezas discretas de la aplicación de las que son responsables y, a menudo, clientes
específicos a los que atiende con su pieza funcional. Por ejemplo, cuando trabajaba en una gran
empresa de servicios financieros, teníamos una aplicación interna de gestión de relaciones con el
cliente (CRM) personalizada que involucraba la coordinación de múltiples equipos, incluida la interfaz
de usuario, el maestro de clientes, el almacén de datos y El equipo de fondos mutuos. La figura 1.1
ilustra la arquitectura básica de esta aplicación.
El problema aquí es que a medida que creció el tamaño y la complejidad de la aplicación CRM
monolítica, los costos de comunicación y coordinación de los equipos individuales que trabajan en la
aplicación no se escalaron. Cada vez que un equipo individual necesitaba hacer un cambio, la
aplicación completa tenía que reconstruirse, volver a probarse y volver a implementarse.
A menudo bromeo con mis colegas acerca de que los microservicios son la droga de entrada para
crear aplicaciones en la nube. Comienza a construir microservicios porque le brindan un alto grado de
flexibilidad y autonomía con sus equipos de desarrollo, pero usted y su equipo rápidamente descubren
que la naturaleza pequeña e independiente de los microservicios los hace fácilmente implementables
en la nube. Una vez que los servicios están en la nube, su pequeño tamaño hace que sea fácil iniciar
un gran número de instancias del mismo servicio, y de repente sus aplicaciones se vuelven más
escalables y, con previsión, más resistentes.
Esto es problemático en un proyecto grande porque estos enlaces externos son frágiles y hacer un
cambio puede resultar en múltiples impactos posteriores a otro código. Un marco de inyección de
dependencias, como Spring, le permite administrar más fácilmente grandes proyectos Java al
externalizar la relación entre los objetos dentro de su aplicación a través de convenciones (y
anotaciones) en lugar de aquellos objetos que tienen conocimiento codificado el uno del otro. Spring
se sienta como intermediario entre las diferentes clases Java de su aplicación y gestiona sus
dependencias. Spring esencialmente te permite ensamblar tu código como un conjunto de ladrillos de
Lego que se unen.
Spring Boot es una reinvención del marco Spring. Si bien abarca las características principales de
Spring, Spring Boot elimina muchas de las características "empresariales" que se encuentran en
Spring y, en cambio, ofrece un marco orientado a los microservicios (Transferencia de estado
representativo) [1] basados en Java y orientados a REST. Con unas pocas anotaciones simples, un
desarrollador de Java puede construir rápidamente un microservicio REST que puede empaquetarse
e implementarse sin la necesidad de un contenedor de aplicaciones externo.
Nota
Si bien cubrimos REST con más detalle en el capítulo 2, el concepto central detrás de REST es que
sus servicios deben adoptar el uso de los verbos HTTP (GET, POST, PUT y DELETE) para representar
las acciones centrales del servicio y usar un peso ligero protocolo de serialización de datos orientado
a la web, como JSON, para solicitar y recibir datos del servicio.
Debido a que los microservicios se han convertido en uno de los patrones arquitectónicos más
comunes para construir aplicaciones basadas en la nube, la comunidad de desarrollo de Spring nos
ha dado Spring Cloud. El marco Spring Cloud simplifica la operacionalización y la implementación de
microservicios en una nube pública o privada. Spring Cloud envuelve varios marcos de microservicios
de administración de nube populares en un marco común y hace que el uso y la implementación de
estas tecnologías sean tan fáciles de usar como anotar su código. Cubro los diferentes componentes
dentro de Spring Cloud más adelante en este capítulo.
Elegí escribir este libro por dos razones. Primero, aunque he visto muchos buenos libros sobre los
aspectos conceptuales de los microservicios, no pude encontrar un buen libro basado en Java sobre
la implementación de microservicios. Si bien siempre me he considerado un políglota de lenguaje de
programación (alguien que sabe y habla varios idiomas), Java es mi lenguaje de desarrollo central y
Spring ha sido el marco de desarrollo al que "alcanzo" cada vez que construyo una nueva aplicación.
Cuando me encontré por primera vez con Spring Boot y Spring Cloud, me quedé impresionado. Spring
Boot y Spring Cloud simplificaron enormemente mi vida de desarrollo a la hora de crear aplicaciones
basadas en microservicios que se ejecutan en la nube.
En segundo lugar, como he trabajado a lo largo de mi carrera como arquitecto e ingeniero, descubrí
que muchas veces los libros de tecnología que compro tienden a ir a uno de los dos extremos. Son
conceptuales sin ejemplos concretos de código o son descripciones mecánicas de un marco particular
o lenguaje de programación. Quería un libro que fuera un buen puente y un punto medio entre las
disciplinas de arquitectura e ingeniería. Mientras lees este libro, quiero darte una introducción sólida
al desarrollo de patrones de microservicios y cómo se usan en el desarrollo de aplicaciones del mundo
real, y luego respaldar estos patrones con ejemplos de código prácticos y fáciles de entender usando
Spring Boot y Spring Cloud.
Cambiemos de marcha por un momento y recorramos la construcción de un microservicio simple con
Spring Boot.
1.5. Construyendo un microservicio con Spring Boot
Siempre he tenido la opinión de que un marco de desarrollo de software está bien pensado y es fácil
de usar si pasa lo que cariñosamente llamo la "Prueba del mono de Carnell". Si un mono como yo (el
autor) puede encontrar un marco en 10 minutos o menos, tiene promesa. Así es como me sentí la
primera vez que escribí una muestra del servicio Spring Boot. Quiero que tenga la misma experiencia
y alegría, así que tomemos un minuto para ver cómo escribir un simple servicio REST "Hello World"
usando Spring Boot.
En esta sección, no vamos a hacer un recorrido detallado de gran parte del código presentado. Nuestro
objetivo es darle una idea de cómo escribir un servicio Spring Boot. Entraremos en mucho más detalle
en el capítulo 2.
La Figura 1.3 muestra lo que su servicio va a hacer y el flujo general de cómo el microservicio Spring
Boot procesará la solicitud de un usuario.
Figura 1.3. Spring Boot abstrae la tarea común de microservicio REST (enrutamiento a la lógica
empresarial, análisis de parámetros HTTP desde la URL, asignación de JSON a / desde objetos Java)
y permite al desarrollador centrarse en la lógica empresarial para el servicio.
Este ejemplo no es exhaustivo o incluso ilustrativo de cómo debe crear un microservicio a nivel de
producción, pero debe hacer que haga una pausa debido al poco código que se necesitó para
escribirlo. No veremos cómo configurar los archivos de compilación del proyecto o los detalles del
código hasta el capítulo 2. Si desea ver el archivo pom.xml de Maven y el código real, puede
encontrarlo en el Capítulo 1 sección del código descargable. Todo el código fuente del capítulo 1 se
puede recuperar del repositorio de GitHub para el libro en https://github.com/carnellj/spmia-chapter1.
Nota
Asegúrese de leer el apéndice A antes de intentar ejecutar los ejemplos de código para los capítulos
de este libro. El Apéndice A cubre el diseño general de proyectos de todos los proyectos en el libro,
cómo ejecutar los scripts de compilación y cómo iniciar el entorno Docker. Los ejemplos de código en
este capítulo son simples y están diseñados para ejecutarse de forma nativa desde su escritorio sin la
información en capítulos adicionales. Sin embargo, en capítulos posteriores comenzará a utilizar
Docker rápidamente para ejecutar todos los servicios e infraestructura utilizados en este libro. No
profundice demasiado en el libro sin leer el apéndice A sobre la configuración de su entorno de
escritorio.
En el listado 1.1 básicamente está exponiendo un único punto final GET HTTP que tomará dos
parámetros (nombre y apellido) en la URL y luego devolverá una cadena JSON simple que tiene una
carga que contiene el mensaje "Hola, nombre, apellido". Si tuviera que llamar al punto final / hello /
john / carnell en su servicio (que mostraré en breve) la devolución de la llamada sería
Pongamos en marcha su servicio. Para hacer esto, vaya al símbolo del sistema y emita el siguiente
comando:
mvn spring-boot:run
Este comando, mvn, utilizará un complemento Spring Boot para iniciar la aplicación utilizando un
servidor Tomcat incorporado.
Java contra Groovy y Maven contra Gradle
El marco Spring Boot tiene un fuerte soporte tanto para Java como para los lenguajes de programación
Groovy. Puede construir microservicios con Groovy y sin configuración de proyecto. Spring Boot
también es compatible con las herramientas de compilación Maven y Gradle. He limitado los ejemplos
en este libro a Java y Maven. Como aficionado de Groovy y Gradle desde hace mucho tiempo, tengo
un gran respeto por el lenguaje y la herramienta de compilación, pero para mantener el libro manejable
y el material enfocado, elegí ir con Java y Maven para llegar a la mayor audiencia posible.
Si todo comienza correctamente, debería ver lo que se muestra en la figura 1.4 desde la ventana de
la línea de comandos.
Figura 1.4. Su servicio Spring Boot comunicará los puntos finales expuestos y el puerto del servicio a
través de la consola.
Si examina la pantalla en la figura 1.4, notará dos cosas. Primero, se inició un servidor Tomcat en el
puerto 8080. Segundo, se expone un punto final GET de / hello / {firstName} / {lastName} en el servidor.
Llamarás a tu servicio usando una herramienta REST basada en navegador llamada POSTMAN
(https://www.getpostman.com/). Muchas herramientas, tanto gráficas como de línea de comandos,
están disponibles para invocar un servicio basado en REST, pero usaré POSTMAN para todos mis
ejemplos en este libro. La figura 1.5 muestra la llamada POSTMAN al punto final
http://localhost:8080/hello/john/carnell y los resultados devueltos por el servicio.
Figure 1.5. The response from the /hello endpoint shows the data you’ve requested represented as a
JSON payload.
Obviamente, este simple ejemplo no demuestra todo el poder de Spring Boot. Pero lo que debería
mostrar es que puede escribir un servicio completo basado en HTTP JSON REST con mapeo de rutas
de URL y parámetros en Java con tan solo 25 líneas de código. Como cualquier desarrollador
experimentado de Java le dirá, escribir algo significativo en 25 líneas de código en Java es
extremadamente difícil. Java, aunque es un lenguaje poderoso, ha adquirido una reputación de ser
prolijo en comparación con otros lenguajes.
Hemos terminado con nuestro breve recorrido por Spring Boot. Ahora tenemos que hacer esta
pregunta: debido a que podemos escribir nuestras aplicaciones utilizando un enfoque de microservicio,
¿esto significa que deberíamos hacerlo? En la siguiente sección, veremos por qué y cuándo un
enfoque de microservicio está justificado para crear sus aplicaciones.
La complejidad ha aumentado: los clientes esperan que todas las partes de una organización
sepan quiénes son. Las aplicaciones "aisladas" que se comunican con una sola base de datos
y no se integran con otras aplicaciones ya no son la norma. Las aplicaciones actuales
necesitan comunicarse con múltiples servicios y bases de datos que residen no solo dentro
del centro de datos de una empresa, sino también con proveedores de servicios externos a
través de Internet.
Los clientes desean una entrega más rápida: los clientes ya no desean esperar la próxima
versión anual o versión de un paquete de software. En cambio, esperan que las características
de un producto de software se desglosen para que la nueva funcionalidad se pueda lanzar
rápidamente en semanas (incluso días) sin tener que esperar el lanzamiento completo del
producto.
Rendimiento y escalabilidad: las aplicaciones globales hacen que sea extremadamente difícil
predecir cuánto volumen de transacción va a manejar una aplicación y cuándo llegará ese
volumen de transacción. Las aplicaciones deben ampliarse rápidamente en varios servidores
y luego reducirse cuando las necesidades de volumen hayan pasado.
Los clientes esperan que sus aplicaciones estén disponibles: dado que los clientes están a un
clic de distancia de un competidor, las aplicaciones de una empresa deben ser altamente
resistentes. Las fallas o problemas en una parte de la aplicación no deberían derribar toda la
aplicación.
Para cumplir con estas expectativas, nosotros, como desarrolladores de aplicaciones, tenemos que
aceptar la paradoja de que para construir aplicaciones altamente escalables y altamente redundantes
necesitamos dividir nuestras aplicaciones en pequeños servicios que se puedan construir e
implementar independientemente uno del otro. Si "desglosamos" nuestras aplicaciones en pequeños
servicios y las alejamos de un solo artefacto monolítico, podemos construir sistemas que son:
Con este fin, al comenzar nuestra discusión sobre microservicios, tenga en cuenta lo siguiente:
Servicios pequeños, simples y desacoplados = Aplicaciones escalables, resistentes y flexibles
1.7. ¿Qué es exactamente la nube?
El término "nube" se ha usado en exceso. Todos los proveedores de software tienen una nube y la
plataforma de todos está habilitada para la nube, pero si se corta la exageración, existen tres modelos
básicos en la informática basada en la nube. Estos son:
Para comprender mejor estos conceptos, mapeemos la tarea diaria de preparar una comida a los
diferentes modelos de computación en la nube. Cuando quieres comer, tienes cuatro opciones:
Figura 1.6. Los diferentes modelos de computación en la nube se reducen a quién es responsable de
qué: el proveedor de la nube o usted.
La diferencia entre estas opciones es sobre quién es responsable de cocinar estas comidas y dónde
se cocinará la comida. En el modelo local, comer una comida en casa requiere que hagas todo el
trabajo, usando tu propio horno e ingredientes que ya están en casa. Una comida comprada en la
tienda es como usar el modelo de computación Infraestructura como servicio (IaaS). Estás usando el
chef y el horno de la tienda para hornear previamente la comida, pero aún eres responsable de calentar
la comida y comerla en la casa (y limpiar los platos después).
En un modelo de Plataforma como servicio (PaaS), usted todavía tiene la responsabilidad de la
comida, pero confía aún más en un proveedor para que se encargue de las tareas principales
asociadas con la preparación de una comida. Por ejemplo, en un modelo PaaS, usted suministra los
platos y los muebles, pero el dueño del restaurante proporciona el horno, los ingredientes y el chef
para cocinarlos. En el modelo de Software como servicio (SaaS), usted va a un restaurante donde se
prepara toda la comida para usted. Comes en el restaurante y luego pagas la comida cuando terminas.
Tampoco tiene platos para preparar o lavar.
Los elementos clave en juego en cada uno de estos modelos son los de control: ¿quién es responsable
del mantenimiento de la infraestructura y cuáles son las opciones tecnológicas disponibles para
construir la aplicación? En un modelo IaaS, el proveedor de la nube proporciona la infraestructura
básica, pero usted es responsable de seleccionar la tecnología y crear la solución final. En el otro
extremo del espectro, con un modelo SaaS, usted es un consumidor pasivo del servicio prestado por
el proveedor y no tiene aportes sobre la selección de tecnología ni ninguna responsabilidad para
mantener la infraestructura de la aplicación.
He documentado los tres tipos principales de plataformas en la nube (IaaS, PaaS, SaaS) que se usan
actualmente. Sin embargo, están surgiendo nuevos tipos de plataforma en la nube. Estas nuevas
plataformas incluyen Funciones como servicio (FaaS) y Contenedor como servicio (CaaS). Las
aplicaciones basadas en FaaS (https://en.wikipedia.org/wiki/Function_as_a_Service) utilizan
tecnologías como las tecnologías Lambda de Amazon y las funciones de Google Cloud para construir
aplicaciones desplegadas como fragmentos de código "sin servidor" que se ejecutan completamente
en la infraestructura informática de la plataforma del proveedor de la nube. Con una plataforma FaaS,
no tiene que administrar ninguna infraestructura de servidor y solo paga los ciclos informáticos
necesarios para ejecutar la función.
Con el modelo de Contenedor como Servicio (CaaS), los desarrolladores construyen e implementan
sus microservicios como contenedores virtuales portátiles (como Docker) a un proveedor de la nube.
A diferencia de un modelo IaaS, donde el desarrollador tiene que administrar la máquina virtual en la
que se implementa el servicio, con CaaS está implementando sus servicios en un contenedor virtual
liviano. El proveedor de la nube ejecuta el servidor virtual en el que se está ejecutando el contenedor,
así como las herramientas integrales del proveedor para construir, implementar, monitorear y escalar
contenedores. El Elastic Container Service (ECS) de Amazon es un ejemplo de una plataforma basada
en CaaS. En el capítulo 10 de este libro, veremos cómo implementar los microservicios que ha creado
en Amazon ECS.
Es importante tener en cuenta que con los modelos FaaS y CaaS de computación en la nube, aún
puede construir una arquitectura basada en microservicios. Recuerde, el concepto de microservicios
gira en torno a la creación de servicios pequeños, con responsabilidad limitada, utilizando una interfaz
basada en HTTP para comunicarse. Las plataformas emergentes de computación en la nube, como
FaaS y CaaS, realmente tratan sobre mecanismos de infraestructura alternativos para implementar
microservicios.
1.8. ¿Por qué la nube y los microservicios?
Uno de los conceptos centrales de una arquitectura basada en microservicios es que cada servicio se
empaqueta y se implementa como su propio artefacto discreto e independiente. Las instancias de
servicio deben aparecer rápidamente y cada instancia del servicio debe ser indistinguible de otra.
Como desarrollador que escribe un microservicio, tarde o temprano tendrá que decidir si su servicio
se implementará en uno de los siguientes:
Servidor físico: si bien puede construir e implementar sus microservicios en una máquina (s)
física (s), pocas organizaciones hacen esto porque los servidores físicos están restringidos.
No puede aumentar rápidamente la capacidad de un servidor físico y puede resultar
extremadamente costoso escalar su microservicio horizontalmente en múltiples servidores
físicos.
Imágenes de máquinas virtuales: uno de los beneficios clave de los microservicios es su
capacidad para iniciar y cerrar rápidamente instancias de microservicios en respuesta a la
escalabilidad y los eventos de falla del servicio. Las máquinas virtuales son el corazón y el
alma de los principales proveedores de la nube. Un microservicio se puede empaquetar en
una imagen de máquina virtual y luego se pueden implementar e iniciar rápidamente varias
instancias del servicio en una nube pública o privada de IaaS.
Contenedor virtual: los contenedores virtuales son una extensión natural de la
implementación de sus microservicios en una imagen de máquina virtual. En lugar de
implementar un servicio en una máquina virtual completa, muchos desarrolladores
implementan sus servicios como contenedores Docker (o tecnología de contenedores
equivalente) en la nube. Los contenedores virtuales se ejecutan dentro de una máquina virtual;
Con un contenedor virtual, puede segregar una sola máquina virtual en una serie de procesos
autónomos que comparten la misma imagen de máquina virtual.
Los servicios creados en este libro se empaquetan como contenedores Docker. Una de las razones
por las que elegí Docker es que, como tecnología de contenedor, Docker se puede implementar en
todos los principales proveedores de la nube. Más adelante en el capítulo 10, demuestro cómo
empaquetar microservicios usando Docker y luego implementar estos contenedores en la plataforma
en la nube de Amazon.
1.9. Los microservicios son más que escribir el código
Si bien los conceptos relacionados con la creación de microservicios individuales son fáciles de
entender, ejecutar y admitir una aplicación de microservicio robusta (especialmente cuando se ejecuta
en la nube) implica más que escribir el código para el servicio. Escribir un servicio robusto incluye
considerar varios temas. La Figura 1.7 destaca estos temas
Figura 1.7. Los microservicios son más que la lógica empresarial. Debe pensar en el entorno en el que
se ejecutarán los servicios y cómo los servicios se ampliarán y serán resistentes.
Este libro adopta un enfoque basado en patrones a medida que respondemos estas preguntas. Con
un enfoque basado en patrones, presentamos diseños comunes que se pueden utilizar en diferentes
implementaciones de tecnología. Si bien hemos elegido usar Spring Boot y Spring Cloud para
implementar los patrones que vamos a utilizar en este libro, nada impedirá que tome los conceptos
presentados aquí y los use con otras plataformas tecnológicas. Específicamente, cubrimos las
siguientes seis categorías de patrones de microservicio:
El patrón de desarrollo del microservicio de desarrollo central aborda los conceptos básicos de la
construcción de un microservicio. La Figura 1.8 resalta los temas que cubriremos sobre el diseño del
servicio básico
Figura 1.8. Al diseñar su microservicio, debe pensar en cómo se consumirá y se comunicará el servicio.
Los patrones de enrutamiento de microservicios tratan de cómo una aplicación cliente que quiere
consumir un microservicio descubre la ubicación del servicio y se enruta a ella. En una aplicación
basada en la nube, es posible que tenga cientos de instancias de microservicio ejecutándose. Deberá
extraer la dirección IP física de estos servicios y tener un único punto de entrada para las llamadas de
servicio, de modo que pueda aplicar de manera coherente las políticas de seguridad y contenido para
todas las llamadas de servicio.
El descubrimiento y el enrutamiento del servicio responden a la pregunta "¿Cómo hago para que la
solicitud de mi cliente de un servicio a una instancia específica de un servicio?"
Descubrimiento del servicio: ¿cómo hace que su microservicio sea reconocible para que las
aplicaciones del cliente puedan encontrarlos sin tener la ubicación del servicio codificada en la
aplicación? ¿Cómo se asegura de que las instancias de microservicio que se comportan mal se
eliminen del conjunto de instancias de servicio disponibles? Cubro el descubrimiento de servicios en
el capítulo 4.
Enrutamiento de servicios: ¿cómo proporciona un único punto de entrada para todos sus servicios
para que las políticas de seguridad y las reglas de enrutamiento se apliquen uniformemente a múltiples
servicios e instancias de servicio en sus aplicaciones de microservicio? ¿Cómo se asegura de que
cada desarrollador de su equipo no tenga que encontrar sus propias soluciones para proporcionar
enrutamiento a sus servicios? Cubro el enrutamiento de servicio en el capítulo 6.
Debido a que las arquitecturas de microservicios están altamente distribuidas, debe ser
extremadamente sensible a la hora de evitar que un problema en un solo servicio (o instancia de
servicio) caiga en cascada hacia los consumidores del servicio. Con este fin, cubriremos cuatro
patrones de resistencia del cliente:
Equilibrio de carga del lado del cliente (Client-side load balancing): ¿cómo almacena en
caché la ubicación de sus instancias de servicio en el cliente de servicio para que las llamadas
a varias instancias de un microservicio se equilibren en carga a todas las instancias de
mantenimiento de ese microservicio?
Patrón de disyuntores (Circuit breakers pattern): ¿cómo evita que un cliente continúe
llamando a un servicio que falla o sufre problemas de rendimiento? Cuando un servicio se
ejecuta lentamente, consume recursos en el cliente que lo llama. Desea que las llamadas
fallidas del microservicio fallen rápidamente para que el cliente que realiza la llamada pueda
responder rápidamente y tomar las medidas adecuadas.
Patrón de recuperación (Fallback pattern): cuando falla una llamada de servicio, ¿cómo se
proporciona un mecanismo de "complemento" que permitirá al cliente de servicio intentar
llevar a cabo su trabajo a través de medios alternativos que no sean el microservicio que se
llama?
Patrón de mampara (Bulkhead pattern): las aplicaciones de microservicios utilizan múltiples
recursos distribuidos para llevar a cabo su trabajo. ¿Cómo compartimenta estas llamadas para
que el mal comportamiento de una llamada de servicio no afecte negativamente al resto de la
aplicación?
La figura 1.10 muestra cómo estos patrones protegen al consumidor del servicio de verse afectado
cuando un servicio se está portando mal. Cubro estos cuatro temas en el capítulo 5.
Figura 1.10. Con microservicios, debe proteger a la persona que llama del servicio de un servicio que
se comporta mal. Recuerde, un servicio lento o inactivo puede causar interrupciones más allá del
servicio inmediato.
1.9.4. Patrones de seguridad de microservicios
Autenticación (Authentication): ¿cómo determina que el cliente del servicio que llama al
servicio es quién dice ser?
Autorización (Authorization): ¿cómo determina si el cliente del servicio que llama a un
microservicio puede llevar a cabo la acción que está tratando de realizar?
Gestión y propagación de credenciales (Credential management and propagation): ¿cómo
evita que un cliente de servicio tenga que presentar constantemente sus credenciales para
las llamadas de servicio involucradas en una transacción? Específicamente, veremos cómo
los estándares de seguridad basados en tokens como OAuth2 y JavaScript Web Tokens
(JWT) se pueden usar para obtener un token que se puede pasar de una llamada de servicio
a otra para autenticar y autorizar al usuario.
La Figura 1.11 muestra cómo puede implementar los tres patrones descritos anteriormente para crear
un servicio de autenticación que pueda proteger sus microservicios.
En este punto no voy a profundizar demasiado en los detalles de la figura 1.10. Hay una razón por la
cual la seguridad requiere un capítulo completo. (Honestamente podría ser un libro en sí mismo).
1.9.5. Registro de microservicios y patrones de rastreo
La figura 1.12 muestra cómo estos patrones encajan entre sí. Cubriremos los patrones de registro y
rastreo con mayor detalle en el capítulo 9.
Figura 1.12. Una estrategia de registro y rastreo bien pensada hace que las transacciones de
depuración en múltiples servicios sean manejables.
1.9.6. Patrones de construcción / implementación de microservicios
Una de las partes centrales de una arquitectura de microservicio es que cada instancia de un
microservicio debe ser idéntica a todas sus otras instancias. No puede permitir que ocurra una "deriva
de configuración" (algo cambia en un servidor después de que se haya implementado), ya que esto
puede introducir inestabilidad en sus aplicaciones.
"Hice solo un pequeño cambio en el servidor de escenario, pero olvidé hacer el cambio en la
producción". La resolución de muchos sistemas inactivos cuando trabajé en equipos de situaciones
críticas a lo largo de los años a menudo comenzó con esas palabras de un desarrollador o
administrador del sistema. Los ingenieros (y la mayoría de las personas en general) operan con
buenas intenciones. No van a trabajar para cometer errores o derribar sistemas. En cambio, están
haciendo lo mejor que pueden, pero se ocupan o se distraen. Ajustan algo en un servidor, con la plena
intención de regresar y hacerlo en todos los entornos.
En un momento posterior, se produce una interrupción y todos se quedan rascándose la cabeza
preguntándose qué hay de diferente entre los entornos más bajos de producción. Descubrí que el
tamaño pequeño y el alcance limitado de un microservicio lo convierten en la oportunidad perfecta
para introducir el concepto de "infraestructura inmutable" en una organización: una vez que se
despliega un servicio, las manos humanas nunca vuelven a tocar la infraestructura en la que se está
ejecutando.
Una infraestructura inmutable es una pieza crítica del uso exitoso de una arquitectura de microservicio,
porque debe garantizar en la producción que cada instancia de microservicio que inicie para un
microservicio particular sea idéntica a sus hermanos.
Figura 1.13. Desea que la implementación del microservicio y el servidor en el que se está ejecutando
sea un artefacto atómico que se implementa en conjunto entre entornos.
Nota
Para los ejemplos de código en este libro (excepto el capítulo 10), todo se ejecutará localmente en su
máquina de escritorio. Los dos primeros capítulos se pueden ejecutar de forma nativa directamente
desde la línea de comandos. A partir del capítulo 3, todo el código se compilará y ejecutará como
contenedores Docker.
1.10. Usando Spring Cloud en la construcción de sus microservicios
En esta sección, presento brevemente las tecnologías Spring Cloud que usará a medida que desarrolla
sus microservicios. Esta es una descripción general de alto nivel; cuando use cada tecnología en este
libro, le enseñaré los detalles de cada una según sea necesario.
Implementar todos estos patrones desde cero sería una gran cantidad de trabajo. Afortunadamente
para nosotros, el equipo de Spring ha integrado una gran cantidad de proyectos de código abierto
probados en batalla en un sub proyecto de Spring conocido colectivamente como Spring Cloud.
(http://projects.spring.io/spring-cloud/).
Spring Cloud envuelve el trabajo de compañías de código abierto como Pivotal, HashiCorp y Netflix
en la entrega de patrones. Spring Cloud simplifica la configuración y configuración de estos proyectos
en su aplicación Spring para que pueda enfocarse en escribir código, no quedar enterrado en los
detalles de la configuración de toda la infraestructura que puede ir con la construcción e
implementación de una aplicación de microservicio.
La Figura 1.14 asigna los patrones enumerados en la sección anterior a los proyectos de Spring Cloud
que los implementan.
Figura 1.14. Puede asignar las tecnologías que va a utilizar directamente a los patrones de
microservicio que hemos explorado hasta ahora en este capítulo.
1.10.1. Spring Boot
Spring Boot es la tecnología central utilizada en nuestra implementación de microservicios. Spring
Boot simplifica enormemente el desarrollo de microservicios al simplificar las tareas principales de
construir microservicios basados en REST. Spring Boot también simplifica enormemente la asignación
de verbos de estilo HTTP (GET, PUT, POST y DELETE) a URL y la serialización del protocolo JSON
hacia y desde objetos Java, así como la asignación de excepciones Java a códigos de error HTTP
estándar.
1.10.2. Spring Cloud Config
Spring Cloud Config maneja la administración de los datos de configuración de la aplicación a través
de un servicio centralizado para que los datos de configuración de su aplicación (particularmente los
datos de configuración específicos de su entorno) se separen limpiamente de su microservicio
implementado. Esto garantiza que, sin importar cuántas instancias de microservicio aparezca, siempre
tendrán la misma configuración. Spring Cloud Config tiene su propio repositorio de administración de
propiedades, pero también se integra con proyectos de código abierto como los siguientes:
Para las implementaciones de aprovisionamiento, haremos un cambio tecnológico. Los marcos Spring
están orientados al desarrollo de aplicaciones. Los marcos de Spring (incluida Spring Cloud) no tienen
herramientas para crear una canalización de "compilación e implementación". Para implementar una
tubería de "compilación e implementación", utilizará las siguientes herramientas: Travis CI
(https://travis-ci.org) para su herramienta de compilación y Docker (https://www.docker.com/) para
construir la imagen final del servidor que contiene su microservicio.
Para implementar sus contenedores Docker construidos, finalizamos el libro con un ejemplo de cómo
implementar toda la pila de aplicaciones desarrollada a lo largo de este libro en la nube de Amazon.
1.11. Spring Cloud, por ejemplo
En la última sección, analizamos todas las diferentes tecnologías de Spring Cloud que usará a medida
que desarrolla sus microservicios. Debido a que cada una de estas tecnologías son servicios
independientes, obviamente tomará más de un capítulo explicarlas en detalle. Sin embargo, al finalizar
este capítulo, quiero dejarle un pequeño ejemplo de código que demuestre nuevamente lo fácil que es
integrar estas tecnologías en su propio esfuerzo de desarrollo de microservicios.
A diferencia del primer ejemplo de código en el listado 1.1, no puede ejecutar este ejemplo de código
porque es necesario configurar y configurar una serie de servicios de soporte para su uso. Sin
embargo, no te preocupes; Los costos de configuración de estos servicios de Spring Cloud (servicio
de configuración, descubrimiento de servicios) son un costo único en términos de configuración del
servicio. Una vez que están configurados, sus microservicios individuales pueden usar estas
capacidades una y otra vez. No podríamos incluir toda esa bondad en un solo ejemplo de código al
comienzo del libro.
package com.thoughtmechanix.simpleservice;
//Removed other imports for conciseness
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
@SpringBootApplication
@RestController
@RequestMapping(value="hello")
@EnableCircuitBreaker
@EnableEurekaClient
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@HystrixCommand(threadPoolKey = "helloThreadPool")
public String helloRemoteServiceCall(String firstName,
String lastName){
ResponseEntity<String> restExchange =
restTemplate.exchange(
"http://logical-service-id/name/
[ca]{firstName}/{lastName}",
HttpMethod.GET,
null, String.class, firstName, lastName);
return restExchange.getBody();
}
@RequestMapping(value="/{firstName}/{lastName}",
method = RequestMethod.GET)
public String hello( @PathVariable("firstName") String firstName,
@PathVariable("lastName") String lastName) {
return helloRemoteServiceCall(firstName, lastName)
}
}
Este código tiene mucho contenido, así que veamos. Tenga en cuenta que este listado es solo un
ejemplo y no se encuentra en el capítulo 1 del código fuente del repositorio de GitHub. Lo he incluido
aquí para darle una idea de lo que vendrá más adelante en el libro.
@HystrixCommand(threadPoolKey = "helloThreadPool")
public String helloRemoteServiceCall(String firstName, String lastName)
La anotación @HystrixCommand está haciendo dos cosas. Primero, cada vez que se llama al método
helloRemoteServiceCall, no se invocará directamente. En cambio, el método se delegará a un grupo
de subprocesos administrado por Hystrix. Si la llamada tarda demasiado (el valor predeterminado es
un segundo), Hystrix interviene e interrumpe la llamada. Esta es la implementación del patrón de
interruptor de circuito. Lo segundo que hace esta anotación es crear un grupo de subprocesos llamado
helloThreadPool administrado por Hystrix. Todas las llamadas al método helloRemoteServiceCall solo
se realizarán en este grupo de subprocesos y se aislarán de cualquier otra llamada de servicio remoto
que se realice.
Lo último a tener en cuenta es lo que ocurre dentro del método helloRemoteServiceCall. La presencia
de @EnableEurekaClient le ha dicho a Spring Boot que va a utilizar una clase RestTemplate
modificada (no es así como funcionaría la Spring RestTemplate estándar) cuando realiza una llamada
de servicio REST. Esta clase RestTemplate le permitirá pasar un ID de servicio lógico para el servicio
que está intentando invocar:
Debajo de las cubiertas, la clase RestTemplate se comunicará con el servicio de Eureka y buscará la
ubicación física de una o más de las instancias del servicio de "nombre". Como consumidor del
servicio, su código nunca tiene que saber dónde se encuentra ese servicio.
Además, la clase RestTemplate está utilizando la biblioteca Ribbon de Netflix. Ribbon recuperará una
lista de todos los puntos finales físicos asociados con un servicio. Cada vez que el cliente llama al
servicio, realiza un "round-robin" de la llamada a las diferentes instancias de servicio en el cliente sin
tener que pasar por un equilibrador de carga centralizado. Al eliminar un equilibrador de carga
centralizado y trasladarlo al cliente, elimina otro punto de falla (el equilibrador de carga se cae) en la
infraestructura de su aplicación.
Espero que en este momento esté impresionado, porque ha agregado un número significativo de
capacidades a su microservicio con solo unas pocas anotaciones. Esa es la verdadera belleza detrás
de Spring Cloud. Usted, como desarrollador, puede aprovechar las capacidades de microservicio de
batalla de compañías líderes en la nube como Netflix y Consul. Estas capacidades, si se usan fuera
de Spring Cloud, pueden ser complejas y obtusas de configurar. Spring Cloud simplifica su uso a
literalmente nada más que unas pocas anotaciones y entradas de configuración simples de Spring
Cloud.
Quiero asegurarme de que este libro proporcione ejemplos con los que pueda relacionarse a medida
que realiza su trabajo diario. Con este fin, he estructurado los capítulos de este libro y los ejemplos de
código correspondientes en torno a las aventuras (desventuras) de una compañía ficticia llamada
ThoughtMechanix.
La empresa tiene aproximadamente 10 años. Si bien han experimentado un sólido crecimiento de los
ingresos, internamente están debatiendo si deberían volver a plataformas su producto principal desde
una aplicación monolítica basada en las instalaciones o mover su aplicación a la nube. El cambio de
plataforma relacionado con EagleEye puede ser un momento decisivo para una empresa.