Implementa el procesamiento de imágenes mediante microservicios y mensajería asíncrona

Last reviewed 2023-07-17 UTC

En este documento, se describe cómo implementar la arquitectura de referencia que se describe en Integra microservicios con Pub/Sub y GKE. La arquitectura está diseñada para manejar procesos de larga duración mediante contenedores y mensajería asíncrona.

En el documento, se usa una aplicación de uso compartido de fotos de ejemplo que genera miniaturas de fotos. Implementa la aplicación mediante Google Kubernetes Engine (GKE) y usa Pub/Sub para invocar procesos de larga duración de forma asíncrona. También puedes usar las notificaciones de Pub/Sub para Cloud Storage a fin de agregar trabajos complementarios sin modificar el código de la aplicación.

Cloud Build aloja la aplicación en contenedores y la almacena en Artifact Registry. Usa Cloud Vision para detectar imágenes inadecuadas.

Arquitectura

En el siguiente diagrama, se ilustra el diseño de la aplicación de álbum de fotos de ejemplo que implementa la arquitectura de referencia.

Arquitectura de la aplicación de álbum de fotos

Figura 1. Arquitectura para el procesamiento de imágenes basada en el uso de contenedores y mensajería asíncrona.

En el diagrama anterior, se muestra cómo se genera la miniatura:

  1. Un cliente sube una imagen a la aplicación.
  2. La aplicación almacena la imagen en Cloud Storage.
  3. Se genera una solicitud para la miniatura.
  4. El generador de miniaturas genera la miniatura.
  5. La respuesta correcta se envía a la aplicación de álbum de fotos.
  6. La respuesta correcta se envía al cliente y puedes encontrar la miniatura en Cloud Storage.

En el siguiente diagrama, se muestra cómo la aplicación implementa la generación de miniaturas como un servicio independiente de manera asíncrona.

Arquitectura del proceso de extracción de miniaturas.

Figura 2. Arquitectura del proceso de extracción de miniaturas.

Usas Pub/Sub para enviar solicitudes al servicio de generación de miniaturas. Esta arquitectura nueva logra que la llamada de servicio sea asíncrona para que se cree una miniatura en segundo plano después de que la aplicación envía la respuesta a un cliente. Este diseño también permite que el servicio de generación de miniaturas se escale para que varios trabajos puedan ejecutarse en paralelo.

Objetivos

  • Implementar una aplicación de álbum de fotos de ejemplo en GKE
  • Realizar llamadas de servicio asíncronas desde la aplicación
  • Usar las notificaciones de Pub/Sub para Cloud Storage a fin de activar la aplicación cuando se suba un archivo nuevo al bucket de Cloud Storage
  • Usar Pub/Sub para realizar más tareas sin modificar la aplicación

Costos

En este documento, usarás los siguientes componentes facturables de Google Cloud:

Para generar una estimación de costos en función del uso previsto, usa la calculadora de precios. Es posible que los usuarios nuevos de Google Cloud califiquen para obtener una prueba gratuita.

Cuando termines de compilar la aplicación de ejemplo, puedes borrar los recursos que creaste para evitar que continúe la facturación. Para obtener más información, consulta Cómo realizar una limpieza.

Antes de comenzar

  1. Accede a tu cuenta de Google Cloud. Si eres nuevo en Google Cloud, crea una cuenta para evaluar el rendimiento de nuestros productos en situaciones reales. Los clientes nuevos también obtienen $300 en créditos gratuitos para ejecutar, probar y, además, implementar cargas de trabajo.
  2. En la página del selector de proyectos de la consola de Google Cloud, selecciona o crea un proyecto de Google Cloud.

    Ir al selector de proyectos

  3. Asegúrate de que la facturación esté habilitada para tu proyecto de Google Cloud.

  4. Habilita las API de GKE, Cloud SQL, Cloud Build, Artifact Registry, and Cloud Vision.

    Habilita las API

  5. En la página del selector de proyectos de la consola de Google Cloud, selecciona o crea un proyecto de Google Cloud.

    Ir al selector de proyectos

  6. Asegúrate de que la facturación esté habilitada para tu proyecto de Google Cloud.

  7. Habilita las API de GKE, Cloud SQL, Cloud Build, Artifact Registry, and Cloud Vision.

    Habilita las API

  8. En la consola de Google Cloud, activa Cloud Shell.

    Activar Cloud Shell

    En la parte inferior de la consola de Google Cloud, se inicia una sesión de Cloud Shell en la que se muestra una ventana de línea de comandos. Cloud Shell es un entorno de shell con Google Cloud CLI ya instalada y con valores ya establecidos para el proyecto actual. La sesión puede tardar unos segundos en inicializarse.

Configure el entorno

En esta sección, dasignarás la configuración predeterminada para los valores que se usarán en todo el documento. Si cierras la sesión de Cloud Shell, perderás la configuración del entorno.

  1. En Cloud Shell, establece tu proyecto de Google Cloud predeterminado:

    gcloud config set project PROJECT_ID
    

    Reemplaza PROJECT_ID por el ID del proyecto de Google Cloud.

  2. Configura la región de Compute Engine predeterminada:

    gcloud config set compute/region REGION
    export REGION=REGION
    

    Reemplaza REGION por una región cercana a ti. Para obtener más información, consulta Regiones y zonas.

  3. Configura la zona predeterminada de Compute Engine:

    gcloud config set compute/zone ZONE
    export ZONE=ZONE
    

    Reemplaza ZONE por una zona cercana a ti.

  4. Descarga los archivos de aplicación de ejemplo y configura el directorio actual:

    git clone https://github.com/GoogleCloudPlatform/gke-photoalbum-example
    cd gke-photoalbum-example
    

Crea un bucket de Cloud Storage y sube la imagen en miniatura predeterminada

  1. En Cloud Shell, crea un bucket de Cloud Storage para almacenar las imágenes y las miniaturas originales:

    export PROJECT_ID=$(gcloud config get-value project)
    gsutil mb -c regional -l ${REGION} gs://${PROJECT_ID}-photostore
    
  2. Sube el archivo de miniaturas predeterminado:

    gsutil cp ./application/photoalbum/images/default.png \
        gs://${PROJECT_ID}-photostore/thumbnails/default.png
    
    • Las imágenes que se subieron se almacenan en el siguiente formato: gs://PROJECT_ID-photostore/FILENAME; en este caso, FILENAME representa el nombre del archivo de imagen que se sube.
    • Las miniaturas generadas se almacenan en el siguiente formato: gs://PROJECT_ID-photostore/thumbnails/FILENAME.
    • La imagen original y la miniatura correspondiente tienen el mismo FILENAME, pero la miniatura se almacena en el bucket thumbnails.
    • Mientras se crea la miniatura, se muestra la siguiente imagen en miniatura del marcador de posición default.png en la aplicación de álbum de fotos.

      La imagen en miniatura del marcador de posición predeterminado.

  3. Haz público el archivo de miniatura:

    gsutil acl ch -u AllUsers:R \
        gs://${PROJECT_ID}-photostore/thumbnails/default.png
    

Crea una instancia de Cloud SQL y una base de datos de MySQL

  1. En Cloud Shell, crea la instancia de Cloud SQL:

    gcloud sql instances create photoalbum-db --region=${REGION} \
        --database-version=MYSQL_8_0
    
  2. Recupera el nombre de la conexión:

    gcloud sql instances describe photoalbum-db \
        --format="value(connectionName)"
    

    Toma nota del nombre porque lo usarás más adelante.

  3. Establece la contraseña para el usuario root@% de MySQL:

    gcloud sql users set-password root --host=% --instance=photoalbum-db \
        --password=PASSWORD
    

    Reemplaza PASSWORD por una contraseña segura para el usuario root@%.

  4. Conéctate a la instancia de Cloud SQL:

    gcloud sql connect photoalbum-db --user=root --quiet
    

    Cuando se te solicite, ingresa la contraseña que configuraste en el paso anterior.

  5. Crea una base de datos llamada photo_db, en la que el usuario sea appuser y la contraseña sea pas4appuser:

    create database photo_db;
    create user 'appuser'@'%' identified by 'pas4appuser';
    grant all on photo_db.* to 'appuser'@'%' with grant option;
    flush privileges;
    
  6. Confirma el resultado y sal de MySQL:

    show databases;
    select user from mysql.user;
    exit
    

    En la salida, confirma que se hayan creado la base de datos photo_db y el usuario appuser:

    mysql> show databases;
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | mysql              |
    | performance_schema |
    | photo_db           |
    | sys                |
    +--------------------+
    5 rows in set (0.16 sec)
    
    mysql> \t
    Outfile disabled.
    mysql> select user from mysql.user;
    +-------------------+
    | user              |
    +-------------------+
    | appuser           |
    | cloudsqlreplica   |
    | cloudsqlsuperuser |
    | root              |
    | cloudsqlexport    |
    | cloudsqlimport    |
    | cloudsqloneshot   |
    | root              |
    | cloudsqlexport    |
    | cloudsqlimport    |
    | cloudsqloneshot   |
    | root              |
    | cloudsqlapplier   |
    | cloudsqlimport    |
    | mysql.infoschema  |
    | mysql.session     |
    | mysql.sys         |
    | root              |
    +-------------------+
    18 rows in set (0.16 sec)
    
    mysql> exit
    Bye
    

Crea un tema y una suscripción de Pub/Sub

  1. En Cloud Shell, crea un tema de Pub/Sub llamado thumbnail-service:

    gcloud pubsub topics create thumbnail-service
    

    La aplicación de álbum de fotos envía solicitudes al servicio de generación de miniaturas mediante la publicación de un mensaje en el tema thumbnail-service.

  2. Crea una suscripción a Pub/Sub llamada thumbnail-workers:

    gcloud pubsub subscriptions create --topic thumbnail-service thumbnail-workers
    

    El servicio de generación de miniaturas recibe solicitudes de la suscripción thumbnail-workers.

Crea un clúster de GKE

  1. En Cloud Shell, crea un clúster de GKE que tenga permiso para llamar a las APIs:

    gcloud container clusters create "photoalbum-cluster" \
        --scopes "https://www.googleapis.com/auth/cloud-platform" \
        --num-nodes "5"
    
  2. Obtén credenciales de acceso configuradas para que puedas administrar el clúster con el comando kubectl en pasos posteriores:

    gcloud container clusters get-credentials photoalbum-cluster
    
  3. Muestra la lista de nodos:

    kubectl get nodes
    

    En el resultado, confirma que haya cinco nodos cuyo valor STATUS sea Ready:

    NAME                                                STATUS   ROLES    AGE     VERSION
    gke-photoalbum-cluster-default-pool-d637570a-2pfh   Ready    <none>   2m55s   v1.24.10-gke.2300
    gke-photoalbum-cluster-default-pool-d637570a-3rm4   Ready    <none>   2m55s   v1.24.10-gke.2300
    gke-photoalbum-cluster-default-pool-d637570a-f7l4   Ready    <none>   2m55s   v1.24.10-gke.2300
    gke-photoalbum-cluster-default-pool-d637570a-qb2z   Ready    <none>   2m53s   v1.24.10-gke.2300
    gke-photoalbum-cluster-default-pool-d637570a-rvnp   Ready    <none>   2m54s   v1.24.10-gke.2300
    

Crea el repositorio de Artifact Registry

  • En Cloud Shell, crea un repositorio para almacenar imágenes de contenedor:

    gcloud artifacts repositories create photoalbum-repo \
        --repository-format=docker \
        --location=us-central1 \
        --description="Docker repository"
    

Compila imágenes para la aplicación

  1. En un editor de texto, abre el archivo application/photoalbum/src/auth_decorator.py y actualiza el nombre de usuario y la contraseña:

    USERNAME = 'username'
    PASSWORD = 'passw0rd'
    
  2. En Cloud Shell, compila una imagen para la aplicación de álbum de fotos con el servicio de Cloud Build:

    gcloud builds submit ./application/photoalbum -t \
        us-central1-docker.pkg.dev/${PROJECT_ID}/photoalbum-repo/photoalbum-app
    
  3. Crea una imagen para el servicio de generación de miniaturas thumbnail-worker con el servicio de Cloud Build:

    gcloud builds submit ./application/thumbnail -t \
        us-central1-docker.pkg.dev/${PROJECT_ID}/photoalbum-repo/thumbnail-worker
    

Implementa la aplicación de álbum de fotos

  1. En Cloud Shell, actualiza los manifiestos de implementación de Kubernetes para el álbum de fotos y el generador de miniaturas con los valores de tu entorno:

    connection_name=$(gcloud sql instances describe photoalbum-db \
        --format "value(connectionName)")
    
    digest_photoalbum=$(gcloud container images describe \
        us-central1-docker.pkg.dev/${PROJECT_ID}/photoalbum-repo/photoalbum-app:latest --format \
        "value(image_summary.digest)")
    
    sed -i.bak -e "s/\[PROJECT_ID\]/${PROJECT_ID}/" \
        -e "s/\[CONNECTION_NAME\]/${connection_name}/" \
        -e "s/\[DIGEST\]/${digest_photoalbum}/" \
        config/photoalbum-deployment.yaml
    
    digest_thumbnail=$(gcloud container images describe \
        us-central1-docker.pkg.dev/${PROJECT_ID}/photoalbum-repo/thumbnail-worker:latest --format \
        "value(image_summary.digest)")
    
    sed -i.bak -e "s/\[PROJECT_ID\]/${PROJECT_ID}/" \
        -e "s/\[CONNECTION_NAME\]/${connection_name}/" \
        -e "s/\[DIGEST\]/${digest_thumbnail}/" \
            config/thumbnail-deployment.yaml
    
  2. Crea recursos de implementación para iniciar la aplicación de álbum de fotos y el servicio de generación de miniaturas:

    kubectl create -f config/photoalbum-deployment.yaml
    kubectl create -f config/thumbnail-deployment.yaml
    
  3. Crea un recurso de servicio para asignar una dirección IP externa a la aplicación:

    kubectl create -f config/photoalbum-service.yaml
    
  4. Verifica los resultados de los pods:

    kubectl get pods
    

    En el resultado, confirma que haya tres pods para cada pod de photoalbum-app y thumbail-worker, y que su valor de STATUS sea Running:

    NAME                                READY     STATUS    RESTARTS   AGE
    photoalbum-app-555f7cbdb7-cp8nw     2/2       Running   0          2m
    photoalbum-app-555f7cbdb7-ftlc6     2/2       Running   0          2m
    photoalbum-app-555f7cbdb7-xsr4b     2/2       Running   0          2m
    thumbnail-worker-86bd95cd68-728k5   2/2       Running   0          2m
    thumbnail-worker-86bd95cd68-hqxqr   2/2       Running   0          2m
    thumbnail-worker-86bd95cd68-xnxhc   2/2       Running   0          2m
    

    Los pods thumbnail-worker suscriben solicitudes de generación de miniaturas de la suscripción thumbnail-workers. Para obtener más información, consulta cómo se usa la función callback en el código fuente.

  5. Verifica los resultados de los servicios:

    kubectl get services
    

    En el resultado, confirma que haya una dirección IP externa en la columna EXTERNAL-IP del servicio photoalbum-service. Es posible que tome unos minutos en ejecutarse.

    NAME                 TYPE           CLUSTER-IP      EXTERNAL-IP       PORT(S)        AGE
    kubernetes           ClusterIP      10.23.240.1     <none>            443/TCP        20m
    photoalbum-service   LoadBalancer   10.23.253.241   146.148.111.115   80:32657/TCP   2m
    

    Toma nota de la dirección IP externa, ya que se usará más adelante. En este ejemplo, es 146.148.111.115.

Prueba la aplicación de álbum de fotos

  1. Para acceder a la aplicación implementada en un navegador web, ve a la siguiente URL y, luego, ingresa el nombre de usuario y la contraseña que configuraste antes:

    http://EXTERNAL_IP
    

    Reemplaza EXTERNAL_IP por la dirección IP que copiaste en el paso anterior.

  2. Para subir un archivo de imagen, haz clic en Subir.

    La miniatura del marcador de posición que se muestra mientras esperas a que el servicio genere una miniatura única.

    El marcador de posición de la miniatura aparecerá en la pantalla.

    En segundo plano, el servicio de generación de miniaturas crea una miniatura de la imagen subida. Para ver la miniatura generada, haz clic en Refresh (Actualizar). La API de Cloud Vision agrega etiquetas de imagen que detecta.

    La miniatura con etiquetas de imagen asociadas.

    Para ver la imagen original, haz clic en la miniatura.

Agrega una función de detección de imágenes inadecuadas

En la siguiente imagen, se muestra cómo puedes usar las notificaciones de Pub/Sub para Cloud Storage a fin de activar un servicio que detecte contenido inadecuado. Esta función desenfoca la imagen cuando se almacena un archivo nuevo con contenido inadecuado en el bucket de Cloud Storage.

Arquitectura de la función de contenido inapropiado

En la imagen anterior, el servicio usa la función de detección de SafeSearch de la API de Vision para detectar contenido inadecuado en una imagen.

La aplicación de fotos activa el generador de miniaturas y el verificador de imágenes de forma asíncrona. Como resultado, no hay garantía de que se ejecuten en un orden específico. Si la generación de miniaturas ocurre antes de que se difumine la imagen, es posible que veas una miniatura inapropiada durante un tiempo breve. Sin embargo, el verificador de imágenes finalmente difumina la imagen inadecuada y la miniatura inadecuada.

Crea un tema, una suscripción y una notificación de Pub/Sub

  1. En Cloud Shell, crea un tema de Pub/Sub llamado safeimage-service:

    gcloud pubsub topics create safeimage-service
    
  2. Crea una suscripción a Pub/Sub llamada safeimage-workers:

    gcloud pubsub subscriptions create --topic safeimage-service \
        safeimage-workers
    
  3. Configura una notificación de Pub/Sub para que se envíe un mensaje al tema safeimage-service cuando se suba un archivo nuevo al depósito de Cloud Storage:

    gsutil notification create -t safeimage-service -f json \
        gs://${PROJECT_ID}-photostore
    

Compila e implementa la imagen del trabajador

  1. En Cloud Shell, compila una imagen de contenedor para la suscripción safeimage-workers con Cloud Build:

    gcloud builds submit ./application/safeimage \
        -t us-central1-docker.pkg.dev/${PROJECT_ID}/photoalbum-repo/safeimage-worker
    
  2. Actualiza los manifiestos de implementación de Kubernetes para el servicio de imagen segura con tu ID del proyecto de Google Cloud, el nombre de la conexión de Cloud SQL y los resúmenes de imágenes de contenedor:

    digest_safeimage=$(gcloud container images describe \
        us-central1-docker.pkg.dev/${PROJECT_ID}/photoalbum-repo/safeimage-worker:latest --format \
        "value(image_summary.digest)")
    sed -i.bak -e "s/\[PROJECT_ID\]/${PROJECT_ID}/" \
        -e "s/\[CONNECTION_NAME\]/${connection_name}/" \
        -e "s/\[DIGEST\]/${digest_safeimage}/" \
        config/safeimage-deployment.yaml
    

Crea un recurso de implementación

  1. Crea un recurso de implementación llamado safeimage-deployment para implementar el tema safeimage-service:

    kubectl create -f config/safeimage-deployment.yaml
    
  2. Verifica los resultados:

    kubectl get pods
    

    En el resultado, confirma que haya tres pods safeimage-worker cuyo valor STATUS sea Running.

    NAME                                READY     STATUS    RESTARTS   AGE
    photoalbum-app-555f7cbdb7-cp8nw     2/2       Running   0          30m
    photoalbum-app-555f7cbdb7-ftlc6     2/2       Running   0          30m
    photoalbum-app-555f7cbdb7-xsr4b     2/2       Running   8          30m
    safeimage-worker-7dc8c84f54-6sqzs   1/1       Running   0          2m
    safeimage-worker-7dc8c84f54-9bskw   1/1       Running   0          2m
    safeimage-worker-7dc8c84f54-b7gtp   1/1       Running   0          2m
    thumbnail-worker-86bd95cd68-9wrpv   2/2       Running   0          30m
    thumbnail-worker-86bd95cd68-kbhsn   2/2       Running   2          30m
    thumbnail-worker-86bd95cd68-n4rj7   2/2       Running   0          30m
    

    Los pods safeimage-worker se suscriben a solicitudes de detección de imágenes inapropiadas de la suscripción safeimage-workers. Para obtener más información, consulta cómo se usa la función callback en el código fuente.

Prueba la función de detección de imágenes inadecuada

En esta sección, subirás una imagen de prueba para verificar que la función de detección de SafeSearch desenfoque una imagen inadecuada. La imagen de prueba es de una niña vestida de zombi (con licencia de CC0 de Pixaby).

  1. Descarga la imagen de prueba.
  2. Para subir la imagen, ve a http://EXTERNAL_IP y haz clic en Upload (Subir).
  3. Haz clic en Actualizar. La aplicación muestra una miniatura difuminada.

    Una miniatura difuminada.

    Para ver que la imagen subida también está desenfocada, haz clic en la miniatura.

Limpia

Si no deseas conservar los recursos de Google Cloud que creaste para la aplicación de ejemplo, puedes quitarlos a fin de que no se te facture por ellos en el futuro. Puedes borrar el proyecto por completo o borrar los recursos del clúster y, luego, borrar el clúster.

Borra el proyecto

  1. En la consola de Google Cloud, ve a la página Administrar recursos.

    Ir a Administrar recursos

  2. En la lista de proyectos, elige el proyecto que quieres borrar y haz clic en Borrar.
  3. En el diálogo, escribe el ID del proyecto y, luego, haz clic en Cerrar para borrar el proyecto.

Borra los recursos individuales

En lugar de borrar el proyecto, puedes borrar los recursos individuales que creaste.

  1. Borra recursos de GKE:

    kubectl delete -f config/safeimage-deployment.yaml
    kubectl delete -f config/photoalbum-service.yaml
    kubectl delete -f config/thumbnail-deployment.yaml
    kubectl delete -f config/photoalbum-deployment.yaml
    
  2. Borra el clúster de GKE:

    gcloud container clusters delete photoalbum-cluster --quiet
    
  3. Borra el repositorio de Artifact Registry:

    gcloud artifacts repositories delete photoalbum-repo --location us-central1 --quiet
    
  4. Borra suscripciones y temas de Pub/Sub:

    gcloud pubsub subscriptions delete safeimage-workers
    gcloud pubsub topics delete safeimage-service
    gcloud pubsub subscriptions delete thumbnail-workers
    gcloud pubsub topics delete thumbnail-service
    
  5. Borra la instancia de Cloud SQL:

    gcloud sql instances delete photoalbum-db --quiet
    
  6. Borra el bucket de Cloud Storage:

    gsutil rm -r gs://${PROJECT_ID}-photostore
    gsutil rm -r gs://${PROJECT_ID}_cloudbuild
    
  7. Borra los archivos:

    cd ..
    rm -rf gke-photoalbum-example
    

¿Qué sigue?

  • Lee sobre DevOps y obtén más información sobre la capacidad de la Arquitectura relacionada con esta arquitectura de referencia.
  • Realiza la verificación rápida de DevOps para comprender cuál es tu posición en comparación con el resto de la industria.
  • Para obtener más información sobre las arquitecturas de referencia, los diagramas y las prácticas recomendadas, explora Cloud Architecture Center.