Pic-a-harian: Lab 3—Buat kolase foto terbaru

1. Ringkasan

Di codelab ini, Anda membuat layanan Cloud Run baru, layanan kolase, yang akan dipicu oleh Cloud Scheduler pada interval waktu yang teratur. Layanan ini mengambil gambar terbaru yang diupload dan membuat kolase gambar tersebut: menemukan daftar gambar terbaru di Cloud Firestore, lalu mendownload file gambar sebenarnya dari Cloud Storage.

df20f5d0402b54b4.png

Yang akan Anda pelajari

  • Cloud Run
  • Cloud Scheduler
  • Cloud Storage
  • Cloud Firestore

2. Penyiapan dan Persyaratan

Penyiapan lingkungan mandiri

  1. Login ke Google Cloud Console dan buat project baru atau gunakan kembali project yang sudah ada. Jika belum memiliki akun Gmail atau Google Workspace, Anda harus membuatnya.

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

  • Project name adalah nama tampilan untuk peserta project ini. String ini adalah string karakter yang tidak digunakan oleh Google API, dan Anda dapat memperbaruinya kapan saja.
  • Project ID harus unik di semua project Google Cloud dan tidak dapat diubah (tidak dapat diubah setelah ditetapkan). Cloud Console otomatis menghasilkan string unik; biasanya Anda tidak peduli dengan kata-katanya. Pada sebagian besar codelab, Anda harus mereferensikan Project ID (dan biasanya diidentifikasi sebagai PROJECT_ID). Jadi, jika Anda tidak menyukainya, buat ID acak lain, atau, Anda dapat mencoba sendiri dan melihat apakah tersedia. Kemudian file akan "dibekukan" setelah project dibuat.
  • Ada nilai ketiga, Nomor Project yang digunakan oleh beberapa API. Pelajari lebih lanjut ketiga nilai ini di dokumentasi.
  1. Selanjutnya, Anda harus mengaktifkan penagihan di Cloud Console untuk menggunakan API/resource Cloud. Menjalankan operasi dalam codelab ini seharusnya tidak memerlukan banyak biaya, bahkan mungkin tidak sama sekali. Untuk menonaktifkan resource agar tidak menimbulkan penagihan di luar tutorial ini, ikuti petunjuk "pembersihan" yang ada di akhir codelab. Pengguna baru Google Cloud memenuhi syarat untuk mengikuti program Uji Coba Gratis senilai $300 USD.

Mulai Cloud Shell

Meskipun Google Cloud dapat dioperasikan dari jarak jauh menggunakan laptop Anda, dalam codelab ini, Anda akan menggunakan Google Cloud Shell, lingkungan command line yang berjalan di Cloud.

Dari GCP Console, klik ikon Cloud Shell di toolbar kanan atas:

bce75f34b2c53987.png

Hanya perlu waktu beberapa saat untuk penyediaan dan terhubung ke lingkungan. Jika sudah selesai, Anda akan melihat tampilan seperti ini:

f6ef2b5f13479f3a.png

Mesin virtual ini berisi semua alat pengembangan yang Anda perlukan. Layanan ini menawarkan direktori beranda tetap sebesar 5 GB dan beroperasi di Google Cloud, sehingga sangat meningkatkan performa dan autentikasi jaringan. Semua pekerjaan Anda di lab ini dapat dilakukan hanya dengan browser.

3. Mengaktifkan API

Anda memerlukan Cloud Scheduler untuk memicu layanan Cloud Run pada interval reguler. Pastikan kebijakan ini diaktifkan:

gcloud services enable cloudscheduler.googleapis.com

Anda akan melihat operasi berhasil diselesaikan:

Operation "operations/acf.5c5ef4f6-f734-455d-b2f0-ee70b5a17322" finished successfully.

4. Meng-clone kode

Clone kode, jika Anda belum melakukannya di codelab sebelumnya:

git clone https://github.com/GoogleCloudPlatform/serverless-photosharing-workshop

Selanjutnya, Anda dapat membuka direktori yang berisi layanan:

cd serverless-photosharing-workshop/services/collage/nodejs

Anda akan memiliki tata letak file berikut untuk layanan:

services
 |
 ├── collage
      |
      ├── nodejs
           |
           ├── Dockerfile
           ├── index.js
           ├── package.json

Di dalam folder, Anda memiliki 3 file:

  • index.js berisi kode Node.js
  • package.json menentukan dependensi library
  • Dockerfile menentukan image container

5. Mempelajari kode

Dependensi

File package.json menentukan dependensi library yang diperlukan:

{
  "name": "collage_service",
  "version": "0.0.1",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "dependencies": {
    "bluebird": "^3.7.2",
    "express": "^4.17.1",
    "imagemagick": "^0.1.3",
    "@google-cloud/firestore": "^4.9.9",
    "@google-cloud/storage": "^5.8.3"
  }
}

Kami bergantung pada library Cloud Storage untuk membaca dan menyimpan file gambar dalam Cloud Storage. Kita mendeklarasikan dependensi pada Cloud Firestore untuk mengambil metadata gambar yang telah disimpan sebelumnya. Express adalah framework web JavaScript / Node. Bluebird digunakan untuk menangani promise, dan imagemagick adalah library untuk memanipulasi gambar.

Dockerfile

Dockerfile menentukan image container untuk aplikasi:

FROM node:14-slim

# installing Imagemagick
RUN set -ex; \
  apt-get -y update; \
  apt-get -y install imagemagick; \
  rm -rf /var/lib/apt/lists/*

WORKDIR /picadaily/services/collage
COPY package*.json ./
RUN npm install --production
COPY . .
CMD [ "npm", "start" ]

Kita menggunakan image dasar Node 14 ringan. Kita sedang menginstal library imagemagick. Kemudian kita menginstal modul NPM yang dibutuhkan oleh kode, dan menjalankan kode node dengan start npm.

index.js

Mari kita pelajari kode index.js lebih lanjut:

const express = require('express');
const imageMagick = require('imagemagick');
const Promise = require("bluebird");
const path = require('path');
const {Storage} = require('@google-cloud/storage');
const Firestore = require('@google-cloud/firestore');

Kita memerlukan berbagai dependensi yang diperlukan agar program kita dapat berjalan: Express adalah framework web Node yang akan kita gunakan, ImageMagick library untuk melakukan manipulasi gambar, Bluebird adalah library untuk menangani promise JavaScript, Path digunakan untuk menangani file dan jalur direktori, kemudian Storage dan Firestore berfungsi masing-masing dengan Google Cloud Storage (bucket gambar kami), dan datastore Cloud Firestore.

const app = express();

app.get('/', async (req, res) => {
    try {
        console.log('Collage request');

        /* ... */

    } catch (err) {
        console.log(`Error: creating the collage: ${err}`);
        console.error(err);
        res.status(500).send(err);
    }
});

Di atas, kita memiliki struktur pengendali Node: aplikasi kita merespons permintaan HTTP GET. Dan kita sedang melakukan sedikit penanganan {i> error<i} jika terjadi kesalahan. Sekarang, mari kita lihat apa yang ada di dalam struktur ini.

const thumbnailFiles = [];
const pictureStore = new Firestore().collection('pictures');
const snapshot = await pictureStore
    .where('thumbnail', '==', true)
    .orderBy('created', 'desc')
    .limit(4).get();

if (snapshot.empty) {
    console.log('Empty collection, no collage to make');
    res.status(204).send("No collage created.");
} else {

    /* ... */

}

Layanan kolase kami akan membutuhkan setidaknya empat gambar (yang thumbnail-nya telah dibuat), jadi pastikan untuk mengunggah 4 gambar terlebih dahulu.

Kami mengambil 4 gambar terbaru yang diupload oleh pengguna, dari metadata yang disimpan di Cloud Firerstore. Kita memeriksa apakah koleksi yang dihasilkan kosong atau tidak, lalu melanjutkan di cabang lain dari kode kita.

Mari kita kumpulkan daftar nama file:

snapshot.forEach(doc => {
    thumbnailFiles.push(doc.id);
});
console.log(`Picture file names: ${JSON.stringify(thumbnailFiles)}`);

Kita akan mendownload setiap file tersebut dari bucket thumbnail, yang namanya berasal dari variabel lingkungan yang telah ditetapkan pada waktu deployment:

const thumbBucket = storage.bucket(process.env.BUCKET_THUMBNAILS);

await Promise.all(thumbnailFiles.map(async fileName => {
    const filePath = path.resolve('/tmp', fileName);
    await thumbBucket.file(fileName).download({
        destination: filePath
    });
}));
console.log('Downloaded all thumbnails');

Setelah thumbnail terbaru diupload, kita akan menggunakan library ImageMagick untuk membuat grid 4 x 4 dari gambar thumbnail tersebut. Kita menggunakan library Bluebird dan implementasi Promise-nya untuk mengubah kode berbasis callback menjadi kode yang mendukung async / await, lalu kita menunggu promise yang akan membuat kolase gambar:

const collagePath = path.resolve('/tmp', 'collage.png');

const thumbnailPaths = thumbnailFiles.map(f => path.resolve('/tmp', f));
const convert = Promise.promisify(im.convert);
await convert([
    '(', ...thumbnailPaths.slice(0, 2), '+append', ')',
    '(', ...thumbnailPaths.slice(2), '+append', ')',
    '-size', '400x400', 'xc:none', '-background', 'none',  '-append',
    collagePath]);
console.log("Created local collage picture");

Karena gambar kolase telah disimpan ke disk secara lokal di folder sementara, sekarang kita perlu menguploadnya ke Cloud Storage, lalu menampilkan respons yang berhasil (kode status 2xx):

await thumbBucket.upload(collagePath);
console.log("Uploaded collage to Cloud Storage bucket ${process.env.BUCKET_THUMBNAILS}");

res.status(204).send("Collage created.");

Sekarang saatnya membuat skrip Node kita memproses permintaan yang masuk:

const PORT = process.env.PORT || 8080;

app.listen(PORT, () => {
    console.log(`Started collage service on port ${PORT}`);
});

Di akhir file sumber, kita memiliki petunjuk agar Express benar-benar memulai aplikasi web pada port default 8080.

6. Menguji secara lokal

Uji kode secara lokal untuk memastikan kode berfungsi sebelum di-deploy ke cloud.

Di dalam folder collage/nodejs, instal dependensi npm dan mulai server:

npm install; npm start

Jika semuanya berjalan dengan baik, server akan dimulai pada port 8080:

Started collage service on port 8080

Gunakan CTRL-C untuk keluar.

7. Membangun dan men-deploy ke Cloud Run

Sebelum men-deploy ke Cloud Run, tetapkan region Cloud Run ke salah satu region dan platform yang didukung ke managed:

gcloud config set run/region europe-west1
gcloud config set run/platform managed

Anda dapat memeriksa apakah konfigurasi telah disetel:

gcloud config list

...
[run]
platform = managed
region = europe-west1

Daripada mem-build dan memublikasikan image container menggunakan Cloud Build secara manual, Anda juga dapat mengandalkan Cloud Run untuk membangun image container tersebut menggunakan Google Cloud Buildpacks.

Jalankan perintah berikut untuk membangun image container:

BUCKET_THUMBNAILS=thumbnails-$GOOGLE_CLOUD_PROJECT
SERVICE_NAME=collage-service
gcloud run deploy $SERVICE_NAME \
    --source . \
    --no-allow-unauthenticated \
    --update-env-vars BUCKET_THUMBNAILS=$BUCKET_THUMBNAILS

Perhatikan flag –-source. Ini adalah deployment berbasis sumber di Cloud Run. Jika Dockerfile ada di direktori kode sumber, kode sumber yang diupload akan dibuat menggunakan Dockerfile tersebut. Jika tidak ada Dockerfile di direktori kode sumber, buildpack Google Cloud akan otomatis mendeteksi bahasa yang Anda gunakan dan mengambil dependensi kode untuk membuat image container siap produksi, menggunakan image dasar aman yang dikelola oleh Google. Tindakan ini menandai Cloud Run untuk menggunakan Google Cloud Buildpacks guna membangun image container yang ditentukan di Dockerfile.

Perhatikan juga bahwa deployment berbasis sumber menggunakan Artifact Registry untuk menyimpan container yang dibangun. Artifact Registry adalah versi modern dari Google Container Registry. CLI akan meminta untuk mengaktifkan API jika API belum diaktifkan dalam project dan akan membuat repositori dengan nama cloud-run-source-deploy di region tempat Anda men-deploy.

Tanda --no-allow-unauthenticated menjadikan layanan Cloud Run sebagai layanan internal yang hanya akan dipicu oleh akun layanan tertentu.

8. Menyiapkan Cloud Scheduler

Setelah layanan Cloud Run siap dan di-deploy, saatnya membuat jadwal rutin untuk memanggil layanan setiap menit.

Buat akun layanan:

SERVICE_ACCOUNT=collage-scheduler-sa
gcloud iam service-accounts create $SERVICE_ACCOUNT \
   --display-name "Collage Scheduler Service Account"

Beri akun layanan izin untuk memanggil layanan Cloud Run:

gcloud run services add-iam-policy-binding $SERVICE_NAME \
   --member=serviceAccount:$SERVICE_ACCOUNT@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com \
   --role=roles/run.invoker

Buat tugas Cloud Scheduler untuk dijalankan setiap 1 menit:

SERVICE_URL=$(gcloud run services describe $SERVICE_NAME --format 'value(status.url)')
gcloud scheduler jobs create http $SERVICE_NAME-job --schedule "* * * * *" \
   --http-method=GET \
   --location=europe-west1 \
   --uri=$SERVICE_URL \
   --oidc-service-account-email=$SERVICE_ACCOUNT@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com \
   --oidc-token-audience=$SERVICE_URL

Anda dapat membuka bagian Cloud Scheduler di Cloud Console untuk melihat bahwa Cloud Scheduler sedang disiapkan dan mengarah ke URL layanan Cloud Run:

35119e28c1da53f3.pngS

9. Menguji layanan

Untuk menguji apakah penyiapan berhasil, lihat bucket thumbnails untuk mencari gambar kolase (disebut collage.png). Anda juga dapat memeriksa log layanan:

93922335a384be2e.pngS

10. Pembersihan (Opsional)

Jika tidak ingin melanjutkan lab lain dalam seri ini, Anda dapat menghapus resource untuk menghemat biaya dan menjadi cloud citizen yang baik secara keseluruhan. Anda dapat membersihkan resource satu per satu seperti berikut.

Hapus layanan:

gcloud run services delete $SERVICE_NAME -q

Hapus tugas Cloud Scheduler:

gcloud scheduler jobs delete $SERVICE_NAME-job -q

Atau, Anda dapat menghapus seluruh project:

gcloud projects delete $GOOGLE_CLOUD_PROJECT

11. Selamat!

Selamat! Anda telah membuat layanan terjadwal: berkat Cloud Scheduler, yang mengirim pesan setiap menit pada topik Pub/Sub, layanan kolase Cloud Run Anda dipanggil dan dapat menambahkan gambar secara bersamaan untuk membuat gambar yang dihasilkan.

Yang telah kita bahas

  • Cloud Run
  • Cloud Scheduler
  • Cloud Storage
  • Cloud Firestore

Langkah Berikutnya