Memulai: Antrean Tugas

Pelajari cara menggunakan antrean tugas dan App Engine Image API untuk mengubah ukuran image.

Antrean tugas menjalankan kode di luar interaksi pengguna langsung, sehingga tugas terjadi di latar belakang. Panduan ini menggunakan Antrean Tugas untuk melakukan tugas setelah menambahkan image ke Cloud Storage. Tugas yang akan dilakukan di Antrean Tugas adalah:

  1. Mengambil file image yang baru saja diupload ke Cloud Storage.
  2. Mengubah ukuran menjadi image thumbnail menggunakan Image API.
  3. Menyimpan thumbnail yang dihasilkan di Cloud Storage.

Runtime App Engine Java 8 juga mendukung class manipulasi gambar image Java seperti AWT dan Java2D.

Sebelum memulai

  1. Mengonfigurasi lingkungan pengembangan dan membuat project App Engine.

  2. Panduan ini menggunakan library Apache Commons IOUtils. Untuk menyertakan library IOUtils ke project App Engine Anda:

    Tambahkan ke pom.xml:

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

Mengimpor library

Kode contoh yang diberikan pada panduan ini menggunakan impor berikut:

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;

Membuat antrean tugas

Meskipun App Engine menyediakan antrean tugas default, Anda dapat membuat antrean tugas yang berbeda untuk jenis pekerjaan yang berbeda. Misalnya, Anda dapat membuat satu antrean tugas untuk mengubah ukuran gambar dan satu lagi untuk memperbarui database aplikasi Anda.

Untuk menambahkan antrean, buat file queue.xml di direktori WEB-INF project App Engine Anda. Antrean Tugas harus menentukan nama dan rasio eksekusi:

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

Contoh antrean ini, yang bernama resize-image, menentukan laju eksekusi 60 kali per jam, atau satu menit sekali. Untuk melihat opsi antrean daftar lengkap, lihat referensi queue.xml.

Antrean Tugas memiliki dua komponen, pemohon tugas dan pengendali tugas. Pemohon menambahkan tugas ke antrean dan mengirimkannya ke pengendali tugas.

Menambahkan tugas ke antrean

Untuk menambahkan tugas ke antrean:

  1. Buat objek antrean tugas menggunakan QueueFactory.getQueue(), pastikan Anda menentukan nama antrean yang ditentukan di 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. Tambahkan tugas ke objek Queue. Seperti yang ditunjukkan dalam contoh kode, imageResizeQueue.add() menambahkan tugas ke objek imageResizeQueue:

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

    Tentukan URI pengendali tugas menggunakan TaskOptions.Builder.withUrl(), beserta dan parameter apa pun yang dikirim ke pengendali.

    Dalam contoh ini, URI-nya adalah /tasks/imageresize dan parameternya adalah variabel bernama filename, yang berisi nama file image yang akan diproses.

Membuat pengendali tugas

Setelah Anda menambahkan tugas ke antrean, pengendali tugas yang dipetakan ke URI /tasks/imageresize akan berjalan. Pengendali tugas adalah Java Servlet yang mencoba melakukan tugas sampai berhasil.

Dalam contoh ini, pengendali tugas melakukan tiga tugas:

  • Mengambil image yang ditentukan oleh pemanggil dari Cloud Storage.

  • Mengubah image menggunakan App Engine Image API, dalam contoh ini, menjadi image thumbnail.

  • Menyimpan image yang ditransformasi (thumbnail) di Cloud Storage.

Untuk membuat pengendali tugas:

  1. Tambahkan anotasi yang memetakan pengendali ke URI /tasks/imageresize:

     @WebServlet(name = "imageResize", description = "Task queue handler", urlPatterns = "/tasks/imageresize")
     public class imageResize extends HttpServlet {
    
       // Task handler functionality
    
     }
    
  2. Siapkan koneksi ke Cloud Storage seperti yang didokumentasikan dalam panduan Menggunakan Cloud Storage dan ambil image dari Cloud Storage:

     public void init() throws ServletException {
    
      // initiate GcsService
      GcsService gcsService =
        GcsServiceFactory.createGcsService(
            new RetryParams.Builder()
                .initialRetryDelayMillis(10)
                .retryMaxAttempts(10)
                .totalRetryPeriodMillis(15000)
                .build());
    }
    
  3. Tangani permintaan Antrean Tugas yang masuk, menggunakan nama file yang disediakan untuk mengambil image dari 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. Gunakan objek ImagesService untuk melakukan pengubahan ukuran gambar:

    // 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()));
    

    Cuplikan di atas menggunakan metode makeResize() Image API untuk mengubah ukuran image menjadi thumbnail. Untuk melakukannya, aplikasi membaca image dari Cloud Storage menjadi InputChannel dan mengonversinya menjadi ByteArray menggunakan IOUtils.toByteArray().

    Setelah menerapkan transformasi, image baru memiliki string thumbnail_ yang ditambahkan ke nama filenya, izin ditetapkan agar dapat dibaca secara publik dan ditulis ke Cloud Storage.

Mengamankan URL pengendali tugas

Anda harus mengamankan tugas-tugas yang melakukan operasi sensitif seperti mengubah data sehingga pengguna eksternal tidak dapat memanggilnya secara langsung. Anda dapat melakukannya dengan membatasi akses tugas ke administrator App Engine, yang mencegah pengguna mengakses URL tugas. Perhatikan bahwa pembatasan ini tidak berlaku untuk permintaan tugas yang berasal dari aplikasi App Engine Anda.

Dalam contoh saat ini, pengendali tugas memiliki URL di folder /tasks/. Untuk membatasi akses ke folder /tasks/ bagi administrator App Engine, tambahkan hal berikut ke web.xml project.

<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>

Menghapus satu tugas dari antrean

Untuk menghapus satu tugas dari antrean, gunakan deleteTask():

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

Menghapus semua tugas dari antrean

Untuk menghapus semua tugas dari antrean, gunakan purge(). Pembersihan permanen bisa memakan waktu hingga satu menit untuk menghapus semua tugas dalam antrean.

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

Diperlukan waktu satu menit untuk menghapus semua tugas dari antrean, jadi Anda harus menunggu beberapa detik sebelum menambahkan tugas baru ke antrean.

Menghapus antrean tugas

Untuk menghapus antrean tugas, hapus entri dari file queue.xml project dan deploy ulang.

Men-deploy ke App Engine

Anda dapat men-deploy aplikasi ke App Engine menggunakan Maven.

Buka direktori root project Anda dan ketik:

mvn package appengine:deploy -Dapp.deploy.projectId=PROJECT_ID

Ganti PROJECT_ID dengan ID project Google Cloud Anda. Jika file pom.xml sudah menentukan ID project, Anda tidak perlu menyertakan properti -Dapp.deploy.projectId dalam perintah yang dijalankan.

Setelah Maven men-deploy aplikasi Anda, buka tab browser web secara otomatis di aplikasi baru dengan mengetik:

gcloud app browse

Langkah selanjutnya

Panduan ini menunjukkan cara menggunakan antrean tugas untuk membuat thumbnail gambar dan menyimpannya di Cloud Storage. Data ini dapat digunakan dengan layanan penyimpanan lain seperti Cloud Datastore atau Cloud SQL.