۱. مقدمه

نمای کلی
سرویسهای Cloud Run برای کانتینرهایی که به طور نامحدود اجرا میشوند و به درخواستهای HTTP گوش میدهند، مناسب هستند، در حالی که کارهای Cloud Run برای کانتینرهایی که تا پایان اجرا میشوند (در حال حاضر تا 24 ساعت ) و به درخواستها پاسخ نمیدهند، مناسبتر هستند. به عنوان مثال، پردازش رکوردها از یک پایگاه داده، پردازش لیستی از فایلها از یک مخزن ذخیرهسازی ابری یا یک عملیات طولانی مدت، مانند محاسبه عدد پی، اگر به عنوان یک کار Cloud Run پیادهسازی شوند، به خوبی کار خواهند کرد.
کارها (jobs) قابلیت ارائه درخواست یا گوش دادن به پورت را ندارند. این بدان معناست که برخلاف سرویسهای Cloud Run، کارها نباید یک وب سرور را به صورت بسته (bundle) ارائه دهند. در عوض، کانتینرهای کارها (jobs containers) باید پس از اتمام کارشان از سرور خارج شوند.
در کارهای Cloud Run، میتوانید چندین کپی از کانتینر خود را به صورت موازی با مشخص کردن تعدادی وظیفه اجرا کنید. هر وظیفه نشان دهنده یک کپی در حال اجرا از کانتینر است. استفاده از چندین وظیفه در صورتی مفید است که هر وظیفه بتواند به طور مستقل زیرمجموعهای از دادههای شما را پردازش کند. به عنوان مثال، پردازش 10،000 رکورد از Cloud SQL یا 10،000 فایل از Cloud Storage میتواند با 10 وظیفه که هر کدام به صورت موازی 1000 رکورد یا فایل را پردازش میکنند، سریعتر انجام شود.
استفاده از کارهای Cloud Run یک فرآیند دو مرحلهای است:
- ایجاد یک کار (job): این فایل تمام پیکربندیهای مورد نیاز برای اجرای کار، مانند تصویر کانتینر، منطقه و متغیرهای محیطی را در خود جای میدهد.
- اجرای کار: این یک اجرای جدید از کار ایجاد میکند. در صورت تمایل، میتوانید کار خود را طوری تنظیم کنید که با استفاده از Cloud Scheduler طبق یک برنامه زمانی اجرا شود.
در این آزمایشگاه کد، ابتدا یک برنامه Node.js را برای گرفتن اسکرینشات از صفحات وب و ذخیره آنها در فضای ذخیرهسازی ابری بررسی میکنید. سپس یک تصویر کانتینر برای برنامه میسازید، آن را روی کارهای Cloud Run اجرا میکنید، کار را برای پردازش صفحات وب بیشتر بهروزرسانی میکنید و کار را با Cloud Scheduler طبق یک برنامه اجرا میکنید.
آنچه یاد خواهید گرفت
- نحوه استفاده از یک برنامه برای گرفتن اسکرین شات از صفحات وب.
- نحوه ساخت یک تصویر کانتینر برای برنامه.
- نحوه ایجاد یک کار Cloud Run برای برنامه.
- نحوه اجرای برنامه به عنوان یک کار Cloud Run.
- نحوه بهروزرسانی شغل.
- نحوه زمانبندی کار با Cloud Scheduler.
۲. تنظیمات و الزامات
تنظیم محیط خودتنظیم
- وارد کنسول گوگل کلود شوید و یک پروژه جدید ایجاد کنید یا از یک پروژه موجود دوباره استفاده کنید. اگر از قبل حساب جیمیل یا گوگل ورک اسپیس ندارید، باید یکی ایجاد کنید .



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

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

این ماشین مجازی با تمام ابزارهای توسعهای که نیاز دارید، مجهز شده است. این ماشین مجازی یک دایرکتوری خانگی پایدار ۵ گیگابایتی ارائه میدهد و روی فضای ابری گوگل اجرا میشود که عملکرد شبکه و احراز هویت را تا حد زیادی بهبود میبخشد. تمام کارهای شما در این آزمایشگاه کد را میتوان در یک مرورگر انجام داد. نیازی به نصب چیزی ندارید.
جی کلود را تنظیم کنید
در Cloud Shell، شناسه پروژه و منطقهای که میخواهید کار Cloud Run را در آن مستقر کنید، تنظیم کنید. آنها را به عنوان متغیرهای PROJECT_ID و REGION ذخیره کنید. در آینده، میتوانید منطقهای را از یکی از مکانهای Cloud Run انتخاب کنید.
PROJECT_ID=[YOUR-PROJECT-ID] REGION=us-central1 gcloud config set core/project $PROJECT_ID
فعال کردن APIها
فعال کردن تمام سرویسهای لازم:
gcloud services enable \ artifactregistry.googleapis.com \ cloudbuild.googleapis.com \ run.googleapis.com
۳. کد را دریافت کنید
شما ابتدا یک برنامه Node.js را برای گرفتن اسکرینشات از صفحات وب و ذخیره آنها در Cloud Storage بررسی میکنید. بعداً، یک تصویر کانتینر برای برنامه میسازید و آن را به عنوان یک کار در Cloud Run اجرا میکنید.
از Cloud Shell، دستور زیر را برای کپی کردن کد برنامه از این مخزن اجرا کنید:
git clone https://github.com/GoogleCloudPlatform/jobs-demos.git
به دایرکتوری حاوی برنامه بروید:
cd jobs-demos/screenshot
شما باید این طرح فایل را ببینید:
screenshot | ├── Dockerfile ├── README.md ├── screenshot.js ├── package.json
در اینجا توضیح مختصری در مورد هر فایل آمده است:
-
screenshot.jsشامل کد Node.js برای برنامه است. -
package.jsonوابستگیهای کتابخانه را تعریف میکند. -
Dockerfileتصویر کانتینر را تعریف میکند.
۴. کد را بررسی کنید
برای بررسی کد، با کلیک روی دکمهی Open Editor در بالای پنجرهی Cloud Shell، از ویرایشگر متن داخلی استفاده کنید.

در ادامه توضیح مختصری در مورد هر فایل ارائه شده است.
اسکرینشات.js
screenshot.js ابتدا Puppeteer و Cloud Storage را به عنوان وابستگی اضافه میکند. Puppeteer یک کتابخانه Node.js است که برای گرفتن اسکرینشات از صفحات وب از آن استفاده میکنید:
const puppeteer = require('puppeteer');
const {Storage} = require('@google-cloud/storage');
یک تابع initBrowser برای مقداردهی اولیه Puppeteer و یک تابع takeScreenshot برای گرفتن اسکرینشات از یک URL مشخص وجود دارد:
async function initBrowser() {
console.log('Initializing browser');
return await puppeteer.launch();
}
async function takeScreenshot(browser, url) {
const page = await browser.newPage();
console.log(`Navigating to ${url}`);
await page.goto(url);
console.log(`Taking a screenshot of ${url}`);
return await page.screenshot({
fullPage: true
});
}
در مرحله بعد، تابعی برای دریافت یا ایجاد یک مخزن ذخیرهسازی ابری و تابع دیگری برای آپلود اسکرینشات یک صفحه وب به یک مخزن وجود دارد:
async function createStorageBucketIfMissing(storage, bucketName) {
console.log(`Checking for Cloud Storage bucket '${bucketName}' and creating if not found`);
const bucket = storage.bucket(bucketName);
const [exists] = await bucket.exists();
if (exists) {
// Bucket exists, nothing to do here
return bucket;
}
// Create bucket
const [createdBucket] = await storage.createBucket(bucketName);
console.log(`Created Cloud Storage bucket '${createdBucket.name}'`);
return createdBucket;
}
async function uploadImage(bucket, taskIndex, imageBuffer) {
// Create filename using the current time and task index
const date = new Date();
date.setMinutes(date.getMinutes() - date.getTimezoneOffset());
const filename = `${date.toISOString()}-task${taskIndex}.png`;
console.log(`Uploading screenshot as '${filename}'`)
await bucket.file(filename).save(imageBuffer);
}
در نهایت، تابع main نقطه ورود است:
async function main(urls) {
console.log(`Passed in urls: ${urls}`);
const taskIndex = process.env.CLOUD_RUN_TASK_INDEX || 0;
const url = urls[taskIndex];
if (!url) {
throw new Error(`No url found for task ${taskIndex}. Ensure at least ${parseInt(taskIndex, 10) + 1} url(s) have been specified as command args.`);
}
const bucketName = process.env.BUCKET_NAME;
if (!bucketName) {
throw new Error('No bucket name specified. Set the BUCKET_NAME env var to specify which Cloud Storage bucket the screenshot will be uploaded to.');
}
const browser = await initBrowser();
const imageBuffer = await takeScreenshot(browser, url).catch(async err => {
// Make sure to close the browser if we hit an error.
await browser.close();
throw err;
});
await browser.close();
console.log('Initializing Cloud Storage client')
const storage = new Storage();
const bucket = await createStorageBucketIfMissing(storage, bucketName);
await uploadImage(bucket, taskIndex, imageBuffer);
console.log('Upload complete!');
}
main(process.argv.slice(2)).catch(err => {
console.error(JSON.stringify({severity: 'ERROR', message: err.message}));
process.exit(1);
});
در مورد متد main به نکات زیر توجه کنید:
- URL ها به عنوان آرگومان ارسال می شوند.
- نام سطل به عنوان متغیر محیطی
BUCKET_NAMEتعریف شده توسط کاربر ارسال میشود. نام سطل باید در کل فضای ابری گوگل منحصر به فرد باشد. - یک متغیر محیطی
CLOUD_RUN_TASK_INDEXتوسط کارهای Cloud Run ارسال میشود. کارهای Cloud Run میتوانند چندین کپی از برنامه را به عنوان وظایف منحصر به فرد اجرا کنند.CLOUD_RUN_TASK_INDEXنشان دهنده شاخص وظیفه در حال اجرا است. وقتی کد خارج از کارهای Cloud Run اجرا میشود، به طور پیشفرض روی صفر قرار میگیرد. وقتی برنامه به عنوان چندین وظیفه اجرا میشود، هر وظیفه/کانتینر URL مربوط به خود را دریافت میکند، از آن اسکرین شات میگیرد و تصویر را در سطل ذخیره میکند.
بسته.json
فایل package.json برنامه را تعریف میکند و وابستگیهای Cloud Storage و Puppeteer را مشخص میکند:
{
"name": "screenshot",
"version": "1.0.0",
"description": "Create a job to capture screenshots",
"main": "screenshot.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Google LLC",
"license": "Apache-2.0",
"dependencies": {
"@google-cloud/storage": "^5.18.2",
"puppeteer": "^13.5.1"
}
}
داکرفایل
Dockerfile تصویر کانتینر را برای برنامه به همراه تمام کتابخانهها و وابستگیهای مورد نیاز تعریف میکند:
FROM ghcr.io/puppeteer/puppeteer:16.1.0 COPY package*.json ./ RUN npm ci --omit=dev COPY . . ENTRYPOINT ["node", "screenshot.js"]
۵. یک شغل را مستقر کنید
قبل از ایجاد یک کار، باید یک حساب کاربری سرویس ایجاد کنید که برای اجرای کار از آن استفاده خواهید کرد.
gcloud iam service-accounts create screenshot-sa --display-name="Screenshot app service account"
نقش storage.admin را به حساب سرویس اعطا کنید تا بتوان از آن برای ایجاد سطلها و اشیاء استفاده کرد.
gcloud projects add-iam-policy-binding $PROJECT_ID \ --role roles/storage.admin \ --member serviceAccount:screenshot-sa@$PROJECT_ID.iam.gserviceaccount.com
اکنون آمادهاید تا یک کار Cloud Run را که شامل پیکربندی مورد نیاز برای اجرای کار است، مستقر کنید.
gcloud beta run jobs deploy screenshot \ --source=. \ --args="https://example.com" \ --args="https://cloud.google.com" \ --tasks=2 \ --task-timeout=5m \ --region=$REGION \ --set-env-vars=BUCKET_NAME=screenshot-$PROJECT_ID-$RANDOM \ --service-account=screenshot-sa@$PROJECT_ID.iam.gserviceaccount.com
این از استقرار مبتنی بر منبع استفاده میکند و یک کار Cloud Run را بدون اجرای آن ایجاد میکند.
توجه کنید که چگونه صفحات وب به عنوان آرگومان ارسال میشوند. نام باکت برای ذخیره تصاویر به عنوان یک متغیر محیطی ارسال میشود.
شما میتوانید با مشخص کردن تعدادی وظیفه برای اجرا با پرچم --tasks چندین کپی از کانتینر خود را به صورت موازی اجرا کنید. هر وظیفه نشان دهنده یک کپی در حال اجرا از کانتینر است. استفاده از چندین وظیفه در صورتی مفید است که هر وظیفه بتواند به طور مستقل زیرمجموعهای از دادههای شما را پردازش کند. برای تسهیل این امر، هر وظیفه از شاخص خود که در متغیر محیطی CLOUD_RUN_TASK_INDEX ذخیره میشود، آگاه است. کد شما مسئول تعیین این است که کدام وظیفه کدام زیرمجموعه از دادهها را مدیریت میکند. به --tasks=2 در این نمونه توجه کنید. این کار تضمین میکند که 2 کانتینر برای 2 URL که میخواهیم پردازش کنیم، اجرا شوند.
هر وظیفه میتواند تا ۲۴ ساعت اجرا شود. شما میتوانید این زمان انتظار را با استفاده از پرچم --task-timeout کاهش دهید، همانطور که در این مثال انجام دادیم. برای اینکه کار با موفقیت انجام شود، همه وظایف باید با موفقیت انجام شوند. به طور پیشفرض، وظایف شکست خورده دوباره اجرا نمیشوند. میتوانید وظایفی را پیکربندی کنید که پس از شکست، دوباره اجرا شوند. اگر تعداد دفعات تلاش مجدد برای هر وظیفه از حد مجاز بیشتر شود، کل کار با شکست مواجه میشود.
به طور پیشفرض، کار شما با حداکثر تعداد وظایف ممکن به صورت موازی اجرا میشود. این تعداد برابر با تعداد وظایف کار شما خواهد بود، حداکثر تا ۱۰۰. میتوانید برای کارهایی که به یک backend با مقیاسپذیری محدود دسترسی دارند، میزان موازی بودن را کمتر تنظیم کنید. به عنوان مثال، یک پایگاه داده که از تعداد محدودی اتصال فعال پشتیبانی میکند. میتوانید با استفاده از پرچم --parallelism میزان موازی بودن را کاهش دهید.
۶. یک کار را اجرا کنید
قبل از اجرای کار، کار را فهرست کنید تا ببینید که ایجاد شده است:
gcloud run jobs list ✔ JOB: screenshot REGION: us-central LAST RUN AT: CREATED: 2022-02-22 12:20:50 UTC
با دستور زیر job را اجرا کنید:
gcloud run jobs execute screenshot --region=$REGION
این کار را اجرا میکند. میتوانید اجراهای فعلی و گذشته را فهرست کنید:
gcloud run jobs executions list --job screenshot --region=$REGION ... JOB: screenshot EXECUTION: screenshot-znkmm REGION: $REGION RUNNING: 1 COMPLETE: 1 / 2 CREATED: 2022-02-22 12:40:42 UTC
اجرا را شرح دهید. باید علامت سبز و پیام « tasks completed successfully » را ببینید:
gcloud run jobs executions describe screenshot-znkmm --region=$REGION ✔ Execution screenshot-znkmm in region $REGION 2 tasks completed successfully Image: $REGION-docker.pkg.dev/$PROJECT_ID/containers/screenshot at 311b20d9... Tasks: 2 Args: https://example.com https://cloud.google.com Memory: 1Gi CPU: 1000m Task Timeout: 3600s Parallelism: 2 Service account: 11111111-compute@developer.gserviceaccount.com Env vars: BUCKET_NAME screenshot-$PROJECT_ID-$RANDOM
همچنین میتوانید صفحه مشاغل Cloud Run در Cloud Console را بررسی کنید تا وضعیت را مشاهده کنید:

اگر بخش ذخیرهسازی ابری را بررسی کنید، باید دو فایل اسکرینشات ایجاد شده را ببینید:

گاهی اوقات ممکن است لازم باشد قبل از اتمام یک اجرا، آن را متوقف کنید - شاید به این دلیل که متوجه شدهاید باید کار را با پارامترهای مختلف اجرا کنید یا خطایی در کد وجود دارد و نمیخواهید زمان محاسباتی غیرضروری صرف کنید.
برای متوقف کردن اجرای یک job، باید آن را حذف کنید:
gcloud run jobs executions delete screenshot-znkmm --region=$REGION
۷. بهروزرسانی یک شغل
نسخههای جدید کانتینر شما به طور خودکار توسط کارهای Cloud Run در اجرای بعدی انتخاب نمیشوند. اگر کد کار خود را تغییر دهید، باید کانتینر را دوباره بسازید و کار خود را بهروزرسانی کنید. استفاده از تصاویر برچسبگذاری شده به شما کمک میکند تا مشخص کنید کدام نسخه از تصویر در حال حاضر استفاده میشود.
به طور مشابه، اگر میخواهید برخی از متغیرهای پیکربندی را بهروزرسانی کنید، باید کار را نیز بهروزرسانی کنید. اجراهای بعدی کار از کانتینر و تنظیمات پیکربندی جدید استفاده خواهند کرد.
کار را بهروزرسانی کنید و صفحاتی را که برنامه از آنها اسکرینشات میگیرد در پرچم --args تغییر دهید. همچنین پرچم --tasks را بهروزرسانی کنید تا تعداد صفحات را منعکس کند.
gcloud run jobs update screenshot \ --args="https://www.pinterest.com" \ --args="https://www.apartmenttherapy.com" \ --args="https://www.google.com" \ --region=$REGION \ --tasks=3
دوباره کار را اجرا کنید. این بار از فلگ --wait برای منتظر ماندن جهت اتمام اجراها استفاده کنید:
gcloud run jobs execute screenshot --region=$REGION --wait
بعد از چند ثانیه، باید ۳ اسکرینشات دیگر را که به سطل اضافه شدهاند، ببینید:

۸. برای یک کار برنامهریزی کنید
تا اینجا، شما کارها را به صورت دستی اجرا میکردید. در یک سناریوی واقعی، احتمالاً میخواهید کارها را در پاسخ به یک رویداد یا طبق یک برنامه اجرا کنید. بیایید ببینیم چگونه میتوان کار گرفتن اسکرینشات را با استفاده از Cloud Scheduler طبق یک برنامه اجرا کرد.
ابتدا مطمئن شوید که API زمانبندی ابری فعال است:
gcloud services enable cloudscheduler.googleapis.com
به صفحه جزئیات مشاغل Cloud Run بروید و روی بخش Triggers کلیک کنید:

دکمه Add Scheduler Trigger انتخاب کنید:

یک پنل در سمت راست باز میشود. یک کار زمانبندی ایجاد کنید که هر روز ساعت ۹:۰۰ با این پیکربندی اجرا شود و Continue انتخاب کنید:

در صفحه بعد، حساب کاربری سرویس محاسباتی پیشفرض را انتخاب کرده و روی Create کلیک کنید:

اکنون باید یک تریگر جدید Cloud Scheduler ایجاد شده را مشاهده کنید:

برای رفتن به صفحه Cloud Scheduler روی View Details کلیک کنید.
میتوانید تا ساعت ۹ صبح صبر کنید تا زمانبندی فعال شود یا میتوانید با انتخاب Force Run ، زمانبندی ابری را به صورت دستی فعال کنید:

پس از چند ثانیه، باید ببینید که کار Cloud Scheduler با موفقیت اجرا شده است:

همچنین باید ۳ اسکرینشات دیگر که توسط فراخوانی Cloud Scheduler اضافه شدهاند را مشاهده کنید:

۹. تبریک
تبریک میگویم، شما codelab را تمام کردید!
پاکسازی (اختیاری)
برای جلوگیری از تحمیل هزینهها، بهتر است منابع را پاکسازی کنید.
اگر به پروژه نیازی ندارید، میتوانید به سادگی آن را حذف کنید:
gcloud projects delete $PROJECT_ID
اگر به پروژه نیاز دارید، میتوانید منابع را به صورت جداگانه حذف کنید.
کد منبع را حذف کنید:
rm -rf ~/jobs-demos/
مخزن رجیستری Artifact را حذف کنید:
gcloud artifacts repositories delete containers --location=$REGION
حذف حساب کاربری سرویس:
gcloud iam service-accounts delete screenshot-sa@$PROJECT_ID.iam.gserviceaccount.com
حذف کار Cloud Run:
gcloud run jobs delete screenshot --region=$REGION
حذف کار زمانبندی ابری:
gcloud scheduler jobs delete screenshot-scheduler-trigger --location=$REGION
حذف سطل ذخیرهسازی ابری:
gcloud storage rm --recursive gs://screenshot-$PROJECT_ID
آنچه ما پوشش دادهایم
- نحوه استفاده از یک برنامه برای گرفتن اسکرین شات از صفحات وب.
- نحوه ساخت یک تصویر کانتینر برای برنامه.
- نحوه ایجاد یک کار Cloud Run برای برنامه.
- نحوه اجرای برنامه به عنوان یک کار Cloud Run.
- نحوه بهروزرسانی شغل.
- نحوه زمانبندی کار با Cloud Scheduler.