Skip to content

Libro Learn Microservices: Guía de Actualización a Spring Boot 2.4

Guía de migración paso a paso de Spring Boot 2.3 a Spring Boot 2.4 para el proyecto de arquitectura de microservicios del libro Learn Microservices with Spring Boot

Este capítulo describe cómo actualizar el código fuente del libro Learn Microservices with Spring Boot a Spring Boot 2.4.0, Spring Cloud 2020.0 y Java 15.

¿Una actualización menor, o no?

Pasar de Spring Boot 2.3.4 a 2.4.0 significa que estamos tratando con una actualización menor (consulta la especificación de versionado semántico si no estás familiarizado con el término). ¿Por qué me preocuparía entonces por escribir un nuevo artículo y publicar el código fuente actualizado?

Acerca de esta guía: Este es un enfoque práctico para migrar un proyecto de Spring Boot desde la versión 2.3 a la versión 2.4 y Spring Cloud 2020.0. Utiliza la base de código del ejemplo práctico del libro Learn Microservices with Spring Boot, pero es aplicable a muchos otros proyectos también. Si quieres profundizar en cómo funciona Spring Boot y configurar una arquitectura de microservicios completa, consigue una copia ahora.

En el libro, invito a los lectores a crear los microservicios usando Spring Initializr en start.spring.io. Si seleccionas la última versión de Spring Boot disponible en el momento de escribir este artículo, 2.4.0, también obtendrás la última versión de Spring Cloud si añades cualquiera de sus starters. Puedes probar descargando el artefacto a través de este enlace y verificando el archivo pom.xml.

La última versión de Spring Cloud, 2020.0, es una actualización mayor, lo que significa que puede romper cosas. Y de hecho lo hace. También lo hace un “cambio menor” introducido en Spring Boot 2.4.0 para bases de datos embebidas.

Analicemos y manejemos estos cambios uno por uno mientras actualizamos el código fuente del último capítulo del libro. Todo el código está disponible en GitHub (mientras estás ahí, ¡dale una estrella!).

Migrar a Spring Boot 2.4.0 y Java 15

Primero, necesitamos descargar e instalar la versión 15 del JDK en caso de que aún no lo hayamos hecho.

Luego, actualizamos nuestros poms. El fragmento de código en el Listado 1 es un ejemplo de los cambios que necesitamos hacer, en este caso para el microservicio Multiplication. Revisa las líneas resaltadas.

  • Cambié la versión de la dependencia spring-boot-starter-parent a 2.4.0. A partir de esta versión, Spring Boot no incluirá el sufijo RELEASE. Ten en cuenta que, dado que no incluimos versiones de bibliotecas en ninguna de nuestras dependencias porque está gestionado por la gestión de dependencias de Spring Boot, obtendremos todas las actualizaciones de bibliotecas que Spring Boot decidió incluir en esta nueva versión. Consulta este enlace si quieres ver la lista completa.
  • La propiedad java.version es 15, lo que significa que compilaremos usando JDK 15. Asegúrate de configurar tu variable de entorno JAVA_HOME en consecuencia.
  • Para facilitar el versionado de los repositorios del libro, cambié la versión del microservicio de 0.0.1-SNAPSHOT a 2.4.0-SNAPSHOT. De esta manera, puedo simplemente seguir el mismo versionado que Spring Boot, que impulsará las actualizaciones futuras.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.0</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>microservices.book</groupId>
	<artifactId>multiplication</artifactId>
	<version>2.4.0-SNAPSHOT</version>
	<name>multiplication</name>
	<description>Multiplication Microservice - Learn Microservices with Spring Boot - Upgrade 2.4.0</description>

	<properties>
		<java.version>15</java.version>
		<spring-cloud.version>Hoxton.SR5</spring-cloud.version>
	</properties>

    <dependencies>
        <!-- ... permanecen iguales, las versiones se actualizan debido al parent -->
    </dependencies>
</project>

Listado 1. Actualizando Spring Boot y Java

Credenciales de la Base de Datos Embebida (H2)

Spring Boot 2.4 sí trae un cambio disruptivo para los proyectos del libro. El nombre de usuario predeterminado ya no es sa, como se cubre en el libro. ¿Qué significa esto? Si ya ejecutaste los proyectos usando la versión Spring Boot 2.3.x, las bases de datos usan sa como nombre de usuario y una contraseña vacía. Por lo tanto, si migras a Spring Boot 2.4.0 y mantienes los mismos archivos de base de datos, obtendrás este error durante la inicialización de los microservicios Multiplication y Gamification:

org.h2.jdbc.JdbcSQLInvalidAuthorizationSpecException: Wrong user name or password [28000-200]

Hay dos formas de solucionar esto:

  1. Eliminar todos los archivos de base de datos de la carpeta home del usuario. Son los archivos con extensión .db.
  2. Cambiar el nombre de usuario de la base de datos H2 de nuevo a sa usando las propiedades de Spring Boot. Ver Listado 2.
spring.application.name=multiplication
# Nos da acceso a la consola web de la base de datos H2
spring.h2.console.enabled=true
# Crea la base de datos en un archivo
spring.datasource.url=jdbc:h2:file:~/multiplication;DB_CLOSE_ON_EXIT=FALSE;AUTO_SERVER=TRUE;
spring.datasource.username=sa

Listado 2. Configurando el nombre de usuario de la base de datos a ‘sa’

Solo necesitas hacer esto en los proyectos Gamification y Multiplication.

Código Fuente: El código fuente del libro con todas las actualizaciones está disponible en GitHub: U.2.4.0. Mientras estás ahí, ¡por favor dale una estrella!

Construyendo las aplicaciones

Puedes actualizar todos los proyectos de Spring Boot a la última versión de Spring Boot: Multiplication, Gamification, Gateway y Logs. Sin embargo, esto es solo una parte de la actualización; los proyectos no funcionarán tal como están en este punto. Obtendrás algunos errores si intentas ejecutar las aplicaciones ahora:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name
 'configurationPropertiesBeans' defined in class path resource [org/springframework/
cloud/autoconfigure/ConfigurationPropertiesRebinderAutoConfiguration.class]

El lanzamiento Spring Cloud Hoxton no es compatible con Spring Boot 2.4 (ni con JDK 15), así que necesitamos continuar con la actualización e incluir Spring Cloud también.

De todos modos, queríamos actualizar Spring Cloud, así que veamos qué cambios necesitamos aplicar a nuestros proyectos.

Migrar a Spring Cloud 2020.0 desde Spring Cloud Hoxton

Nota: Esta publicación ha sido actualizada el 13 de febrero de 2021 para usar la versión de lanzamiento de Spring Cloud, en lugar del milestone.

Para incluir la versión 2020.0 (Ilford) de Spring Cloud, necesitamos actualizar todos nuestros poms como se muestra en el Listado 3.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <!-- ... -->
	<properties>
		<java.version>15</java.version>
		<spring-cloud.version>2020.0.0</spring-cloud.version>
	</properties>
</project>

Listado 3. Actualizando Spring Cloud

En principio, solo necesitamos cambiar la propiedad de versión de Spring Cloud en todos los archivos pom.xml para los proyectos que usan Spring Cloud, que son todos los microservicios - Multiplication, Gamification, Gateway y Logs.

Repasemos los cambios necesarios para hacer que nuestros proyectos funcionen después de actualizar a esta nueva versión de Spring Cloud.

Spring Cloud Bootstrap

Cuando actualizamos a Spring Cloud 2020.0, perdemos la funcionalidad de bootstrap porque ha sido eliminada por defecto. En nuestros proyectos, usamos la fase bootstrap con su archivo bootstrap.properties correspondiente para ajustar la configuración del Config Server de Consul. Esto significa que nuestros servicios fallarán al ejecutarlos en contenedores Docker porque no pueden encontrar la configuración del perfil docker que creamos para inicializar la dirección del host de RabbitMQ. Sin cargar este perfil, los microservicios intentarán alcanzar el servidor RabbitMQ localmente (desde localhost - el host del contenedor).

Para solucionar esto, tenemos varias opciones como se documenta en las notas de lanzamiento. En mi caso, elegí añadir una dependencia extra a todos los proyectos. Ver Listado 4 para la nueva dependencia que podemos añadir a todos los proyectos que usan Spring Cloud para habilitar Bootstrap nuevamente.

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>

Listado 4. Añadiendo el Spring Cloud Starter Bootstrap

Alternativamente, podríamos pasar una variable de entorno para habilitar bootstrap, pero esta nueva dependencia introducida con esta versión de Spring Cloud lo hace más transparente en mi opinión.

Spring Cloud Consul Config - nombre de aplicación

Como el usuario de Github mi2shiii descubrió, Spring Cloud Consul Config ya no usa el spring.application.name para buscar combinaciones de perfiles después de la actualización de Spring Cloud 2020.0. Intenta encontrar coincidencias como application,rabbitmq-production, y queremos que sea multiplication,rabbitmq-production. Consulta el issue de Github para ver los detalles en los logs.

La razón es que, en el libro, incluí la propiedad del nombre de aplicación en el archivo application.properties. Con el cambio introducido por Spring a la fase bootstrap, este valor no se carga antes de buscar perfiles. Solía haber una lógica para fusionar valores de ambas fuentes de propiedades que ya no está ahí.

La solución es simple. Solo mueve las propiedades spring.application.name de application.properties a bootstrap.properties. Esta es una buena práctica de todos modos, ya que hay procesos en la fase bootstrap que requieren o pueden usar el nombre de la aplicación.

Ver los cambios en el Pull Request.

Spring Cloud Sleuth - nombres de claves MDC

En el nuevo lanzamiento de Spring Cloud Sleuth, las claves MDC heredadas como X-B3-TraceId y X-B3-SpanId han sido renombradas. Ahora, estas claves están alineadas con las que Brave (el motor de rastreo subyacente) usa nativamente.

El microservicio logs hace referencia a estos traces para imprimir un mensaje formateado. Está incluido en el patrón de registro de Logback en el archivo logback-spring.xml:

<Pattern>
    [%-15marker] [%X{X-B3-TraceId:-},%X{X-B3-SpanId:-}] %highlight(%-5level) %msg%n
</Pattern>

Si mantenemos esos valores después de actualizar Spring Cloud, este servicio imprimirá cadenas vacías como identificadores de trace en los logs.

A primera vista, este problema parece muy fácil de solucionar. Modificamos los nombres de las claves MDC para que coincidan con los valores de Brave traceId y spanId:

<Pattern>
    [%-15marker] [%X{traceId:-},%X{spanId:-}] %highlight(%-5level) %msg%n
</Pattern>

Sin embargo, si seguimos ese enfoque, observaremos que los identificadores no coinciden entre los servicios, y ya no hay un traceId único para el proceso completo (créditos al lector mi2shiii por reportar el error). Esto probablemente es causado por un cambio en cómo funciona el AmqpAppender de Spring para fines de registro. En el libro, estaba aprovechando el hecho de que el appender de registro usaba el mismo identificador de trace que el resto del proceso. Sin embargo, eso es un poco frágil, como acabamos de ver.

Por lo tanto, en lugar de intentar hacer que los traces coincidan nuevamente, creé una solución alternativa. Ahora, incrustamos los identificadores de trace en los mensajes registrados desde los servicios (ver Listado 6), lo que hace que el logger centralizado sea más simple ya que solo necesita imprimir el mensaje.

<appender name="AMQP"
          class="org.springframework.amqp.rabbit.logback.AmqpAppender">
    <layout>
        <pattern>%d{HH:mm:ss.SSS} [trace id: %X{traceId:-}, span id: %X{spanId:-}] [%t] %logger{36} - %msg</pattern>
    </layout>
</appender>

Listado 6. Cambiando el patrón de registro, para que contenga los IDs de trace y span

Ver los cambios completos en Github’s Pull Request #4.

Actualizando las dependencias de imágenes Docker

También podemos actualizar la versión de Consul usada para el importador de configuración de Consul y el registro de servicios. Lo estableceremos en la versión 1.9. Ver Listado 6, donde la imagen base ahora está actualizada a consul:1.9. Para evitar confusiones, podemos etiquetar la imagen Docker que generamos con esta definición como consul-importer:1.9.

FROM consul:1.9
COPY ./consul-kv-docker.json /usr/src/consul/
WORKDIR /usr/src/consul
ENV CONSUL_HTTP_ADDR=consul:8500
ENTRYPOINT until consul kv import @consul-kv-docker.json; do echo "Waiting for Consul"; sleep 2; done

Listado 6. Actualizando la imagen base del Dockerfile del importador de consul (carpeta docker/consul).

El contenedor principal de Consul también puede usar esta imagen Docker. Ver Listado 7 para un fragmento del archivo docker-compose.xml actualizado.

version: "3"

services:
  # ...
  consul-importer:
    image: consul-importer:1.9
    # ...
  consul-dev:
    image: consul:1.9
    # ...
  rabbitmq-dev:
    image: rabbitmq:3-management
    # ...

Listado 7. Archivo Docker Compose con versiones actualizadas

Ahora, el archivo Docker Compose extrae la imagen consul-importer:1.9 (construida y etiquetada por nosotros con el Dockerfile mostrado en el Listado 5), y la imagen consul:1.9 disponible en el registro público de Docker.

Ten en cuenta que se extraerá automáticamente una imagen más nueva de RabbitMQ ya que usamos una etiqueta que los mantenedores de la imagen Docker mueven entre versiones (siempre que la versión mayor sea 3). La etiqueta 3-management se mueve con el tiempo para apuntar a la última versión 3.x.x.

Hice que todas las nuevas versiones de microservicios estuvieran disponibles desde el registro público. Usa el archivo docker-compose-public.yml para extraer las nuevas imágenes y ejecutar el sistema completo:

docker $ docker-compose -f docker-compose-public.yml up

Código Fuente: El código fuente del libro con todas las actualizaciones está disponible en GitHub: U.2.4.0. Mientras estás ahí, ¡por favor dale una estrella!

Master Microservices with Spring Boot

A hands-on guide to building production-ready microservices

Get the Book

Get More Architecture Insights

Join hundreds of software architects and engineers getting practical insights delivered to their inbox.

Volver al Blog