Primeros pasos con las listas de tareas en cola

Aprende a usar las listas de tareas en cola y la API de imágenes de App Engine para cambiar el tamaño de las imágenes.

Las listas de tareas en cola ejecutan el código fuera de la interacción directa del usuario, lo cual permite que se realicen tareas en segundo plano. Esta guía se basa en el código de muestra usado en la guía Usa Cloud Storage, que almacena archivos en Cloud Storage. La guía actual extiende la muestra de Cloud Storage cuando se agrega una lista de tareas en cola para realizar tareas después de almacenar una imagen en Cloud Storage. Las tareas que se tienen que realizar en la lista de tareas en cola son las siguientes:

  1. Recupera el archivo de imagen que acabas de subir a Cloud Storage.
  2. Cambia el tamaño a una imagen en miniatura con la API de imágenes.
  3. Almacena la miniatura en Cloud Storage.

El entorno de ejecución de App Engine de Java 8 también admite las clases de manipulación de imágenes nativas de Java como AWT y Java2D.

Antes de comenzar

  1. Configura tu entorno de desarrollo y crea tu proyecto de App Engine.

  2. Esta guía usa la biblioteca Apache Commons IOUtils. Para incluir la biblioteca IOUtils en tu proyecto de App Engine, sigue estos pasos:

    Maven

    Agrega a tu pom.xml:

    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.5</version>
    </dependency>
    

    Gradle

    Agrega a tu build.gradle:

    compile group: 'commons-io', name: 'commons-io', version: '2.5'
    

Importa las bibliotecas

En el código de muestra proporcionado con esta guía, se usan las siguientes importaciones:

import com.google.appengine.api.images.Image;
import com.google.appengine.api.images.ImagesService;
import com.google.appengine.api.images.ImagesServiceFactory;
import com.google.appengine.api.images.Transform;
import org.apache.commons.io.IOUtils;

Crea una lista de tareas en cola

App Engine tiene una lista de tareas en cola default, sin embargo, puedes crear tu propia lista agregando una entrada en el queue.xml.

Para agregar colas, crea el archivo queue.xml en el directorio WEB-INF de tu proyecto de App Engine. Una lista de tareas en cola básica puede incluir solo un nombre y una tasa de ejecución:

<?xml version="1.0" encoding="UTF-8"?>
  <queue-entries>
    <queue>
      <name>resize-image</name>
      <rate>60/h</rate>
    </queue>
  </queue-entries>

Esta cola de ejemplo con el nombre resize-image define una tasa de ejecución de 60 veces por hora o una vez por minuto. Para ver la lista completa de opciones de cola, consulta la referencia de queue.xml.

Una lista de tareas en cola tiene dos componentes: el solicitante de tareas y el controlador de tareas. El solicitante agrega una tarea a la cola y la envía al controlador de tareas.

Agrega tareas a una cola

Para agregar una tarea a una cola, haz lo siguiente:

  1. Crea un objeto de lista de tareas en cola con QueueFactory.getQueue(), asegurándote de especificar el nombre de cola definido en la queue.xml:

    Queue imageResizeQueue; // Taskqueue queue
    
    @Override
    public void init() throws ServletException {
    
      // Setup Cloud Storage service
      gcsService =
          GcsServiceFactory.createGcsService(
              new RetryParams.Builder()
                  .initialRetryDelayMillis(10)
                  .retryMaxAttempts(10)
                  .totalRetryPeriodMillis(15000)
                  .build());
    
      // Initialize the queue object with the specific queue
      imageResizeQueue = QueueFactory.getQueue([QUEUE-NAME]);
    
      // Cloud SQL connection setup
      try {
        final String url = System.getProperty("cloudsql"); // Cloud SQL server URI
    
        try {
          conn = DriverManager.getConnection(url); // Connect to the database
    
          Statement createTable; // SQL statement
    
          // Batch SQL table creation commands
          createTable.addBatch(createContentTableSql);
          createTable.addBatch(createUserTableSql);
          createTable.addBatch(createImageTableSql);
          createTable.addBatch(createBlogPostImageTableSql);
          conn.createTable.executeBatch(); // Execute batch
    
        } catch (SQLException e) {
          throw new ServletException("Unable to connect to Cloud SQL", e);
        }
    
      } finally {
        // Nothing really to do here.
      }
    
    }
    
  2. Agrega tareas al objeto Queue. Como se observa en el código de muestra, imageResizeQueue.add() agrega una tarea al objeto imageResizeQueue:

    try {
      // Add a queued task to create a thumbnail of the uploaded image
      imageResizeQueue.add(
          TaskOptions.Builder.withUrl("/tasks/imageresize").param("filename", filename));
    }
    

    Especifica el URI del controlador de tareas con TaskOptions.Builder.withUrl() y cualquier otro parámetro enviado al controlador.

    En este ejemplo, el URI es /tasks/imageresize y el parámetro es una variable llamada filename que contiene el nombre del archivo de la imagen que se procesará.

Crea un controlador de tareas

Una vez que agregaste una tarea a la cola, el controlador de tareas asignado al URI /tasks/imageresize se ejecutará. Un controlador de tareas es un servlet de Java que intenta realizar la tarea hasta lograrlo.

En este ejemplo, el controlador de tareas realiza tres tareas:

  • Recupera la imagen especificada por el emisor desde Cloud Storage.

  • Transforma la imagen en este ejemplo en una imagen en miniatura con la API de App Engine Image.

  • Almacena la imagen transformada (imagen en miniatura) en Cloud Storage.

Para crear el controlador de tareas:

  1. Agrega una anotación que asigne el controlador al URI/tasks/imageresize:

     @WebServlet(name = "imageResize", description = "Task queue handler", urlPatterns = "/tasks/imageresize")
     public class imageResize extends HttpServlet {
    
       // Task handler functionality
    
     }
    
  2. Configura una conexión a Cloud Storage como está documentada en la guía Usa Cloud Storage y recupera la imagen desde Cloud Storage:

     public void init() throws ServletException {
    
      // initiate GcsService
      GcsService gcsService =
        GcsServiceFactory.createGcsService(
            new RetryParams.Builder()
                .initialRetryDelayMillis(10)
                .retryMaxAttempts(10)
                .totalRetryPeriodMillis(15000)
                .build());
    }
    
  3. Controla la solicitud entrante de la lista de tareas en cola con el nombre de archivo proporcionado para recuperar la imagen desde Cloud Storage:

    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
    
      String filename = req.getParameter("filename"); // Get the filename passed from the task requestor
      GcsFilename gcsFile = new GcsFilename(bucket, filename); // Create a valid Cloud Storage filename
    
      GcsInputChannel readChannel = gcsService.openPrefetchingReadChannel(gcsFile, 0, BUFFER_SIZE); // Read the file from Cloud Storage
    
  4. Usa el objeto ImagesService para cambiar el tamaño de la imagen:

    // Get an instance of the ImagesService we can use to transform images.
    ImagesService imagesService = ImagesServiceFactory.getImagesService();
    
    // Make an image directly from a byte array, and transform it.
    Image image =
        ImagesServiceFactory.makeImage(IOUtils.toByteArray(Channels.newInputStream(readChannel)));
    Transform resize = ImagesServiceFactory.makeResize(100, 50); // resize image to 100x50
    Image resizedImage = imagesService.applyTransform(resize, image);
    
    // Write the transformed image back to a Cloud Storage object.
    gcsService.createOrReplace(
        new GcsFilename(bucket, "thumbnail_" + filename),
        new GcsFileOptions.Builder().acl("public-read").build(),
        ByteBuffer.wrap(resizedImage.getImageData()));
    

    El fragmento anterior usa el método de la API de imágenes makeResize() para cambiar el tamaño de la imagen a una en miniatura. Para eso, lee la imagen desde Cloud Storage en InputChannel y la convierte en un ByteArray con IOUtils.toByteArray().

    Después de aplicar la transformación, la imagen nueva tiene la string thumbnail_ adjunta a su nombre de archivo, acceso público de lectura y escritura en Cloud Storage.

Asegura las URL del controlador de tareas

Debes proteger las tareas que realizan operaciones sensibles, como modificar datos, para que usuarios externos no puedan emitirlas de manera directa. Para ello, restringe el acceso a las tareas a los administradores de App Engine, lo cual no permite que los usuarios accedan a las URL de tareas. Ten en cuenta que esta restricción no aplica a los pedidos de tareas que provienen de la app de App Engine.

En este ejemplo, los controladores de tareas tienen URL en el archivo /tasks/. Para restringir el acceso al archivo /tasks/ a los administradores de App Engine, agrega lo siguiente a la web.xmlde los proyectos.

<security-constraint>
    <web-resource-collection>
        <web-resource-name>tasks</web-resource-name>
        <url-pattern>/tasks/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>admin</role-name>
    </auth-constraint>
</security-constraint>

Quita una sola tarea de una cola

Para quitar una sola tarea de una cola, usa deleteTask():

private void removeTask(Queue queue, String taskName) {
  queue.deleteTask(taskName); // remove a task from a queue
}

Quita todas las tareas de una cola

Para quitar todas las tareas de una cola, usa purge(). La eliminación definitiva de las todas las tareas en la cola puede demorar hasta un minuto.

private void purgeQueue(Queue queue) {
  queue.purge(); // remove all tasks from a queue
}

La eliminación definitiva de todas las tareas en una cola puede demorar hasta un minuto, por lo que deberías esperar unos segundos antes de agregar nuevas tareas a la cola.

Borra una lista de tareas en cola

Para borrar una lista de tareas en cola, quita la entrada de la queue.xml del archivo del proyecto y vuelve a implementarla.

Implementa en App Engine

Puedes implementar tu app en App Engine con Maven.

Ve al directorio raíz de tu proyecto y escribe:

mvn appengine:deploy

Una vez que Maven implementa tu app, escribe lo siguiente para abrir una pestaña del navegador web de forma automática en ella:

gcloud app browse

Pasos siguientes

En esta guía, se muestra cómo usar una lista de tareas en cola para crear una imagen en miniatura y almacenarla en Cloud Storage. Puede usarse con otros servicios de almacenamiento, como Cloud Datastore o Cloud SQL.

¿Te ha resultado útil esta página? Enviar comentarios:

Enviar comentarios sobre...

Entorno estándar de App Engine para Java