Esta publicación es uno de los cuatro tutoriales que te ayudan a poner en práctica los conceptos de Microservicios de marzo de 2023: Comience a entregar microservicios :
Todas las aplicaciones requieren configuración, pero las consideraciones al configurar un microservicio pueden ser diferentes a las de una aplicación monolítica . Podemos consultar el Factor 3 ( Almacenar configuración en el entorno ) de la aplicación de doce factores para obtener orientación aplicable a ambos tipos de aplicaciones, aunque esta orientación puede adaptarse a las aplicaciones de microservicios. En particular, podemos adaptar la forma en que definimos la configuración del servicio, proporcionamos la configuración a un servicio y hacemos que un servicio esté disponible como valor de configuración para otros servicios que puedan depender de él.
Para obtener una comprensión conceptual de cómo adaptar Factor 3 para microservicios, específicamente las mejores prácticas para archivos de configuración, bases de datos y descubrimiento de servicios, lea Mejores prácticas para configurar aplicaciones de microservicios en nuestro blog. Esta publicación es una excelente manera de poner ese conocimiento en práctica.
Nota: Nuestra intención en este tutorial es ilustrar algunos conceptos fundamentales, no mostrar la forma correcta de implementar microservicios en producción. Si bien utiliza una arquitectura de “microservicios” real, hay algunas advertencias importantes:
Este tutorial ilustra cómo se aplican los conceptos del Factor 3 a las aplicaciones de microservicios. En cuatro desafíos, explorarás algunos patrones comunes de configuración de microservicios e implementarás y configurarás un servicio utilizando esos patrones:
En los Desafío 1 y 2, explorarás el primer patrón, que se refiere a dónde se ubica la configuración de una aplicación de microservicios. Hay tres ubicaciones típicas:
El tutorial utiliza cuatro tecnologías:
Mire este vídeo para obtener una descripción general del tutorial. Los pasos no coinciden exactamente con esta publicación, pero ayuda a comprender los conceptos.
Para completar el tutorial en su propio entorno, necesitará:
bash
(pero se proporcionan y explican todos los códigos y comandos, por lo que aún puede tener éxito con un conocimiento limitado)Node.js 19.x o posterior
asdf
para obtener exactamente la misma versión de Node.js utilizada en los contenedores.curl
(ya instalado en la mayoría de los sistemas)En su directorio de inicio, cree el directorio microservices-march y clone en él los repositorios de GitHub para este tutorial. (También puede utilizar un nombre de directorio diferente y adaptar las instrucciones en consecuencia).
Nota: A lo largo del tutorial se omite el aviso en la línea de comandos de Linux para que sea más fácil copiar y pegar los comandos en su terminal. La tilde ( ~
) representa su directorio de inicio.
mkdir ~/microservices-marchcd ~/microservices-march
Clon de git https://github.com/microservices-march/platform.git --branch mm23-twelve-factor-start
Clon de git https://github.com/microservices-march/messenger.git --branch mm23-twelve-factor-start
Cambie al repositorio de la plataforma e inicie Docker Compose:
cd platformdocker componer -d --build
Esto inicia RabbitMQ y Consul, que se utilizarán en desafíos posteriores.
-d
le indica a Docker Compose que se separe de los contenedores cuando se hayan iniciado (de lo contrario, los contenedores permanecerán conectados a su terminal).--build
le indica a Docker Compose que reconstruya todas las imágenes al iniciarse. Esto garantiza que las imágenes que está ejecutando se mantengan actualizadas ante cualquier posible cambio en los archivos.Cambie al repositorio de mensajería e inicie Docker Compose:
cd ../messengerdocker componer -d --build
Esto inicia la base de datos PostgreSQL para el servicio de mensajería , al que nos referiremos como messenger-database durante el resto del tutorial.
En este desafío, configurarás la configuración en la primera de las tres ubicaciones que veremos en el tutorial: el nivel de la aplicação . ( El desafío 2 ilustra la segunda y tercera ubicación, los scripts de implementación y las fuentes externas).
La aplicación de doce factores excluye específicamente la configuración a nivel de aplicação, porque dicha configuración no necesita cambiar entre diferentes entornos de implementación (a los que la aplicación de doce factores llama "implementaciones" ). No obstante, cubrimos los tres tipos para completar: la forma de abordar cada categoría a medida que desarrolla, construye e implementa un servicio es diferente.
El servicio de mensajería está escrito en Node.js, con el punto de entrada en app/index.mjs en el repositorio de mensajería . Esta línea del archivo:
aplicación.use(express.json());
es un ejemplo de configuración a nivel de aplicação. Configura el marco Express para deserializar los cuerpos de solicitud que son de tipo aplicação/json
en objetos JavaScript.
Esta lógica está estrechamente ligada al código de su aplicação y no es lo que la aplicación de doce factores considera "configuración". Pero en el software todo depende de tu situación, ¿no es así?
En las siguientes dos secciones, modificará esta línea para implementar dos ejemplos de configuración a nivel de aplicação.
En este ejemplo, establece el tamaño máximo del cuerpo de una solicitud aceptada por el servicio de mensajería . Este límite de tamaño se establece mediante el argumento limit
de la función express.json , como se analiza en la documentación de la API de Express . Aquí agrega el argumento de límite
a la configuración del middleware JSON del marco Express discutido anteriormente .
En su editor de texto preferido, abra app/index.mjs y reemplace:
aplicación.use(express.json())
con:
aplicación.use(express.json({ límite: "20b" }));
En la terminal de la aplicación (la que usaste en Configuración ), cambia al directorio de la aplicación e inicia el servicio de mensajería :
cd app npm install node index.mjs messenger_service escuchando en el puerto 4000
Inicie una segunda sesión de terminal independiente (cuyas instrucciones posteriores llaman a la terminal del cliente ) y envíe una solicitud POST
al servicio de mensajería . El mensaje de error indica que la solicitud se procesó correctamente, porque el cuerpo de la solicitud estaba por debajo del límite de 20 bytes establecido en el Paso 1, pero que el contenido de la carga útil JSON es incorrecto:
curl -d '{ "texto": "hola" }' -H "Tipo de contenido: aplicação/json" -X POST http://localhost:4000/conversaciones ... { "error": "La conversación debe tener 2 usuarios únicos"
Envía un cuerpo de mensaje un poco más largo (nuevamente en la terminal del cliente). Hay mucho más resultado que en el paso 3, incluido un mensaje de error que indica que esta vez el cuerpo de la solicitud supera los 20 bytes:
curl -d '{ "text": "hola, mundo" }' -H "Content-Type: aplicação/json" -X POST http://localhost:4000/conversations ... \”PayloadTooLargeError: la entidad solicitada es demasiado grande”
Este ejemplo utiliza convict
, una biblioteca que le permite definir un “esquema” de configuración completo en un solo archivo. También ilustra dos pautas del Factor 3 de la aplicación de doce factores:
JSON_BODY_LIMIT
) en lugar de estar codificado en el código de la aplicación.El ejemplo también configura algunas "plomerías" que aprovecharás en el Desafío 2 : el script de implementación de mensajero que crearás en ese desafío establece la variable de entorno JSON_BODY_LIMIT
que insertas en el código de la aplicación aquí, como una ilustración de la configuración especificada en un script de implementación.
Abra el archivo de configuración de convicto
, app/config/config.mjs , y agregue lo siguiente como una nueva clave después de la clave amqpport
:
jsonBodyLimit: { doc: `El tamaño máximo (con unidad incluida) que analizará el middleware JSON. El análisis de unidades lo realiza la biblioteca https://www.npmjs.com/package/bytes.
Ejemplo: "100kb"`,
formato: Cadena,
predeterminado: nulo,
entorno: "LÍMITE_DE_CUERPO_JSON",
La biblioteca convict
se encarga de analizar la variable de entorno JSON_BODY_LIMIT
cuando la usa para establecer el tamaño máximo del cuerpo en la línea de comando en el Paso 3 a continuación:
cadena
)jsonBodyLimit
En app/index.mjs reemplace:
aplicación.use(express.json({ límite: "20b" }));
con
aplicación.use(express.json({ límite: config.get("jsonBodyLimit") }));
En la terminal de la aplicación (donde inició el servicio de mensajería en el Paso 2 del Ejemplo 1 ), presione Ctrl+c
para detener el servicio. Luego, inícielo nuevamente, utilizando la variable de entorno JSON_BODY_LIMIT
para establecer el tamaño máximo del cuerpo en 27 bytes:
^cJSON_BODY_LIMIT=27b índice de nodo.mjs
Este es un ejemplo de cómo modificar el método de configuración cuando hacerlo tiene sentido para su caso de uso: ha pasado de codificar un valor (en este caso, un límite de tamaño) en el código de la aplicación a configurarlo con una variable de entorno, como lo recomienda la aplicación de doce factores.
Como se mencionó anteriormente, en el Desafío 2 , el uso de la variable de entorno JSON_BODY_LIMIT
se convertirá en un ejemplo de la segunda ubicación para la configuración, cuando utilice el script de implementación del servicio de mensajería para configurar la variable de entorno en lugar de configurarla en la línea de comando.
En la terminal del cliente, repita el comando curl
del Paso 4 del Ejemplo 1 (con el cuerpo de solicitud más grande). Como ahora ha aumentado el límite de tamaño a 27 bytes, el cuerpo de la solicitud ya no excede el límite y recibe el mensaje de error que indica que se procesó la solicitud, pero que el contenido de la carga útil JSON es incorrecto:
curl -d '{ "texto": "hola, mundo" }' -H "Tipo de contenido: aplicação/json" -X POST http://localhost:4000/conversations { "error": "La conversación debe tener 2 usuarios únicos"
Puede cerrar la terminal del cliente si lo desea. Emitirás todos los comandos en el resto del tutorial en la terminal de la aplicación.
En la terminal de la aplicación, presione Ctrl+c
para detener el servicio de mensajería (detuvo y reinició el servicio en esta terminal en el Paso 3 anterior).
^c
Detener la base de datos del mensajero . Puede ignorar de forma segura el mensaje de error que se muestra, ya que la red aún está en uso por los elementos de infraestructura definidos en el repositorio de la plataforma . Ejecute este comando en la raíz del repositorio del mensajero .
docker compose down ...no se pudo eliminar la red mm_2023....
A primera vista, esto se podría interpretar como “no registrar la configuración en el control de origen”. En este desafío, implementa un patrón común para entornos de microservicios que puede parecer romper esta regla, pero en realidad la respeta y al mismo tiempo proporciona valiosas mejoras de proceso que son fundamentales para los entornos de microservicios.
En este desafío, creará scripts de implementación para imitar la funcionalidad de la infraestructura como código y los manifiestos de implementación que proporcionan configuración a un microservicio, modificará los scripts para usar fuentes externas de configuración, establecerá un secreto y luego ejecutará los scripts para implementar los servicios y su infraestructura.
Crea los scripts de implementación en un directorio de infraestructura recién creado en el repositorio de Messenger . Un directorio llamado infraestructura (o alguna variación de ese nombre) es un patrón común en las arquitecturas de microservicios modernas, que se utiliza para almacenar cosas como:
Los beneficios de este patrón incluyen:
Como se mencionó anteriormente, nuestra intención con este tutorial no es mostrar cómo configurar un sistema real, y los scripts que implementa en este desafío no se parecen a un sistema de producción real. Más bien, ilustran algunos conceptos centrales y problemas resueltos mediante la configuración específica de la herramienta cuando se trata de la implementación de infraestructura relacionada con microservicios, al mismo tiempo que abstraen los scripts a la mínima cantidad de herramientas específicas posible.
En la terminal de la aplicación, cree un directorio de infraestructura en la raíz del repositorio de mensajería y cree archivos para contener los scripts de implementación para el servicio de mensajería y la base de datos de mensajería . Dependiendo de su entorno, es posible que necesite anteponer sudo
a los comandos chmod
:
mkdir infraestructuracd infraestructura
touch messenger-deploy.sh
chmod +x messenger-deploy.sh
touch messenger-db-deploy.sh
chmod +x messenger-db-deploy.sh
En su editor de texto preferido, abra messenger-deploy.sh y agregue lo siguiente para crear un script de implementación inicial para el servicio de mensajería :
#!/bin/bashset -e LÍMITE_DEL_CUERPO_JSON=20b docker run \ --rm \ -e LÍMITE_DEL_CUERPO_JSON="${JSON_BODY_LIMIT} " \ mensajero
Este guión no está completo en este momento, pero ilustra un par de conceptos:
-e
en el comando docker
run
para inyectar variables de entorno en el contenedor en tiempo de ejecución.Puede parecer redundante establecer el valor de las variables de entorno de esta manera, pero significa que, sin importar cuán complejo se vuelva este script de implementación, puede echar un vistazo rápido a la parte superior del script y comprender cómo se proporcionan los datos de configuración a la implementación.
Además, aunque un script de implementación real puede no invocar explícitamente el comando docker
run
, este script de muestra está destinado a transmitir los problemas centrales que se resuelven con algo como un manifiesto de Kubernetes. Al utilizar un sistema de orquestación de contenedores como Kubernetes, una implementación inicia un contenedor y la configuración de la aplicação derivada de los archivos de configuración de Kubernetes se pone a disposición de ese contenedor. Por lo tanto, podemos considerar este archivo de implementación de muestra como una versión mínima de un script de implementación que cumple la misma función que los archivos de implementación específicos del marco, como los manifiestos de Kubernetes.
En un entorno de desarrollo real, puedes registrar este archivo en el control de origen y someterlo a una revisión de código. Esto le da al resto de su equipo la oportunidad de comentar sobre su configuración y, por lo tanto, ayuda a evitar incidentes en los que valores mal configurados provocan un comportamiento inesperado. Por ejemplo, en esta captura de pantalla un miembro del equipo señala correctamente que un límite de 20 bytes para los cuerpos de solicitud JSON entrantes (establecido con JSON_BODY_LIMIT
) es demasiado bajo.
En esta parte del desafío, configura la tercera ubicación para la configuración de un microservicio: una fuente externa que se consulta en el momento de la implementación. Registrar valores dinámicamente y obtenerlos de una fuente externa en el momento de la implementación es una práctica mucho mejor que codificar valores de forma rígida, que deben actualizarse constantemente y pueden provocar fallas. Para obtener más información, consulte Mejores prácticas para configurar aplicaciones de microservicios en nuestro blog.
En este punto, dos componentes de infraestructura se ejecutan en segundo plano para proporcionar los servicios auxiliares requeridos por el servicio de mensajería :
El esquema de convicto
para el servicio de mensajería en app/config/config.mjs define las variables de entorno requeridas correspondientes a estas piezas de configuración externa. En esta sección, configura estos dos componentes para proporcionar configuración estableciendo los valores de las variables en una ubicación de acceso común para que el servicio de mensajería pueda consultarlos cuando se implemente.
La información de conexión requerida para RabbitMQ y la base de datos de mensajería se registra en el almacén de clave/valor (KV) de Consul , que es una ubicación común a la que pueden acceder todos los servicios a medida que se implementan. El almacén Consul KV no es un lugar estándar para almacenar este tipo de datos, pero este tutorial lo utiliza para simplificar.
Reemplace el contenido de infraestructura/messenger-deploy.sh (creado en el Paso 2 de la sección anterior ) con lo siguiente:
#!/bin/bashset -e # Esta configuración requiere una nueva confirmación para cambiar NODE_ENV=production PORT=4000 JSON_BODY_LIMIT=100kb # Configuración de la base de datos de Postgres extrayendo información del # sistema POSTGRES_USER=$(curl -X GET http://localhost:8500/v1/kv/messenger-db-application-user?raw=true) PGPORT=$(curl -X GET http://localhost:8500/v1/kv/messenger-db-port?raw=true) PGHOST=$(curl -X GET http://localhost:8500/v1/kv/messenger-db-host?raw=true) # Configuración de RabbitMQ extrayendo información del sistema AMQPHOST=$(curl -X GET http://localhost:8500/v1/kv/amqp-host?raw=true) AMQPPORT=$(curl -X GET http://localhost:8500/v1/kv/amqp-port?raw=true) docker run \ --rm \ -e NODE_ENV="${NODE_ENV} " \ -e PUERTO="${PORT} " \ -e LÍMITE_DEL_CUERPO_JSON="${JSON_BODY_LIMIT} " \ -e PGUSER="${POSTGRES_USER} " \ -e PGPORT="${PGPORT} " \ -e PGHOST="${PGHOST} " \ -e AMQPPORT="${AMQPPORT} " \ -e AMQPHOST="${AMQPHOST} " \ mensajero
Este script ejemplifica dos tipos de configuración:
NODE_ENV
) y el puerto ( PORT
), y cambia JSON_BODY_LIMIT
a 100 KB, un valor más realista que 20 bytes.POSTGRES_USER
, PGPORT
, PGHOST
, AMQPHOST
y AMQPPORT
del almacén Consul KV. Los valores de las variables de entorno en el almacén de Consul KV se establecen en los dos pasos siguientes.Abra messenger-db-deploy.sh y agregue lo siguiente para crear un script de implementación inicial para messenger-database :
#!/bin/bashset -e PUERTO=5432 POSTGRES_USER=postgres docker run \ -d \ --rm \ --name messenger-db \ -v db-data:/var/lib/postgresql/data/pgdata \ -e POSTGRES_USER="${POSTGRES_USER} " \ -e CONTRASEÑA_POSTGRES="${POSTGRES_PASSWORD} " \ -e PGPORT="${PORT} " \ -e PGDATA=/var/lib/postgresql/data/pgdata \ --network mm_2023 \ postgres:15.1 # Registrar detalles sobre la base de datos con Consul curl -X PUT http://localhost:8500/v1/kv/messenger-db-port \ -H "Content-Type: aplicação/json" \ -d "${PORT} " curl -X PUT http://localhost:8500/v1/kv/messenger-db-host \ -H "Content-Type: aplicação/json" \ -d 'messenger-db' # Esto coincide con el indicador "--name" anterior # (el nombre del host) curl -X PUT http://localhost:8500/v1/kv/messenger-db-application-user \ -H "Content-Type: aplicação/json" \ -d "${POSTGRES_USER} "
Además de definir la configuración que puede consultar el servicio de mensajería en el momento de la implementación, el script ilustra los mismos dos conceptos que el script inicial para el servicio de mensajería de Crear scripts de implementación inicial ):
-e
para inyectar variables de entorno en el contenedor en tiempo de ejecución. También establece el nombre del contenedor en ejecución en messenger-db , que se convierte en el nombre de host de la base de datos en la red Docker que creó cuando lanzó el servicio de plataforma en el Paso 2 de Configuración .En una implementación real, generalmente es el equipo de la Plataforma (o similar) el que maneja la implementación y el mantenimiento de un servicio como RabbitMQ en el repositorio de la plataforma , tal como lo hace para la base de datos de Messenger en el repositorio de Messenger . Luego, el equipo de la Plataforma se asegura de que los servicios que dependen de ella puedan descubrir la ubicación de esa infraestructura. Para los fines de este tutorial, configure usted mismo los valores de RabbitMQ:
curl -X PUT --silent --output /dev/null --show-error --fail \ -H "Tipo de contenido: aplicação/json" \
-d "rabbitmq" \
<a href="http://localhost:8500/v1/kv/amqp-host">http://localhost:8500/v1/kv/amqp-host</a>
curl -X PUT --silent --output /dev/null --show-error --fail \
-H "Tipo de contenido: aplicação/json" \
-d "5672" \
<a href="http://localhost:8500/v1/kv/amqp-port">http://localhost:8500/v1/kv/puerto-amqp</a>
(Quizás te preguntes por qué se utiliza amqp
para definir variables de RabbitMQ: es porque AMQP es el protocolo utilizado por RabbitMQ).
Solo falta un dato (crítico) en los scripts de implementación del servicio de mensajería : ¡la contraseña para la base de datos del mensajero !
Nota: La gestión de secretos no es el foco de este tutorial, por lo que para simplificar el secreto se define en los archivos de implementación. Nunca hagas esto en un entorno real (desarrollo, prueba o producción), ya que crea un enorme riesgo de seguridad .
Para aprender sobre la gestión adecuada de secretos, consulte la Unidad 2, Gestión de secretos de microservicios 101 de Microservicios de marzo de 2023. (Spoiler: una herramienta de gestión de secretos es el único método verdaderamente seguro para almacenar secretos).
Reemplace el contenido de infraestructura/messenger-db-deploy.sh con lo siguiente para almacenar el secreto de contraseña para la base de datos de messenger en el almacén Consul KV:
#!/bin/bashset -e PORT=5432 POSTGRES_USER=postgres # NOTA: Nunca hagas esto en una implementación del mundo real. Almacene las contraseñas # únicamente en un almacén de secretos cifrados.
POSTGRES_PASSWORD=postgres docker run \ --rm \ --name messenger-db-primary \ -d \ -v db-data:/var/lib/postgresql/data/pgdata \ -e POSTGRES_USER="${POSTGRES_USER} " \ -e CONTRASEÑA_POSTGRES="${POSTGRES_PASSWORD} " \ -e PGPORT="${PORT} " -e PGDATA=/var/lib/postgresql/data/pgdata --network mm_2023 postgres:15.1 echo "Registrar clave messenger-db-port\n" curl -X PUT --silent --output /dev/null --show-error --fail http://localhost:8500/v1/kv/messenger-db-port -H "Tipo de contenido: aplicação/json" -d${PORT} " echo "Registrar clave messenger-db-host\n" curl -X PUT --silent --output /dev/null --show-error --fail http://localhost:8500/v1/kv/messenger-db-host \ -H "Content-Type: aplicação/json" \ -d 'messenger-db-primary' # Esto coincide con el indicador "--name" anterior # que para nuestra configuración significa el nombre de host echo "Registrar clave messenger-db-application-user\n" curl -X PUT --silent --output /dev/null --show-error --fail http://localhost:8500/v1/kv/messenger-db-application-user \ -H "Content-Type: aplicação/json" \ -d "${POSTGRES_USER} " echo "Registrar clave messenger-db-password-nunca-haga-esto\n" curl -X PUT --silent --output /dev/null --show-error --fail http://localhost:8500/v1/kv/messenger-db-password-nunca-haga-esto \ -H "Tipo-de-contenido: aplicação/json" \ -d "${POSTGRES_PASSWORD} " printf "\nSe terminó de registrar los detalles de postgres con Consul\n"
Reemplace el contenido de infraestructura/messenger-deploy.sh con lo siguiente para obtener el secreto de contraseña de la base de datos de messenger del almacén Consul KV:
#!/bin/bashset -e # Esta configuración requiere una nueva confirmación para cambiar NODE_ENV=production PORT=4000 JSON_BODY_LIMIT=100kb # Configuración de la base de datos de Postgres extrayendo información del # sistema POSTGRES_USER=$(curl -X GET http://localhost:8500/v1/kv/messenger-db-application-user?raw=true) PGPORT=$(curl -X GET http://localhost:8500/v1/kv/messenger-db-port?raw=true) PGHOST=$(curl -X GET http://localhost:8500/v1/kv/messenger-db-host?raw=true) # NOTA: Nunca hagas esto en una implementación del mundo real. Almacene las contraseñas # únicamente en un almacén de secretos cifrados.
PGPASSWORD=$(curl -X GET http://localhost:8500/v1/kv/messenger-db-password-never-do-this?raw=true) # Configuración de RabbitMQ extrayendo del sistema AMQPHOST=$(curl -X GET http://localhost:8500/v1/kv/amqp-host?raw=true) AMQPPORT=$(curl -X GET http://localhost:8500/v1/kv/amqp-port?raw=true) docker run \ --rm \ -d \ -e NODE_ENV="${NODE_ENV} " \ -e PUERTO="${PORT} " \ -e LÍMITE_DEL_CUERPO_JSON="${JSON_BODY_LIMIT} " \ -e PGUSER="${POSTGRES_USER} " \ -e PGPORT="${PGPORT} " \ -e PGHOST="${PGHOST} " \ -e PGPASSWORD="${PGPASSWORD} " \ -e AMQPPORT="${AMQPPORT} " \ -e AMQPHOST="${AMQPHOST} " \ --network mm_2023 \ mensajero
Cambie al directorio de la aplicación en el repositorio de Messenger y cree la imagen de Docker para el servicio de Messenger :
cd ../appdocker build -t messenger .
Verifique que solo se estén ejecutando los contenedores que pertenecen al servicio de la plataforma :
docker ps --format '{{.Names}}' consul-server consul-client rabbitmq
Cambie a la raíz del repositorio de mensajería e implemente la base de datos de mensajería y el servicio de mensajería :
cd .../infraestructura/messenger-db-deploy.sh
./infraestructura/messenger-deploy.sh
El script messenger-db-deploy.sh inicia la base de datos de messenger y registra la información apropiada con el sistema (que en este caso es el almacén Consul KV).
Luego, el script messenger-deploy.sh inicia la aplicação y extrae la configuración registrada por messenger-db-deploy.sh del sistema (nuevamente, el almacén Consul KV).
Pista: Si un contenedor no puede iniciarse, elimine el segundo parámetro del comando docker
run
(la línea -d
\
) en el script de implementación y ejecute el script nuevamente. Luego, el contenedor se inicia en primer plano, lo que significa que sus registros aparecen en la terminal y podrían identificar el problema. Cuando resuelva el problema, restaure la línea -d
\
para que el contenedor real se ejecute en segundo plano.
Envíe una solicitud de verificación de estado simple a la aplicação para verificar que la implementación se realizó correctamente:
curl localhost:4000/salud curl: (7) No se pudo conectar al puerto localhost 4000 después de 11 ms: Conexión rechazada
¡Ups, fallo! Resulta que todavía falta una pieza crítica de configuración y el servicio de mensajería no está expuesto al sistema más amplio. Funciona correctamente dentro de la red mm_2023 , pero esa red solo es accesible desde Docker.
Detenga el contenedor en ejecución para prepararlo para crear una nueva imagen en el próximo desafío:
docker rm $(docker stop $(docker ps -a -q --filter ancestor=messenger --format="{{.ID}}"))
En un entorno de producción, generalmente no se exponen los servicios directamente. En lugar de ello, sigue un patrón común de microservicios y coloca un servicio de proxy inverso delante de tu servicio principal.
En este desafío, usted expone el servicio de mensajería al mundo exterior configurando el descubrimiento de servicios: el registro de nueva información de servicio y la actualización dinámica de esa información a medida que acceden otros servicios. Para ello, utiliza estas tecnologías:
Para obtener más información sobre el descubrimiento de servicios, consulte Cómo hacer que un servicio esté disponible como configuración en Mejores prácticas para configurar aplicaciones de microservicios en nuestro blog.
El archivo app/consul/index.mjs en el repositorio de mensajería contiene todo el código necesario para registrar el servicio de mensajería con Consul al inicio y cancelar su registro al apagar correctamente. Expone una función, register
, que registra cualquier servicio recién implementado con el registro de servicios de Consul.
En su editor de texto preferido, abra app/index.mjs y agregue el siguiente fragmento después de las otras declaraciones de importación
, para importar la función de registro
desde app/consul/index.mjs :
importar { registrarse como registerConsul } desde "./consul/index.mjs";
Luego modifique la sección SERVER
START
al final del script como se muestra, para llamar a registerConsul()
después de que la aplicação se haya iniciado:
/* ================= INICIO DEL SERVIDOR ================== */ app.listen(port, async () => { console.log(`messenger_service escuchando en el puerto${port} `); registerConsul(); }); exportar aplicación predeterminada;
Abra el esquema de convicto
en app/config/config.mjs y agregue los siguientes valores de configuración después de la clave jsonBodyLimit
que agregó en el Paso 1 del Ejemplo 2 .
consulServiceName: { doc: "El nombre con el que se registra el servicio en Consul. Si no se especifica, el servicio no está registrado.
Formato: "*",
Predeterminado: nulo,
Entorno: "NOMBRE_SERVICIO_CONSUL",
},
consulHost: {
doc: "El host donde se ejecuta el cliente Consul", formato: Cadena,
predeterminado: "consul-client",
env: "CONSUL_HOST",
},
consulPort: {
doc: "El puerto del cliente Consul",
formato: "puerto",
predeterminado: 8500,
env: "CONSUL_PORT",
Esto configura el nombre bajo el cual se registra un nuevo servicio y define el nombre de host y el puerto para el cliente Consul. En el siguiente paso, modifique el script de implementación del servicio de mensajería para incluir esta nueva conexión de Consul y la información de registro del servicio.
Abra Infrastructure/messenger-deploy.sh y reemplace su contenido con lo siguiente para incluir en la configuración del servicio de mensajería la información de conexión y registro del servicio de Consul que configuró en el paso anterior:
#!/bin/bashset -e # Esta configuración requiere una nueva confirmación para cambiar NODE_ENV=production PORT=4000 JSON_BODY_LIMIT=100kb CONSUL_SERVICE_NAME="messenger" # El host y el puerto de Consul se incluyen en cada host ya que # no podemos consultar a Consul hasta que los conozcamos CONSUL_HOST="${CONSUL_HOST} " CONSUL_PORT="${CONSUL_PORT} " # Configuración de la base de datos de Postgres extrayendo información del # sistema POSTGRES_USER=$(curl -X GET "http://localhost:8500/v1/kv/messenger-db-application-user?raw=true") PGPORT=$(curl -X GET "http://localhost:8500/v1/kv/messenger-db-port?raw=true") PGHOST=$(curl -X GET "http://localhost:8500/v1/kv/messenger-db-host?raw=true") # NOTA: Nunca hagas esto en una implementación del mundo real. Almacene las contraseñas # únicamente en un almacén de secretos cifrados.
PGPASSWORD=$(curl -X GET "http://localhost:8500/v1/kv/messenger-db-password-never-do-this?raw=true") # Configuración de RabbitMQ extrayendo del sistema AMQPHOST=$(curl -X GET "http://localhost:8500/v1/kv/amqp-host?raw=true") AMQPPORT=$(curl -X GET "http://localhost:8500/v1/kv/amqp-port?raw=true") docker run \ --rm \ -d \ -e NODE_ENV="${NODE_ENV} " \ -e PUERTO="${PORT} " \ -e LÍMITE_DEL_CUERPO_JSON="${JSON_BODY_LIMIT} " \ -e PGUSER="${POSTGRES_USER} " \ -e PGPORT="${PGPORT} " \ -e PGHOST="${PGHOST} " \ -e PGPASSWORD="${PGPASSWORD} " \ -e AMQPPORT="${AMQPPORT} " \ -e AMQPHOST="${AMQPHOST} " \ -e CONSUL_HOST="${CONSUL_HOST} " \ -e CONSUL_PORT="${CONSUL_PORT} " \ -e NOMBRE_SERVICIO_CÓNSUL="${CONSUL_SERVICE_NAME} " \ --network mm_2023 \ mensajero
Los principales aspectos a tener en cuenta son:
CONSUL_SERVICE_NAME
le dice a la instancia del servicio de mensajería qué nombre usar cuando se registra en Consul.CONSUL_HOST
y CONSUL_PORT
son para el cliente Consul que se ejecuta en la ubicación donde se ejecuta el script de implementación.Nota: En una implementación del mundo real, este es un ejemplo de configuración que debe acordarse entre los equipos: el equipo responsable de Consul debe proporcionar las variables de entorno CONSUL_HOST
y CONSUL_PORT
en todos los entornos, ya que un servicio no puede consultar Consul sin esta información de conexión.
En la terminal de la aplicación, cambie al directorio de la aplicación , detenga cualquier instancia en ejecución del servicio de mensajería y reconstruya la imagen de Docker para integrar el nuevo código de registro del servicio:
cd appdocker rm $(docker stop $(docker ps -a -q --filter ancestor=messenger --format="{{.ID}}"))
docker build -t messenger .
Navegue a http://localhost:8500 en un navegador para ver la interfaz de usuario de Consul en acción (aunque todavía no sucede nada interesante).
En la raíz del repositorio de mensajería , ejecute el script de implementación para iniciar una instancia del servicio de mensajería :
CONSUL_HOST=cliente-consul CONSUL_PORT=8500 ./infraestructura/messenger-deploy.sh
En la interfaz de usuario de Consul en el navegador, haga clic en Servicios en la barra de encabezado para verificar que se esté ejecutando un solo servicio de mensajería .
Ejecute el script de implementación unas cuantas veces más para iniciar más instancias del servicio de mensajería . Verifique en la interfaz de usuario de Consul que se estén ejecutando.
CONSUL_HOST=cliente-consul CONSUL_PORT=8500 ./infraestructura/messenger-deploy.sh
El siguiente paso es agregar NGINX Open Source como proxy inverso y balanceador de carga para enrutar el tráfico entrante a todas las instancias de mensajería en ejecución.
En la terminal de la aplicación, cambie el directorio a la raíz del repositorio de Messenger y cree un directorio llamado load-balancer y tres archivos:
mkdir balanceador-de-cargarcd balanceador-de-carga
toca nginx.ctmpl
toca consul-template-config.hcl
toca Dockerfile
El Dockerfile define el contenedor donde se ejecutan las plantillas NGINX y Consul. La plantilla de Consul usa los otros dos archivos para actualizar dinámicamente los upstreams de NGINX cuando el servicio de mensajería cambia (las instancias de servicio aparecen o desaparecen) en su registro de servicio.
Abra el archivo nginx.ctmpl creado en el Paso 1 y agregue el siguiente fragmento de configuración de NGINX, que la plantilla de Consul usa para actualizar dinámicamente el grupo ascendente de NGINX:
servicio de mensajería ascendente { {{- rango servicio "mensajero" }}
servidor {{ .Dirección }}:{{ .Puerto }};
{{- fin }}
}
servidor {
escuchar 8085;
nombre_servidor localhost;
ubicación / {
contraseña_proxy http://servicio_mensajero;
add_header Host_ascendente $upstream_addr;
}
}
Este fragmento agrega la dirección IP y el número de puerto de cada instancia de servicio de mensajería registrada con Consul al grupo ascendente messenger_service de NGINX. NGINX envía las solicitudes entrantes al conjunto definido dinámicamente de instancias de servicio ascendentes.
Abra el archivo consul-template-config.hcl creado en el Paso 1 y agregue la siguiente configuración:
cónsul { dirección = "consul-client:8500"
retry {
habilitado = verdadero
intentos = 12
retroceso = "250ms"
}
}
plantilla {
origen = "/usr/templates/nginx.ctmpl"
destino = "/etc/nginx/conf.d/default.conf"
perms = 0600
comando = "si [ -e /var/run/nginx.pid ]; entonces nginx -s recargar; de lo contrario nginx; fi"
}
Esta configuración para la plantilla Consul le indica que vuelva a renderizar la plantilla de origen
(el fragmento de configuración de NGINX creado en el paso anterior), la coloque en el destino
especificado y, finalmente, ejecute el comando
especificado (que le indica a NGINX que vuelva a cargar su configuración).
En la práctica, esto significa que se crea un nuevo archivo default.conf cada vez que se registra, actualiza o cancela el registro de una instancia de servicio en Consul. Luego, NGINX vuelve a cargar su configuración sin tiempo de inactividad, lo que garantiza que NGINX tenga un conjunto de servidores (instancias de servicio de mensajería ) actualizado y en buen estado a los que pueda enviar tráfico.
Abra el archivo Dockerfile creado en el Paso 1 y agregue el siguiente contenido, que crea el servicio NGINX. (No es necesario que comprenda el Dockerfile para los fines de este tutorial, pero el código está documentado en línea para su conveniencia).
DESDE nginx:1.23.1 ARG CONSUL_TEMPLATE_VERSION=0.30.0 # Establezca una variable de entorno para la ubicación del clúster Consul. De forma predeterminada, intenta resolverse en consul-client:8500 , que es el comportamiento si Consul se ejecuta como un contenedor en el mismo host y está vinculado a este contenedor NGINX (con el alias consul, por supuesto). Pero esta variable de entorno también puede ser anulada cuando se inicia el contenedor si queremos resolverlo en otra dirección.
ENV CONSUL_URL consul-client:8500 # Descargar la versión especificada de la plantilla Consul ADD https://releases.hashicorp.com/consul-template/${CONSUL_TEMPLATE_VERSION} /plantilla-consul_${CONSUL_TEMPLATE_VERSION} _linux_amd64.zip /tmp EJECUTAR apt-get update \ && apt-get install -y --no-install-recommends dumb-init unzip \ && unzip /tmp/consul-template_${CONSUL_TEMPLATE_VERSION} _linux_amd64.zip -d /usr/local/bin \ && rm -rf /tmp/consul-template_${CONSUL_TEMPLATE_VERSION} _linux_amd64.zip COPIAR consul-template-config.hcl ./consul-template-config.hcl COPIAR nginx.ctmpl /usr/templates/nginx.ctmpl EXPONER 8085 SEÑAL DE PARADA SIGQUIT CMD ["dumb-init", "consul-template", "-config=consul-template-config.hcl"]
Construir una imagen de Docker:
docker build -t messenger-lb .
Cambie a la raíz del directorio del mensajero y cree un archivo llamado messenger-load-balancer-deploy.sh como archivo de implementación para el servicio NGINX (al igual que con el resto de los servicios que ha implementado a lo largo del tutorial). Dependiendo de su entorno, es posible que necesite anteponer sudo
al comando chmod
:
cd ..
touch infraestructura/messenger-load-balancer-deploy.sh
chmod +x infraestructura/messenger-load-balancer-deploy.sh
Abra messenger-load-balancer-deploy.sh y agregue el siguiente contenido:
#!/bin/bashset -e # El host y el puerto de Consul se incluyen en cada host ya que # no podemos consultar a Consul hasta que los conozcamos CONSUL_HOST="${CONSUL_HOST} " CONSUL_PORT="${CONSUL_PORT} "docker run\--rm\-d\--name messenger-lb\-e CONSUL_URL="${CONSUL_HOST} :${CONSUL_PORT} " \ -p 8085:8085 \ --network mm_2023 \ messenger-lb
Ahora que tiene todo en su lugar, implemente el servicio NGINX:
CONSUL_HOST=cliente-consul CONSUL_PORT=8500 ./infraestructura/messenger-load-balancer-deploy.sh
Vea si puede acceder al servicio de mensajería externamente:
curl -X GET http://localhost:8085/health OK
¡Funciona! NGINX ahora equilibra la carga en todas las instancias del servicio de mensajería que se han creado. Puedes saberlo porque el encabezado X-Forwarded-For
muestra las mismas direcciones IP del servicio de mensajería que las de la interfaz de usuario de Consul en el paso 8 de la sección anterior.
Las aplicações grandes a menudo utilizan “ejecutores de trabajos” con pequeños procesos de trabajo que pueden usarse para realizar tareas únicas como modificar datos (algunos ejemplos son Sidekiq y Celery ). Estas herramientas a menudo requieren infraestructura de soporte adicional, como Redis o RabbitMQ . En este caso, utiliza el propio servicio de mensajería como un “ejecutor de tareas” para ejecutar tareas puntuales. Esto tiene sentido porque ya es muy pequeño, es totalmente capaz de interactuar con la base de datos y otras piezas de infraestructura de las que depende, y se ejecuta de forma completamente independiente de la aplicação que sirve el tráfico.
Hacer esto tiene tres beneficios:
En este desafío, explorarás cómo se puede modificar un artefacto para cumplir una nueva función cambiando algunos valores de configuración de la base de datos y migrando la base de datos del mensajero para usar los nuevos valores y probar su rendimiento .
Para una implementación de producción en el mundo real, puede crear dos usuarios distintos con diferentes permisos: un “usuario de aplicação ” y un “usuario migrador”. Para simplificar, en este ejemplo se utiliza el usuario predeterminado como usuario de la aplicação y se crea un usuario migrador con privilegios de superusuario. En una situación real, vale la pena dedicar más tiempo a decidir qué permisos mínimos específicos necesita cada usuario en función de su rol.
En la terminal de la aplicación, cree un nuevo usuario PostgreSQL con privilegios de superusuario:
echo "CREAR USUARIO messenger_migrator CON CONTRASEÑA DE SUPERUSUARIO 'migrator_password';" | docker exec -i messenger-db-primary psql -U postgres
Abra el script de implementación de la base de datos ( infrastructure/messenger-db-deploy.sh ) y reemplace su contenido para agregar las credenciales del nuevo usuario.
Nota: Tomémonos el tiempo para reiterar: para una implementación en el mundo real, NUNCA coloque secretos como credenciales de base de datos en un script de implementación o en cualquier otro lugar que no sea una herramienta de administración de secretos. Para más detalles, consulte la Unidad 2: Secretos de microservicios Gestión 101 de microservicios Marzo de 2023.
#!/bin/bash set -e PORT=5432 POSTGRES_USER=postgres # NOTA: Nunca hagas esto en una implementación del mundo real. Almacene las contraseñas # solo en un almacén de secretos cifrados. # Debido a que nos centraremos en otros conceptos en este tutorial, # configuramos la contraseña de esta manera aquí para mayor comodidad.
POSTGRES_PASSWORD=postgres # Usuario de migración POSTGRES_MIGRATOR_USER=messenger_migrator # NOTA: Como se mencionó anteriormente, nunca haga esto en una implementación real.
POSTGRES_MIGRATOR_PASSWORD=contraseña_del_migrador docker run \ --rm \ --name messenger-db-primary \ -d \ -v db-data:/var/lib/postgresql/data/pgdata \ -e POSTGRES_USER="${POSTGRES_USER} " \ -e CONTRASEÑA_POSTGRES="${POSTGRES_PASSWORD} " \ -e PGPORT="${PORT} " -e PGDATA=/var/lib/postgresql/data/pgdata --network mm_2023 postgres:15.1 echo "Registrar clave messenger-db-port\n" curl -X PUT --silent --output /dev/null --show-error --fail http://localhost:8500/v1/kv/messenger-db-port -H "Tipo de contenido: aplicação/json" -d${PORT} " echo "Registrar clave messenger-db-host\n" curl -X PUT --silent --output /dev/null --show-error --fail http://localhost:8500/v1/kv/messenger-db-host \ -H "Content-Type: aplicação/json" \ -d 'messenger-db-primary' # Esto coincide con el indicador "--name" anterior # que para nuestra configuración significa el nombre de host echo "Registrar clave messenger-db-application-user\n" curl -X PUT --silent --output /dev/null --show-error --fail http://localhost:8500/v1/kv/messenger-db-application-user \ -H "Content-Type: aplicação/json" \ -d "${POSTGRES_USER} " curl -X PUT --silent --output /dev/null --show-error --fail http://localhost:8500/v1/kv/messenger-db-password-never-do-this \ -H "Tipo de contenido: aplicação/json" \ -d "${POSTGRES_PASSWORD} " echo "Registrar clave messenger-db-application-user\n" curl -X PUT --silent --output /dev/null --show-error --fail http://localhost:8500/v1/kv/messenger-db-migrator-user \ -H "Tipo de contenido: aplicação/json" \ -d "${POSTGRES_MIGRATOR_USER} " curl -X PUT --silent --output /dev/null --show-error --fail http://localhost:8500/v1/kv/messenger-db-migrator-password-never-do-this \ -H "Tipo de contenido: aplicação/json" \ -d "${POSTGRES_MIGRATOR_PASSWORD} " printf "\nSe terminó de registrar los detalles de postgres con Consul\n"
Este cambio solo agrega el usuario migrador al conjunto de usuarios que se configura en Consul después de que se implementa la base de datos.
Cree un nuevo archivo en el directorio de infraestructura llamado messenger-db-migrator-deploy.sh (nuevamente, es posible que deba anteponer el comando chmod
con sudo
):
toque infraestructura/messenger-db-migrator-deploy.shchmod +x infraestructura/messenger-db-migrator-deploy.sh
Abra messenger-db-migrator-deploy.sh y agregue lo siguiente:
#!/bin/bashset -e # Esta configuración requiere una nueva confirmación para cambiar NODE_ENV=production PORT=4000 JSON_BODY_LIMIT=100kb CONSUL_SERVICE_NAME="messenger-migrator" # El host y el puerto de Consul se incluyen en cada host ya que # no podemos consultar a Consul hasta que los conozcamos CONSUL_HOST="${CONSUL_HOST} " CONSUL_PORT="${CONSUL_PORT} " # Obtener el nombre de usuario y la contraseña del migrador POSTGRES_USER=$(curl -X GET "http://localhost:8500/v1/kv/messenger-db-migrator-user?raw=true") PGPORT=$(curl -X GET "http://localhost:8500/v1/kv/messenger-db-port?raw=true") PGHOST=$(curl -X GET http://localhost:8500/v1/kv/messenger-db-host?raw=true) # NOTA: Nunca hagas esto en una implementación del mundo real. Almacene las contraseñas # únicamente en un almacén de secretos cifrados.
PGPASSWORD=$(curl -X GET "http://localhost:8500/v1/kv/messenger-db-migrator-password-never-do-this?raw=true") # Configuración de RabbitMQ extrayendo del sistema AMQPHOST=$(curl -X GET "http://localhost:8500/v1/kv/amqp-host?raw=true") AMQPPORT=$(curl -X GET "http://localhost:8500/v1/kv/amqp-port?raw=true") docker run \--rm \ -d \ --name messenger-migrator \ -e NODE_ENV="${NODE_ENV} " \ -e PUERTO="${PORT} " \ -e LÍMITE_DEL_CUERPO_JSON="${JSON_BODY_LIMIT} " \ -e PGUSER="${POSTGRES_USER} " \ -e PGPORT="${PGPORT} " \ -e PGHOST="${PGHOST} " \ -e PGPASSWORD="${PGPASSWORD} " \ -e AMQPPORT="${AMQPPORT} " \ -e AMQPHOST="${AMQPHOST} " \ -e CONSUL_HOST="${CONSUL_HOST} " \ -e CONSUL_PORT="${CONSUL_PORT} " \ -e NOMBRE_SERVICIO_CÓNSUL="${CONSUL_SERVICE_NAME} " \ --network mm_2023 \ mensajero
Este script es bastante similar al script Infrastructure/messenger-deploy.sh en su forma final, que creó en el Paso 3 de Configurar Consul . La principal diferencia es que CONSUL_SERVICE_NAME
es messenger-migrator
en lugar de messenger
, y PGUSER
corresponde al superusuario “migrator” que creó en el Paso 1 anterior.
Es importante que CONSUL_SERVICE_NAME
sea messenger-migrator
. Si se configurara como Messenger
, NGINX pondría automáticamente este servicio en rotación para recibir llamadas API y no está destinado a manejar ningún tráfico.
El script despliega una instancia de corta duración en el rol de migrador. Esto evita que cualquier problema con la migración afecte el servicio de tráfico por parte de las instancias del servicio de mensajería principal.
Volver a implementar la base de datos PostgreSQL. Dado que en este tutorial utiliza scripts bash
, deberá detener y reiniciar el servicio de base de datos. En una aplicação de producción, normalmente solo se ejecuta un script de infraestructura como código para agregar únicamente los elementos que han cambiado.
docker stop messenger-db-primaryCONSUL_HOST=consul-client CONSUL_PORT=8500 ./infraestructura/messenger-db-deploy.sh
Implementar el servicio de migración de bases de datos PostgreSQL:
CONSUL_HOST=cliente-consul CONSUL_PORT=8500 ./infraestructura/messenger-db-migrator-deploy.sh
Verifique que la instancia se esté ejecutando como se espera:
docker ps --format "{{.Names}}" ... messenger-migrator
También puedes verificar en la interfaz de usuario de Consul que el servicio de migración de base de datos se haya registrado correctamente en Consul como messenger-migrator (nuevamente, no se registra con el nombre de messenger porque no maneja tráfico):
¡Ahora, el paso final: ejecutar los scripts de migración de la base de datos! Estos scripts no se parecen a ningún script de migración de base de datos real, pero utilizan el servicio messenger-migrator para ejecutar scripts específicos de la base de datos. Una vez migrada la base de datos, detenga el servicio messenger-migrator :
docker exec -i -e PGDATABASE=postgres -e CREATE_BD_NAME=messenger messenger-migrator node scripts/create-db.mjs docker exec -i messenger-migrator node scripts/create-schema.mjs
docker exec -i messenger-migrator node scripts/create-seed-data.mjs
docker stop messenger-migrator
Ahora que has migrado la base de datos de mensajería a su formato final, ¡el servicio de mensajería finalmente está listo para que lo veas en acción! Para hacer esto, ejecute algunas consultas curl
básicas contra el servicio NGINX (usted configuró NGINX como el punto de entrada del sistema en Configurar NGINX ).
Algunos de los siguientes comandos utilizan la biblioteca jq
para formatear la salida JSON. Puede instalarlo según sea necesario u omitirlo desde la línea de comando si lo desea.
Crear una conversación:
curl -d '{"participant_ids": [1, 2]}' -H "Tipo de contenido: aplicação/json" -X POST 'http://localhost:8085/conversations' { "conversation": { "id": "1", "insertado_en": " AAAA - MM - DD T06:41:59.000Z" } }
Envía un mensaje a la conversación desde un usuario con ID 1:
curl -d '{"contenido": "Este es el primer mensaje"}' -H "Id. de usuario: 1" -H "Tipo de contenido: aplicação/json" -X POST 'http://localhost:8085/conversaciones/1/mensajes' | jq { "mensaje": { "id": "1", "contenido": "Este es el primer mensaje", "índice": 1, "id_de_usuario": 1, "nombre de usuario": "James Blanderphone", "conversación_id": 1, "insertado_en": " AAAA - MM - DD T06:42:15.000Z" } }
Responder con un mensaje de un usuario diferente (con ID 2):
curl -d '{"contenido": "Este es el segundo mensaje"}' -H "Id. de usuario: 2" -H "Tipo de contenido: aplicação/json" -X POST 'http://localhost:8085/conversaciones/1/mensajes' | jq { "mensaje": { "id": "2", "contenido": "Este es el segundo mensaje", "índice": 2, "id_de_usuario": 2, "nombre de usuario": "Arcoíris de Normandía", "id de conversación": 1, "insertado_en": " AAAA - MM - DD T06:42:25.000Z" } }
Obtener los mensajes:
curl -X GET 'http://localhost:8085/conversaciones/1/mensajes' | jq { "mensajes": [ { "id": "1", "contenido": "Este es el primer mensaje", "user_id": "1", "id_del_canal": "1", "índice": "1", "insertado_en": " AAAA - MM - DD T06:42:15.000Z", "nombre de usuario": "James Blanderphone" }, { "identificación": "2", "contenido": "Este es el segundo mensaje", "user_id": "2", "id_del_canal": "1", "índice": "2", "insertado_en": " AAAA - MM - DD T06:42:25.000Z", "nombre de usuario": "Cabezudo normando"
¡Has creado una cantidad significativa de contenedores e imágenes a lo largo de este tutorial! Utilice los siguientes comandos para eliminar cualquier contenedor e imagen de Docker que no desee conservar.
Para eliminar cualquier contenedor Docker en ejecución:
docker rm $(docker stop $(docker ps -a -q --filter ancestor=messenger --format="{{.ID}}"))docker rm $(docker stop messenger-db-primary)
docker rm $(docker stop messenger-lb)
Para eliminar los servicios de la plataforma :
# Desde el repositorio de la plataforma docker compose down
Para eliminar todas las imágenes de Docker utilizadas en el tutorial:
Docker RMI Messenger
Docker RMI Messenger-LB
Docker RMI Postgres: 15.1
Docker RMI Hashicorp/Consul: 1.14.4
Docker RMI RabbitMQ: 3.11.4-Management-Alpine
Podrías estar pensando: “Parece mucho trabajo montar algo tan sencillo”, ¡y estarías en lo cierto! Para pasar a una arquitectura centrada en microservicios es necesario ser meticuloso en cómo estructurar y configurar los servicios. A pesar de toda la complejidad, has logrado avances importantes:
Para continuar su educación sobre microservicios, consulte Microservicios de marzo de 2023. La Unidad 2, Microservices Secrets Management 101 , proporciona una descripción general detallada pero fácil de usar de la gestión de secretos en entornos de microservicios.
"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.