Saltar a contenido

Visión general de la Arquitectura

QFieldCloud tiene una arquitectura en contenedores con múltiples contenedores y volúmenes.

Arquitectura QFieldCloud: Los rectángulos redondeados representan contenedores, las elipses representan volúmenes. El texto entre corchetes es el nombre del servicio que se encuentra en el archivo `docker-compose.yml`, el resto del texto es la función del contenedor. Las flechas entre contenedores indican quién inicia la comunicación. Las flechas entre un contenedor y un volumen representan si el contenedor lee (flecha que señala al contenedor) o escribe (flecha que señala al volumen) datos. Las flechas y contenedores en gris representan servicios obsoletos
Arquitectura QFieldCloud: Los rectángulos redondeados representan contenedores, las elipses representan volúmenes. El texto entre corchetes es el nombre del servicio que se encuentra en el archivo docker-compose.yml, el resto del texto es la función del contenedor. Las flechas entre contenedores indican quién inicia la comunicación. Las flechas entre un contenedor y un volumen representan si el contenedor lee (flecha que señala al contenedor) o escribe (flecha que señala al volumen) datos. Las flechas y contenedores en gris representan servicios obsoletos

Ver una versión interactiva de el dibujo anterior.

Nota Por simplicidad y claridad, todos los gráficos muestran el llamado "camino feliz" sin detallar la gestión de errores a lo largo del proceso.

Objetos Docker

Contenedores

[nginx] Proxy inverso

El proxy inverso que se sitúa delante de QFieldCloud. Debe tener un nginx para este propósito, ya que la cabecera HTTP X-Accel-Redirect se utiliza mucho en producción para servir archivos directamente desde el [minio] Almacenamiento de Archivos.

Requiere la presencia de un certificado SSL: autofirmado, Let's Encrypt u otro.

[app] Aplicación QFieldCloud

El software principal que ejecuta QFieldCloud, incluyendo autenticación, gestión de permisos, modelos de datos, archivos estáticos, interfaz administrativa y más.

Consta de varias aplicaciones Django, a saber:

  • autenticación - responsable de la autenticación de la API.
  • core - modelos de datos, permisos, gestión de colas de trabajo, API REST, interfaz administrativa y todo lo demás de QFieldCloud que no gestionan las otras aplicaciones Django.
  • filestorage - responsable de la gestión de archivos del proyecto y de su respectiva API REST.
  • notifs - módulo de notificaciones.
  • suscripción - gestión de los planes de usuario, suscripción y cuota de almacenamiento.

[memcached] Caché en memoria

Utiliza memcached para la caché en memoria de la configuración de Django y otros valores calculados.

[ofelia] Runner CRON

Utiliza ofelia para el runner CRON.

[mkcert] Creador del certificado autofirmado

Crea automáticamente un certificado SSL autofirmado para el desarrollo local y las implantaciones de prueba.

[certbot] Gestor de Letsencrypt

Utiliza certbot para gestionar los certificados Let's Encrypt. Recrea automáticamente los certificados SSL que caducan y son recargados automáticamente por [nginx] Reverse Proxy.

[worker_wrapper] Cola Consumer

Uno o más contenedores para consumir y gestionar trabajos desde la cola. El [worker_wrapper] Consumidor de Cola consulta periódicamente la [db] Base de Datos de Aplicaciones para detectar nuevos trabajos pendientes. Al encontrar un trabajo en estado PENDIENTE, el [worker_wrapper] Consumidor de Cola lo establece en estado EN COLA y comienza a procesarlo. A continuación, el contenedor establece una serie de metadatos en el objeto Trabajo en la [db] Base de Datos de Aplicaciones e inicia un nuevo contenedor temporal [qgis] Worker. Espera a que el contenedor [qgis] Worker finalice, obtiene los registros y los almacena en la [db] Base de Datos de Aplicaciones.

Por último, actualiza un conjunto de metadatos de otros Trabajos en la [db] Base de Datos basándose en el código de salida y en los registros del [qgis] Worker, y establece el estado del Trabajo en FINISHED o FAILED.

El contenedor ejecuta el mismo código Django utilizado en [app] QFieldCloud App.

Lee cómo funciona la cola del consumer [worker_wrapper] en la sección Cola de trabajos.

[qgis] Worker

El contenedor del Worker es el lugar real donde se ejecutan los Trabajos creados por la [app] QFieldCloud App. Cada contenedor Worker es creado dinámicamente por el [worker_wrapper] Cola del Consumer para ejecutar un único trabajo para un único proyecto y eliminado justo después. La ejecución típica de un Worker consiste en iniciar una aplicación QGIS cualquiera, descargar los archivos del proyecto, procesar los archivos del proyecto y volver a cargar los archivos procesados resultantes.

El contenedor [qgis] Worker obtiene variables de entorno, incluido un token temporal de autenticación QFieldCloud, del [worker_wrapper] Cola de Consumer, y le devuelve datos escribiendo registros en el STDERR y escribiendo archivos en el volumen compartido temporal, principalmente feedback.json.

Volúmenes

[cerbot_www]

Almacena los certificados SSL creados por [mkcert] Creador de certificados autofirmados o [certbot] Gestor de Letsencrypt.

[transformation_grids]

Contiene todos los grip de transformación disponibles, descargadas de https://cdn.proj.org/ y puestas a disposición de todos los Trabajos.

[static_volume]

Contiene todos los activos estáticos, como fuentes, CSS, JS o archivos de imagen.

[media_volume]

Aviso Obsoleto, puede ser eliminado en cualquier momento.

La ubicación por defecto para los archivos subidos por el usuario. No debe utilizarse nunca.

Servicios de desarrollo

Los siguientes contenedores sólo están disponibles para fines de desarrollo local y no deben utilizarse en producción, ya que estos servicios no están monitorizados, no tienen copia de seguridad y, en general, están diseñados para un uso crítico dentro del stack.

[minio] Almacenamiento de archivos

Almacenamiento local de objetos (tipo S3) utilizado para el desarrollo. Los datos se almacenan en 4 volúmenes [minio_data], ya que minio impone la replicación.

Debería sustituirse por un proveedor SaaS de almacenamiento de objetos similar a S3.

Si se está ejecutando minio, asegúrate de que el cortafuegos del host permite el puerto 8009, requerido por el servicio minio (o el puerto configurado con la variable de entorno MINIO_API_PORT).

[createbuckets] Crear Buckets de Minio

Contenedor de un solo shot para crear los buckets necesarios en el Almacenamiento de Objetos bajo [minio] Almacenamiento de Archivos.

[webdav] Almacenamiento de archivos alternativo

Almacenamiento WebDAV local utilizado para el desarrollo, utilizando el protocolo y las especificaciones WebDAV.

Los datos se almacenan en el volumen [webdav_data].

Se puede usar alternativamente en lugar del almacenamiento de archivos minio para almacenar archivos. Opcionalmente, se puede usar para almacenar solo archivos adjuntos.

Info

El almacenamiento webdav es opcional; no es un requisito para el correcto funcionamiento del sistema.

Si se utiliza, el servicio de almacenamiento webDAV debe reemplazarse por un servidor WebDAV adecuado, por ejemplo, NextCloud.

[db] Aplicación PostgreSQL

Servidor local de base de datos PostgreSQL para alojar los datos de la [app] QFieldCloud Aplicación. El esquema de la base de datos está totalmente gestionado por Django. El esquema no debe ser modificado por servicios externos.

Debería reemplazarse por una base de datos PostgreSQL adecuada con un proveedor SaaS PostGIS instalado.

[smtpdev] Servidor de correo

Servidor de correo local para gestionar el envío de correos electrónicos, como activación de registro, restablecimiento de contraseña o notificaciones.

Debería reemplazarse por un proveedor SaaS de correo electrónico adecuado que admita el protocolo SMTP.

[geodb] GeoDB PostgreSQL

¡!!! alerta Obsoleto, podría eliminarse en cualquier momento.

Almacena bases de datos PostGIS del usuario creadas dinámicamente.

[minio_data]

Almacena datos para el servicio [minio] S3.

[webdav_data]

Almacena datos para el servicio de almacenamiento [webdav] si está presente.

[postgres_data]

Almacena datos para [db] Aplicación PostgreSQL.

[smtp4dev_data]

Almacena datos para el servidor de correo [smtpdev].

[geodb_data]

!!! advertencia! Obsoleto, podría eliminarse en cualquier momento.

Almacena datos para [geodb] GeoDB PostgreSQL.

Cola de trabajos

QFieldCloud ejecuta operaciones muy pesadas para que la sincronización del proyecto funcione sin problemas para los usuarios. Por lo tanto, estas operaciones se ejecutan mediante los trabajos (jobs.md) que se ejecutan en segundo plano.

Aquí tenemos un diagrama de secuencia de las etapas que sigue cada ejecución de trabajo.

Algunos de los pasos se acortan intencionalmente para mayor claridad..

sequenceDiagram
    autonumber
    participant DB as QFieldCloud DB
    participant Queue as QFieldCloud Queue

    loop poll database
      Queue->>DB: select the oldest Job with `PENDING` status
      Queue->>DB: set the status of Job to `STARTED` status

      Queue->>DB: create a new temporary authentication token

      create participant Worker
      Queue->>Worker: create the worker and pass the authentication token

      note over Worker: job specific processing...

      destroy Worker
      Queue-xWorker: get worker's structured and free text logs and exit code

      Queue->>DB: set job's structured logs, free text logs and exit code

      alt Worker has zero exit status
        Queue->>DB: set the Job  status to `FINISHED`
      else Worker has non-zero exit status
        Queue->>DB: set the Job  status to `FAILED`
      end

      break when any of the steps above fails
          Queue-->DB: set the status Job to `FAILED`
      end
    end

Si bien algunos de los pasos aún están simplificados, este diagrama contiene mucha más información sobre el ciclo de vida de los atributos del trabajo.

sequenceDiagram
    autonumber

    participant DB as QFieldCloud DB
    participant Queue as QFieldCloud Queue

    loop [every few seconds]
      Queue->>DB: select the oldest job with `PENDING` status

      Queue->>DB: set the status of current job to `QUEUED`
      Queue->>DB: set the status of current job to `STARTED` and `started_at` to `now()`

      Queue->>DB: create a new temporary authentication token
      Queue->>DB: set `docker_started_at` to `now()`


      create participant Worker
      Queue->>Worker: - mount `transformation_grids` volume <br> - set shared data volume <br> - set the environment variable with the authentication token <br> - set the environment variables from secrets <br> - set the `pgservice` file from secrets <br><br> Create the worker
      activate Worker

      par run worker
        Worker->>API: Download files
        API->>Worker: Files downloaded

        note over Worker: job specific processing...

        Worker->>API: Upload files
        API->>Worker: Files uploaded

        deactivate Worker

      and wait for Worker to finish on Queue
        Queue->>DB: set `container_id` to the newly created Docker container id
        Queue->>Queue: wait until the Worker is finished or timeout reached
      end

      Queue->>DB: set `docker_finished_at` to `now()`


      destroy Worker
      Queue-xWorker: - get Worker's `stdout` logs <br> - get Worker's structured logs from the `feedback.json` in the shared volume <br> - get Worker's exit status code <br><br> Remove the container and cleanup all Job data

      Queue->>DB: set job's `output` and `feedback`

      alt [Worker has zero exit status]
        Queue->>DB: set the status of current job to `FINISHED` and `finished_at` to `now()`
      else [Worker has non-zero exit status]
        Queue->>DB: set the status of current job to `FAILED`
      end

      break when any of the steps above fails
          Queue-->DB: set the status of the current job to `FAILED`
      end

    end

    participant API as QFieldCloud App