Pic-a-day: Lab 3 — کلاژی از جدیدترین تصاویر ایجاد کنید

1. بررسی اجمالی

در این آزمایشگاه کد، یک سرویس Cloud Run جدید، سرویس کلاژ ایجاد می‌کنید که توسط Cloud Scheduler در یک بازه زمانی منظم راه‌اندازی می‌شود. این سرویس آخرین تصاویر آپلود شده را واکشی می کند و کلاژی از آن تصاویر ایجاد می کند: لیست تصاویر اخیر را در Cloud Firestore پیدا می کند و سپس فایل های تصویر واقعی را از Cloud Storage دانلود می کند.

df20f5d0402b54b4.png

چیزی که یاد خواهید گرفت

  • Cloud Run
  • Cloud Scheduler
  • فضای ذخیره سازی ابری
  • Cloud Firestore

2. راه اندازی و الزامات

تنظیم محیط خود به خود

  1. به Google Cloud Console وارد شوید و یک پروژه جدید ایجاد کنید یا از یک موجود استفاده مجدد کنید. اگر قبلاً یک حساب Gmail یا Google Workspace ندارید، باید یک حساب ایجاد کنید .

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

  • نام پروژه نام نمایشی برای شرکت کنندگان این پروژه است. این یک رشته کاراکتری است که توسط API های Google استفاده نمی شود و می توانید هر زمان که بخواهید آن را به روز کنید.
  • شناسه پروژه باید در تمام پروژه‌های Google Cloud منحصربه‌فرد باشد و تغییرناپذیر باشد (پس از تنظیم نمی‌توان آن را تغییر داد). Cloud Console به طور خودکار یک رشته منحصر به فرد تولید می کند. معمولاً برای شما مهم نیست که چیست. در اکثر کدها، باید به شناسه پروژه ارجاع دهید (و معمولاً به عنوان PROJECT_ID شناخته می‌شود)، بنابراین اگر آن را دوست ندارید، یک نمونه تصادفی دیگر ایجاد کنید، یا می‌توانید شناسه پروژه را امتحان کنید و ببینید در دسترس است. سپس پس از ایجاد پروژه "یخ زده" می شود.
  • یک مقدار سوم وجود دارد، یک شماره پروژه که برخی از API ها از آن استفاده می کنند. در مورد هر سه این مقادیر در مستندات بیشتر بیاموزید.
  1. در مرحله بعد، برای استفاده از منابع Cloud/APIها، باید صورتحساب را در کنسول Cloud فعال کنید . اجرا کردن از طریق این کد لبه نباید هزینه زیادی داشته باشد، اگر اصلاً باشد. برای اینکه منابع را خاموش کنید تا بیش از این آموزش متحمل صورتحساب نشوید، دستورالعمل‌های «پاک‌سازی» را که در انتهای Codelab یافت می‌شود دنبال کنید. کاربران جدید Google Cloud واجد شرایط برنامه آزمایشی رایگان 300 دلاری هستند.

Cloud Shell را راه اندازی کنید

در حالی که Google Cloud را می توان از راه دور از لپ تاپ شما کار کرد، در این کد لبه از Google Cloud Shell استفاده خواهید کرد، یک محیط خط فرمان که در Cloud اجرا می شود.

از کنسول GCP روی نماد Cloud Shell در نوار ابزار بالا سمت راست کلیک کنید:

bce75f34b2c53987.png

تهیه و اتصال به محیط فقط چند لحظه طول می کشد. وقتی تمام شد، باید چیزی شبیه به این را ببینید:

f6ef2b5f13479f3a.png

این ماشین مجازی با تمام ابزارهای توسعه که شما نیاز دارید بارگذاری شده است. این یک فهرست اصلی 5 گیگابایتی دائمی را ارائه می دهد و در Google Cloud اجرا می شود و عملکرد و احراز هویت شبکه را تا حد زیادی افزایش می دهد. تمام کارهای شما در این آزمایشگاه به سادگی با یک مرورگر قابل انجام است.

3. API ها را فعال کنید

برای راه اندازی سرویس Cloud Run در یک بازه زمانی منظم به Cloud Scheduler نیاز دارید. مطمئن شوید که فعال است:

gcloud services enable cloudscheduler.googleapis.com

برای اتمام موفقیت آمیز باید عملیات را مشاهده کنید:

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

4. کد را شبیه سازی کنید

اگر قبلاً در آزمایشگاه کد قبلی نبوده اید، کد را شبیه سازی کنید:

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 وابستگی های کتابخانه را تعریف می کند
  • Dockerfile تصویر ظرف را تعریف می کند

5. کد را کاوش کنید

وابستگی ها

فایل package.json وابستگی های کتابخانه مورد نیاز را تعریف می کند:

{
  "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 Firestore اعلام می کنیم تا متادیتای تصویری را که قبلاً ذخیره کرده بودیم واکشی کنیم. Express یک چارچوب وب جاوا اسکریپت / Node است. 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" ]

ما از یک تصویر پایه Node 14 سبک استفاده می کنیم. ما در حال نصب کتابخانه imagemagick هستیم. سپس ماژول های 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');

ما به وابستگی های مختلف مورد نیاز برای اجرای برنامه خود نیاز داریم: Express چارچوب وب Node است که از آن استفاده خواهیم کرد، ImageMagick کتابخانه ای برای انجام دستکاری تصویر، Bluebird کتابخانه ای برای مدیریت وعده های جاوا اسکریپت، Path برای رسیدگی به مسیرهای فایل ها و دایرکتوری ها استفاده می شود. و سپس Storage و Firestore به ترتیب برای کار با Google Cloud Storage (سطل های تصاویر ما) و Cloud Firestore datastore هستند.

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

در بالا، ساختار Node handler خود را داریم: برنامه ما به درخواست‌های 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 آخرین عکس آپلود شده توسط کاربران خود را از ابرداده های ذخیره شده در Cloud Firerstore بازیابی می کنیم. بررسی می کنیم که آیا مجموعه به دست آمده خالی است یا نه، و سپس در شاخه else کد ما ادامه می دهیم.

بیایید لیستی از نام فایل ها را جمع آوری کنیم:

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 برای ایجاد یک شبکه 4×4 از آن تصاویر بند انگشتی استفاده می کنیم. ما از کتابخانه Bluebird و اجرای Promise آن برای تبدیل کد مبتنی بر تماس به کد 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");

از آنجایی که تصویر کلاژ به صورت محلی در پوشه موقت در دیسک ذخیره شده است، اکنون باید آن را در فضای ذخیره سازی ابری آپلود کنیم و سپس یک پاسخ موفق را برگردانیم (کد وضعیت 2xx):

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

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

اکنون زمان آن است که اسکریپت Node خود را به درخواست های دریافتی گوش دهد:

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 به صورت دستی، می‌توانید برای ساختن تصویر کانتینر با استفاده از Google Cloud Buildpacks به Cloud Run نیز تکیه کنید.

برای ساختن تصویر کانتینر دستور زیر را اجرا کنید:

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 به‌طور خودکار زبانی را که استفاده می‌کنید شناسایی می‌کند و وابستگی‌های کد را برای ایجاد یک تصویر ظرف آماده برای تولید، با استفاده از یک تصویر پایه امن که توسط Google مدیریت می‌شود، واکشی می‌کند. این Cloud Run را برای استفاده از Google Cloud Buildpacks برای ساخت تصویر کانتینر تعریف‌شده در Dockerfile علامت‌گذاری می‌کند.

همچنین توجه داشته باشید که استقرار مبتنی بر منبع از Artifact Registry برای ذخیره کانتینرهای ساخته شده استفاده می کند. Artifact Registry یک نسخه مدرن از Google Container Registry است. اگر API قبلاً در پروژه فعال نشده باشد، 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 Scheduler در Cloud Console بروید تا ببینید که تنظیم شده است و به آدرس اینترنتی سرویس 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 Firestore

مراحل بعدی