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

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



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

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

این ماشین مجازی مجهز به تمام ابزارهای توسعه مورد نیاز شماست. این ماشین یک دایرکتوری خانگی دائمی ۵ گیگابایتی ارائه میدهد و روی فضای ابری گوگل اجرا میشود که عملکرد شبکه و احراز هویت را تا حد زیادی بهبود میبخشد. تمام کارهای شما در این آزمایشگاه را میتوان به سادگی با یک مرورگر انجام داد.
۳. فعال کردن 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 اشاره میکند:

۹. سرویس را آزمایش کنید
برای بررسی اینکه آیا تنظیمات به درستی کار میکنند، در بخش تصاویر thumbnails ، تصویر کلاژ (با نام collage.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 شما فراخوانی شده و قادر است تصاویر را به هم الحاق کند تا تصویر نهایی را ایجاد کند.
آنچه ما پوشش دادهایم
- اجرای ابری
- زمانبندی ابری
- فضای ذخیرهسازی ابری
- فروشگاه ابری فایر استور