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

۱. مرور کلی

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

df20f5d0402b54b4.png

آنچه یاد خواهید گرفت

  • اجرای ابری
  • زمان‌بندی ابری
  • فضای ذخیره‌سازی ابری
  • فروشگاه ابری فایر استور

۲. تنظیمات و الزامات

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

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

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

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

شروع پوسته ابری

اگرچه می‌توان از راه دور و از طریق لپ‌تاپ، گوگل کلود را مدیریت کرد، اما در این آزمایشگاه کد، از گوگل کلود شل ، یک محیط خط فرمان که در فضای ابری اجرا می‌شود، استفاده خواهید کرد.

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

bce75f34b2c53987.png

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

f6ef2b5f13479f3a.png

این ماشین مجازی مجهز به تمام ابزارهای توسعه مورد نیاز شماست. این ماشین یک دایرکتوری خانگی دائمی ۵ گیگابایتی ارائه می‌دهد و روی فضای ابری گوگل اجرا می‌شود که عملکرد شبکه و احراز هویت را تا حد زیادی بهبود می‌بخشد. تمام کارهای شما در این آزمایشگاه را می‌توان به سادگی با یک مرورگر انجام داد.

۳. فعال کردن APIها

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

gcloud services enable cloudscheduler.googleapis.com

باید ببینید که عملیات با موفقیت به پایان رسیده است:

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

۴. کد را کپی کنید

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

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 تصویر کانتینر را تعریف می‌کند.

۵. کد را بررسی کنید

وابستگی‌ها

فایل 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 Storage وابسته هستیم. ما یک وابستگی به Cloud Firestore اعلام می‌کنیم تا متادیتای تصویری که قبلاً ذخیره کرده‌ایم را دریافت کنیم. Express یک چارچوب وب جاوا اسکریپت/نود است. Bluebird برای مدیریت promiseها استفاده می‌شود و imagemagick کتابخانه‌ای برای دستکاری تصاویر است.

داکرفایل

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 مورد نیاز کد خود را نصب می‌کنیم و کد node خود را با دستور npm start اجرا می‌کنیم.

ایندکس.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 کتابخانه‌ای برای مدیریت promiseهای جاوا اسکریپت است، Path برای مدیریت مسیر فایل‌ها و دایرکتوری‌ها استفاده می‌شود و سپس 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);
    }
});

در بالا، ساختار 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 تصویر را آپلود کنید.

ما ۴ تصویر آخر آپلود شده توسط کاربرانمان را از ابرداده‌های ذخیره شده در Cloud Firerstore بازیابی می‌کنیم. بررسی می‌کنیم که آیا مجموعه حاصل خالی است یا خیر، و سپس در شاخه else کد خود ادامه می‌دهیم.

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

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

ما قصد داریم هر یک از آن فایل‌ها را از سطل thumbnail دانلود کنیم، که نام آنها از یک متغیر محیطی که در زمان استقرار تنظیم کرده‌ایم، گرفته شده است:

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 برای ایجاد یک شبکه ۴x۴ از این تصاویر بندانگشتی استفاده خواهیم کرد. ما از کتابخانه Bluebird و پیاده‌سازی Promise آن برای تبدیل کد مبتنی بر فراخوانی به کدی سازگار async / await استفاده می‌کنیم، سپس روی promise که در حال ساخت کلاژ تصویر است، منتظر می‌مانیم:

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

در انتهای فایل منبع، دستورالعمل‌هایی داریم که اکسپرس را وادار می‌کند برنامه وب ما را روی پورت پیش‌فرض ۸۰۸۰ اجرا کند.

۶. به صورت محلی آزمایش کنید

قبل از انتشار در فضای ابری، کد را به صورت محلی آزمایش کنید تا از عملکرد آن مطمئن شوید.

داخل پوشه collage/nodejs ، وابستگی‌های npm را نصب کنید و سرور را راه‌اندازی کنید:

npm install; npm start

اگر همه چیز خوب پیش رفته باشد، باید سرور روی پورت ۸۰۸۰ شروع به کار کند:

Started collage service on port 8080

برای خروج از CTRL-C استفاده کنید.

۷. ساخت و استقرار در 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 Buildpacks تصویر کانتینر را برای شما بسازد.

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

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

همچنین توجه داشته باشید که استقرار مبتنی بر منبع از Artifact Registry برای ذخیره کانتینرهای ساخته شده استفاده می‌کند. Artifact Registry نسخه مدرن Google Container Registry است. اگر API از قبل در پروژه فعال نشده باشد، رابط خط فرمان (CLI) درخواست فعال کردن آن را می‌دهد و یک مخزن با نام cloud-run-source-deploy در منطقه‌ای که در آن مستقر می‌شوید، ایجاد می‌کند.

پرچم --no-allow-unauthenticated سرویس Cloud Run را به یک سرویس داخلی تبدیل می‌کند که فقط توسط حساب‌های سرویس خاص فعال می‌شود.

۸. تنظیم زمان‌بندی ابری

اکنون که سرویس 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

یک کار زمان‌بندی ابری ایجاد کنید که هر ۱ دقیقه اجرا شود:

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 اشاره می‌کند:

۳۵۱۱۹e۲۸c۱da۵۳f۳.png

۹. سرویس را آزمایش کنید

برای بررسی اینکه آیا تنظیمات به درستی کار می‌کنند، در بخش تصاویر thumbnails ، تصویر کلاژ (با نام collage.png ) را بررسی کنید. همچنین می‌توانید گزارش‌های سرویس را بررسی کنید:

۹۳۹۲۲۳۳۵a۳۸۴be۲e.png

۱۰. تمیز کردن (اختیاری)

اگر قصد ندارید با سایر آزمایشگاه‌های این مجموعه ادامه دهید، می‌توانید منابع را پاکسازی کنید تا در هزینه‌ها صرفه‌جویی کنید و در کل شهروند ابری خوبی باشید. می‌توانید منابع را به صورت جداگانه و به شرح زیر پاکسازی کنید.

سرویس را حذف کنید:

gcloud run services delete $SERVICE_NAME -q

حذف کار زمان‌بندی ابری:

gcloud scheduler jobs delete $SERVICE_NAME-job -q

روش دیگر، حذف کل پروژه است:

gcloud projects delete $GOOGLE_CLOUD_PROJECT

۱۱. تبریک می‌گویم!

تبریک! شما یک سرویس زمان‌بندی‌شده ایجاد کردید: به لطف Cloud Scheduler که هر دقیقه یک پیام را در یک موضوع Pub/Sub ارسال می‌کند، سرویس کلاژ Cloud Run شما فراخوانی شده و قادر است تصاویر را به هم الحاق کند تا تصویر نهایی را ایجاد کند.

آنچه ما پوشش داده‌ایم

  • اجرای ابری
  • زمان‌بندی ابری
  • فضای ذخیره‌سازی ابری
  • فروشگاه ابری فایر استور

مراحل بعدی