รูปภาพรายวัน: ห้องทดลอง 3 - สร้างภาพต่อกันจากรูปภาพล่าสุด

1. ภาพรวม

ใน Code Lab นี้ คุณสร้างบริการ Cloud Run ซึ่งเป็นบริการภาพต่อกันที่ Cloud Scheduler จะทริกเกอร์ในช่วงเวลาที่สม่ำเสมอ บริการจะดึงรูปภาพล่าสุดที่อัปโหลดและสร้างภาพคอลลาจของรูปภาพเหล่านั้น โดยจะค้นหารายการรูปภาพล่าสุดใน Cloud Firestore จากนั้นดาวน์โหลดไฟล์รูปภาพจริงจาก Cloud Storage

df20f5d0402b54b4.png

สิ่งที่คุณจะได้เรียนรู้

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

2. การตั้งค่าและข้อกำหนด

การตั้งค่าสภาพแวดล้อมตามเวลาที่สะดวก

  1. ลงชื่อเข้าใช้ Google Cloud Console และสร้างโปรเจ็กต์ใหม่หรือใช้โปรเจ็กต์ที่มีอยู่ซ้ำ หากยังไม่มีบัญชี Gmail หรือ Google Workspace คุณต้องสร้างบัญชี

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

  • ชื่อโครงการคือชื่อที่แสดงของผู้เข้าร่วมโปรเจ็กต์นี้ เป็นสตริงอักขระที่ Google APIs ไม่ได้ใช้และคุณอัปเดตได้ทุกเมื่อ
  • รหัสโปรเจ็กต์ต้องไม่ซ้ำกันในโปรเจ็กต์ Google Cloud ทั้งหมดและจะเปลี่ยนแปลงไม่ได้ (เปลี่ยนแปลงไม่ได้หลังจากตั้งค่าแล้ว) Cloud Console จะสร้างสตริงที่ไม่ซ้ำกันโดยอัตโนมัติ ปกติแล้วคุณไม่สนว่าอะไรเป็นอะไร ใน Codelab ส่วนใหญ่ คุณจะต้องอ้างอิงรหัสโปรเจ็กต์ (ซึ่งปกติระบุไว้ว่าเป็น PROJECT_ID) ดังนั้นหากไม่ชอบ ให้สร้างรหัสแบบสุ่มขึ้นมาอีกรหัสหนึ่ง หรือคุณจะลองใช้รหัสโปรเจ็กต์ของคุณเองแล้วดูว่ารหัสโปรเจ็กต์พร้อมใช้งานหรือไม่ แล้วก็ "แช่แข็ง" หลังจากสร้างโปรเจ็กต์แล้ว
  • มีค่าที่ 3 คือหมายเลขโปรเจ็กต์ที่ API บางตัวใช้ ดูข้อมูลเพิ่มเติมเกี่ยวกับค่าทั้ง 3 ค่าเหล่านี้ในเอกสารประกอบ
  1. ถัดไป คุณจะต้องเปิดใช้การเรียกเก็บเงินใน Cloud Console เพื่อใช้ทรัพยากร/API ของระบบคลาวด์ การใช้งาน Codelab นี้น่าจะไม่มีค่าใช้จ่ายใดๆ หากมี หากต้องการปิดทรัพยากรเพื่อไม่ให้มีการเรียกเก็บเงินนอกเหนือจากบทแนะนำนี้ ให้ทำตาม "การล้าง" ดูได้ที่ตอนท้ายของ Codelab ผู้ใช้ใหม่ของ Google Cloud จะมีสิทธิ์เข้าร่วมโปรแกรมทดลองใช้ฟรี$300 USD

เริ่มต้น Cloud Shell

แม้ว่าคุณจะดำเนินการ Google Cloud จากระยะไกลได้จากแล็ปท็อป แต่คุณจะใช้ Google Cloud Shell ซึ่งเป็นสภาพแวดล้อมแบบบรรทัดคำสั่งที่ทำงานในระบบคลาวด์ใน Codelab นี้

จากคอนโซล GCP ให้คลิกไอคอน Cloud Shell บนแถบเครื่องมือด้านขวาบนดังนี้

bce75f34b2c53987.png

การจัดสรรและเชื่อมต่อกับสภาพแวดล้อมนี้ควรใช้เวลาเพียงครู่เดียว เมื่อเสร็จแล้ว คุณจะเห็นข้อมูลต่อไปนี้

f6ef2b5f13479f3a.png

เครื่องเสมือนนี้เต็มไปด้วยเครื่องมือการพัฒนาทั้งหมดที่คุณต้องการ โดยมีไดเรกทอรีหลักขนาด 5 GB ที่ใช้งานได้ต่อเนื่องและทำงานบน Google Cloud ซึ่งช่วยเพิ่มประสิทธิภาพของเครือข่ายและการตรวจสอบสิทธิ์ได้อย่างมาก งานทั้งหมดใน Lab นี้สามารถทำได้โดยใช้เบราว์เซอร์

3. เปิดใช้ API

คุณจะต้องใช้ Cloud Scheduler เพื่อทริกเกอร์บริการ Cloud Run ในช่วงเวลาที่สม่ำเสมอ ตรวจสอบว่าได้เปิดใช้แล้ว โดยทำดังนี้

gcloud services enable cloudscheduler.googleapis.com

คุณควรเห็นการดำเนินการที่เสร็จสิ้นเรียบร้อยแล้ว

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

4. โคลนโค้ด

โคลนโค้ดหากยังไม่ได้ทำใน Code Lab ก่อนหน้านี้:

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

จากนั้นคุณจะไปที่ไดเรกทอรีที่มีบริการได้โดยทำดังนี้

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

คุณจะมีการจัดวางไฟล์ดังต่อไปนี้สำหรับบริการ:

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

ภายในโฟลเดอร์จะมี 3 ไฟล์ดังนี้

  • index.js มีโค้ด Node.js
  • package.json กำหนดทรัพยากร Dependency ของไลบรารี
  • Dockerfile กำหนดอิมเมจคอนเทนเนอร์

5. สำรวจโค้ด

การขึ้นต่อกัน

ไฟล์ package.json จะกำหนดทรัพยากร Dependency ของไลบรารีที่ต้องการดังนี้

{
  "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"
  }
}

เราใช้ไลบรารี Cloud Storage เพื่ออ่านและบันทึกไฟล์ภาพภายใน Cloud Storage เราประกาศการพึ่งพา Cloud Firestore เพื่อดึงข้อมูลเมตาของรูปภาพที่จัดเก็บไว้ก่อนหน้านี้ Express เป็นเฟรมเวิร์กเว็บ JavaScript / โหนด Bluebird ใช้ในการจัดการคำสัญญา ส่วน Imagemagick เป็นไลบรารีสำหรับการควบคุมรูปภาพ

Dockerfile

Dockerfile กำหนดอิมเมจคอนเทนเนอร์สำหรับแอปพลิเคชัน:

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

เราใช้อิมเมจฐาน 14 แบบสว่าง เรากำลังติดตั้งไลบรารีรูปภาพ จากนั้นเราจะติดตั้งโมดูล NPM ที่จำเป็นสำหรับโค้ดของเรา และเราเรียกใช้โค้ดโหนดของเราด้วยการเริ่มต้น npm

index.js

มาดูรายละเอียดเกี่ยวกับโค้ด index.js กัน

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');

เราต้องการทรัพยากร Dependency ต่างๆ ที่จำเป็นต่อการเรียกใช้โปรแกรม ได้แก่ Express คือเฟรมเวิร์กเว็บของโหนดที่เราจะใช้, ImageMagick ไลบรารีสำหรับจัดการรูปภาพ, Bluebird เป็นไลบรารีสำหรับจัดการคำขอของ JavaScript, เส้นทางใช้เพื่อจัดการกับไฟล์และเส้นทางไดเรกทอรี จากนั้น Storage และ Firestore สำหรับการทำงานร่วมกับ Google Cloud Storage (ที่เก็บข้อมูลรูปภาพของเรา) และพื้นที่เก็บข้อมูล 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);
    }
});

ด้านบนเรามีโครงสร้างของเครื่องจัดการโหนด โดยแอปของเราตอบสนองต่อคำขอ HTTP GET และเราจะทำการจัดการข้อผิดพลาดเล็กๆ น้อยๆ ในกรณีที่เกิดข้อผิดพลาด มาดูกันว่าในโครงสร้างนี้มีอะไรบ้าง

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 {

    /* ... */

}

บริการภาพคอลลาจของเราต้องมีรูปภาพอย่างน้อย 4 ภาพ (ที่ระบบสร้างภาพขนาดย่อ) ดังนั้นโปรดอัปโหลดรูปภาพ 4 ภาพก่อน

เราเรียกภาพล่าสุด 4 ภาพที่ผู้ใช้ของเราอัปโหลดจากข้อมูลเมตาที่จัดเก็บใน Cloud Firerstore ตรวจสอบว่าคอลเล็กชันที่ได้ว่างเปล่าหรือไม่ จากนั้นจึงดําเนินการต่อในโค้ดของเราส่วนอื่น

เรามารวบรวมรายชื่อชื่อไฟล์กัน

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

เราจะดาวน์โหลดไฟล์เหล่านั้นแต่ละไฟล์จากที่เก็บข้อมูลภาพขนาดย่อ ซึ่งได้ชื่อมาจากตัวแปรสภาพแวดล้อมที่เรากำหนดไว้ตอนติดตั้งใช้งาน

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');

หลังจากอัปโหลดภาพขนาดย่อล่าสุดแล้ว เราจะใช้ไลบรารี ImageMagick เพื่อสร้างตาราง 4x4 สำหรับภาพขนาดย่อเหล่านั้น เราใช้ไลบรารี Bluebird และการใช้งาน Promise เพื่อเปลี่ยนโค้ดที่มาจาก Callback ให้เป็นโค้ด friendly async / await จากนั้นเราจะให้คำมั่นสัญญาว่าจะสร้างภาพต่อกันดังนี้

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");

เนื่องจากระบบได้บันทึกภาพคอลลาจไปยังดิสก์ในโฟลเดอร์ชั่วคราวภายในเครื่องแล้ว เราจึงต้องอัปโหลดไปยัง Cloud Storage แล้วส่งการตอบกลับที่สำเร็จ (รหัสสถานะ 2xx):

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

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

ตอนนี้ถึงเวลาทำให้สคริปต์โหนดของเราฟังคำขอที่เข้ามาแล้ว:

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

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

ในตอนท้ายของไฟล์ต้นฉบับ เรามีคำแนะนำเพื่อให้ Express เริ่มต้นเว็บแอปพลิเคชันของเราบนพอร์ตเริ่มต้น 8080

6. ทดสอบในเครื่อง

ทดสอบโค้ดภายในเครื่องเพื่อให้แน่ใจว่าโค้ดใช้งานได้ก่อนทำให้ใช้งานได้บนระบบคลาวด์

ภายในโฟลเดอร์ collage/nodejs ให้ติดตั้งการอ้างอิง npm และเริ่มต้นเซิร์ฟเวอร์:

npm install; npm start

หากทุกอย่างเป็นไปอย่างถูกต้อง เซิร์ฟเวอร์ควรเริ่มที่พอร์ต 8080:

Started collage service on port 8080

ใช้ CTRL-C เพื่อออก

7. สร้างและทำให้ใช้งานได้กับ Cloud Run

ก่อนทำให้ใช้งานได้กับ Cloud Run ให้ตั้งค่าภูมิภาค Cloud Run เป็นภูมิภาคและแพลตฟอร์มที่รองรับเป็น managed ดังนี้

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

คุณจะตรวจสอบได้ว่ามีการกำหนดค่าโดยทำดังนี้

gcloud config list

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

แทนที่จะสร้างและเผยแพร่อิมเมจคอนเทนเนอร์โดยใช้ Cloud Build ด้วยตนเอง คุณยังใช้ Cloud Run สร้างอิมเมจคอนเทนเนอร์ให้คุณโดยใช้ Google Cloud Buildpack ได้ด้วย

เรียกใช้คำสั่งต่อไปนี้เพื่อสร้างอิมเมจคอนเทนเนอร์

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

จดบันทึก –-source นี่คือการทำให้ใช้งานได้ตามแหล่งที่มา ใน Cloud Run หากมี Dockerfile อยู่ในไดเรกทอรีซอร์สโค้ด ซอร์สโค้ดที่อัปโหลดจะสร้างโดยใช้ Dockerfile นั้น หากไม่มี Dockerfile ในไดเรกทอรีซอร์สโค้ด Google Cloud Buildpacks จะตรวจหาภาษาที่คุณใช้อยู่โดยอัตโนมัติและดึงทรัพยากร Dependency ของโค้ดเพื่อสร้างอิมเมจคอนเทนเนอร์ที่พร้อมใช้งานจริง โดยใช้อิมเมจฐานที่ปลอดภัยที่จัดการโดย Google การดำเนินการนี้จะแจ้ง Cloud Run ให้ใช้ Google Cloud Buildpack เพื่อสร้างอิมเมจคอนเทนเนอร์ที่กำหนดไว้ใน Dockerfile

โปรดทราบด้วยว่าการติดตั้งใช้งานตามซอร์สจะใช้ Artifact Registry เพื่อจัดเก็บคอนเทนเนอร์ที่สร้างขึ้น Artifact Registry คือ Google Container Registry เวอร์ชันใหม่ CLI จะแจ้งให้เปิดใช้ API หากยังไม่ได้เปิดใช้ในโปรเจ็กต์ และจะสร้างที่เก็บชื่อ cloud-run-source-deploy ในภูมิภาคที่คุณกำลังทำให้ใช้งานได้

แฟล็ก --no-allow-unauthenticated ทำให้บริการ Cloud Run เป็นบริการภายในที่จะทริกเกอร์โดยบัญชีบริการบางรายการเท่านั้น

8. ตั้งค่า Cloud Scheduler

ตอนนี้บริการ Cloud Run พร้อมติดตั้งใช้งานแล้ว ก็ถึงเวลาสร้างกำหนดการปกติเพื่อเรียกใช้บริการทุกนาที

สร้างบัญชีบริการได้ดังนี้

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

ให้สิทธิ์บัญชีบริการเพื่อเรียกใช้บริการ 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

สร้างงาน Cloud Scheduler ที่จะดำเนินการทุก 1 นาที:

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

คุณอาจไปที่ส่วนเครื่องจัดตารางเวลาของ Cloud ใน Cloud Console เพื่อดูว่ามีการตั้งค่าและชี้ไปยัง URL ของบริการ Cloud Run แล้วดังนี้

35119e28c1da53f3.png

9. ทดสอบบริการ

หากต้องการทดสอบว่าการตั้งค่าใช้งานได้หรือไม่ ให้ตรวจสอบในที่เก็บข้อมูล thumbnails สำหรับรูปภาพภาพต่อกัน (ชื่อว่า collage.png) คุณยังตรวจสอบบันทึกของบริการได้โดยทำดังนี้

93922335a384be2e.png

10. ล้างข้อมูล (ไม่บังคับ)

หากไม่ต้องการใช้ห้องทดลองอื่นๆ ในชุดนี้ต่อ คุณสามารถล้างทรัพยากรเพื่อประหยัดต้นทุนและเป็นพลเมืองระบบคลาวด์ที่ดีโดยรวม คุณสามารถล้างทรัพยากรแต่ละรายการได้ดังนี้

ลบบริการ

gcloud run services delete $SERVICE_NAME -q

ลบงาน Cloud Scheduler:

gcloud scheduler jobs delete $SERVICE_NAME-job -q

หรือจะลบทั้งโปรเจ็กต์ก็ได้ โดยทำดังนี้

gcloud projects delete $GOOGLE_CLOUD_PROJECT

11. ยินดีด้วย

ยินดีด้วย คุณได้สร้างบริการที่กำหนดเวลาไว้ โดยอาศัย Cloud Scheduler ที่พุชข้อความทุกๆ นาทีในหัวข้อ Pub/Sub ทำให้บริการภาพคอลลาจของ Cloud Run เรียกใช้และสามารถเพิ่มรูปภาพเข้าด้วยกันเพื่อสร้างรูปภาพผลลัพธ์

หัวข้อที่ครอบคลุม

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

ขั้นตอนถัดไป