1. Giới thiệu

Tổng quan
Các dịch vụ Cloud Run phù hợp với những vùng chứa chạy vô thời hạn để chờ các yêu cầu HTTP, trong khi các công việc Cloud Run phù hợp hơn với những vùng chứa chạy cho đến khi hoàn tất (hiện tại là tối đa 24 giờ) và không xử lý các yêu cầu. Ví dụ: xử lý các bản ghi từ cơ sở dữ liệu, xử lý danh sách tệp từ một bộ chứa Cloud Storage hoặc một thao tác kéo dài, chẳng hạn như tính toán số Pi, sẽ hoạt động hiệu quả nếu được triển khai dưới dạng một công việc Cloud Run.
Các công việc không có khả năng xử lý yêu cầu hoặc theo dõi trên một cổng. Điều này có nghĩa là không giống như các dịch vụ Cloud Run, các công việc không được đi kèm với một máy chủ web. Thay vào đó, các vùng chứa công việc sẽ thoát khi hoàn tất.
Trong các lệnh Cloud Run, bạn có thể chạy song song nhiều bản sao của vùng chứa bằng cách chỉ định số lượng tác vụ. Mỗi tác vụ đại diện cho một bản sao đang chạy của vùng chứa. Việc sử dụng nhiều tác vụ sẽ hữu ích nếu mỗi tác vụ có thể xử lý độc lập một tập hợp con dữ liệu của bạn. Ví dụ: bạn có thể xử lý 10.000 bản ghi từ Cloud SQL hoặc 10.000 tệp từ Cloud Storage nhanh hơn bằng cách sử dụng 10 tác vụ xử lý 1.000 bản ghi hoặc tệp, mỗi tác vụ song song.
Sử dụng các công việc Cloud Run là một quy trình gồm 2 bước:
- Tạo một công việc: Thao tác này bao gồm tất cả cấu hình cần thiết để chạy công việc, chẳng hạn như hình ảnh vùng chứa, khu vực, biến môi trường.
- Chạy công việc: Thao tác này sẽ tạo một lần thực thi mới cho công việc. Bạn có thể thiết lập để công việc chạy theo lịch bằng Cloud Scheduler.
Trong lớp học lập trình này, trước tiên, bạn sẽ khám phá một ứng dụng Node.js để chụp ảnh màn hình các trang web và lưu trữ chúng vào Cloud Storage. Sau đó, bạn sẽ tạo một hình ảnh vùng chứa cho ứng dụng, chạy hình ảnh đó trên các công việc Cloud Run, cập nhật công việc để xử lý nhiều trang web hơn và chạy công việc theo lịch bằng Cloud Scheduler.
Kiến thức bạn sẽ học được
- Cách dùng ứng dụng để chụp ảnh màn hình của các trang web.
- Cách tạo một hình ảnh vùng chứa cho ứng dụng.
- Cách tạo một công việc Cloud Run cho ứng dụng.
- Cách chạy ứng dụng dưới dạng một công việc Cloud Run.
- Cách cập nhật công việc.
- Cách lên lịch cho lệnh bằng Cloud Scheduler.
2. Thiết lập và yêu cầu
Thiết lập môi trường theo tốc độ của riêng bạn
- Đăng nhập vào Google Cloud Console rồi tạo một dự án mới hoặc sử dụng lại một dự án hiện có. Nếu chưa có tài khoản Gmail hoặc Google Workspace, bạn phải tạo một tài khoản.



- Tên dự án là tên hiển thị của những người tham gia dự án này. Đây là một chuỗi ký tự mà các API của Google không sử dụng. Bạn luôn có thể cập nhật thông tin này.
- Mã dự án là mã duy nhất trên tất cả các dự án trên Google Cloud và không thể thay đổi (bạn không thể thay đổi mã này sau khi đã đặt). Cloud Console sẽ tự động tạo một chuỗi duy nhất; thường thì bạn không cần quan tâm đến chuỗi này. Trong hầu hết các lớp học lập trình, bạn sẽ cần tham chiếu đến Mã dự án (thường được xác định là
PROJECT_ID). Nếu không thích mã nhận dạng được tạo, bạn có thể tạo một mã nhận dạng ngẫu nhiên khác. Hoặc bạn có thể thử tên người dùng của riêng mình để xem tên đó có được chấp nhận hay không. Bạn không thể thay đổi chế độ này sau bước này và chế độ này sẽ duy trì trong suốt thời gian diễn ra dự án. - Để bạn nắm được thông tin, có một giá trị thứ ba là Số dự án mà một số API sử dụng. Tìm hiểu thêm về cả 3 giá trị này trong tài liệu.
- Tiếp theo, bạn cần bật tính năng thanh toán trong Cloud Console để sử dụng các tài nguyên/API trên Cloud. Việc thực hiện lớp học lập trình này sẽ không tốn nhiều chi phí, nếu có. Để tắt các tài nguyên nhằm tránh bị tính phí ngoài phạm vi hướng dẫn này, bạn có thể xoá các tài nguyên đã tạo hoặc xoá dự án. Người dùng mới của Google Cloud đủ điều kiện tham gia chương trình Dùng thử miễn phí 300 USD.
Khởi động Cloud Shell
Mặc dù có thể vận hành Google Cloud từ xa trên máy tính xách tay, nhưng trong lớp học lập trình này, bạn sẽ sử dụng Google Cloud Shell, một môi trường dòng lệnh chạy trên Cloud.
Trên Bảng điều khiển Google Cloud, hãy nhấp vào biểu tượng Cloud Shell trên thanh công cụ ở trên cùng bên phải:

Quá trình này chỉ mất vài phút để cung cấp và kết nối với môi trường. Khi quá trình này kết thúc, bạn sẽ thấy như sau:

Máy ảo này được trang bị tất cả các công cụ phát triển mà bạn cần. Nền tảng này cung cấp một thư mục chính có dung lượng 5 GB và chạy trên Google Cloud, giúp tăng cường đáng kể hiệu suất mạng và hoạt động xác thực. Bạn có thể thực hiện mọi thao tác trong lớp học lập trình này trong trình duyệt. Bạn không cần cài đặt bất cứ thứ gì.
Thiết lập gcloud
Trong Cloud Shell, hãy đặt mã dự án và khu vực mà bạn muốn triển khai công việc Cloud Run. Lưu các giá trị này dưới dạng biến PROJECT_ID và REGION. Trong tương lai, bạn có thể chọn một khu vực trong số các vị trí của Cloud Run.
PROJECT_ID=[YOUR-PROJECT-ID] REGION=us-central1 gcloud config set core/project $PROJECT_ID
Bật API
Bật tất cả các dịch vụ cần thiết:
gcloud services enable \ artifactregistry.googleapis.com \ cloudbuild.googleapis.com \ run.googleapis.com
3. Lấy mã
Trước tiên, bạn sẽ khám phá một ứng dụng Node.js để chụp ảnh màn hình các trang web và lưu trữ chúng vào Cloud Storage. Sau đó, bạn sẽ tạo một hình ảnh vùng chứa cho ứng dụng và chạy ứng dụng đó dưới dạng một công việc trên Cloud Run.
Trong Cloud Shell, hãy chạy lệnh sau để sao chép mã ứng dụng từ kho lưu trữ này:
git clone https://github.com/GoogleCloudPlatform/jobs-demos.git
Chuyển đến thư mục chứa ứng dụng:
cd jobs-demos/screenshot
Bạn sẽ thấy bố cục tệp sau:
screenshot | ├── Dockerfile ├── README.md ├── screenshot.js ├── package.json
Sau đây là nội dung mô tả ngắn gọn về từng tệp:
screenshot.jschứa mã Node.js cho ứng dụng.package.jsonxác định các phần phụ thuộc của thư viện.Dockerfilexác định hình ảnh vùng chứa.
4. Khám phá mã
Để khám phá mã, hãy sử dụng trình chỉnh sửa văn bản tích hợp bằng cách nhấp vào nút Open Editor ở đầu cửa sổ Cloud Shell.

Sau đây là nội dung giải thích ngắn gọn về từng tệp.
screenshot.js
screenshot.js trước tiên sẽ thêm Puppeteer và Cloud Storage làm phần phụ thuộc. Puppeteer là một thư viện Node.js mà bạn dùng để chụp ảnh màn hình các trang web:
const puppeteer = require('puppeteer');
const {Storage} = require('@google-cloud/storage');
Có hàm initBrowser để khởi chạy Puppeteer và hàm takeScreenshot để chụp ảnh màn hình của một URL nhất định:
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
});
}
Tiếp theo, có một hàm để lấy hoặc tạo một vùng chứa Bộ nhớ đám mây và một hàm khác để tải ảnh chụp màn hình của một trang web lên vùng chứa:
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);
}
Cuối cùng, hàm main là điểm truy cập:
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);
});
Hãy lưu ý những điều sau về phương thức main:
- URL được truyền dưới dạng đối số.
- Tên nhóm được truyền dưới dạng biến môi trường
BUCKET_NAMEdo người dùng xác định. Tên bộ chứa phải là duy nhất trên toàn bộ Google Cloud. - Các công việc trên Cloud Run sẽ truyền biến môi trường
CLOUD_RUN_TASK_INDEX. Các công việc trên Cloud Run có thể chạy nhiều bản sao của ứng dụng dưới dạng các tác vụ riêng biệt.CLOUD_RUN_TASK_INDEXbiểu thị chỉ mục của tác vụ đang chạy. Giá trị này mặc định là 0 khi mã được chạy bên ngoài các công việc Cloud Run. Khi ứng dụng chạy dưới dạng nhiều tác vụ, mỗi tác vụ/vùng chứa sẽ chọn URL mà ứng dụng chịu trách nhiệm, chụp ảnh màn hình và lưu hình ảnh vào vùng lưu trữ.
package.json
Tệp package.json xác định ứng dụng và chỉ định các phần phụ thuộc cho Cloud Storage và 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
Dockerfile xác định hình ảnh vùng chứa cho ứng dụng với tất cả các thư viện và phần phụ thuộc bắt buộc:
FROM ghcr.io/puppeteer/puppeteer:16.1.0 COPY package*.json ./ RUN npm ci --omit=dev COPY . . ENTRYPOINT ["node", "screenshot.js"]
5. Triển khai một công việc
Trước khi tạo một công việc, bạn cần tạo một tài khoản dịch vụ mà bạn sẽ dùng để chạy công việc đó.
gcloud iam service-accounts create screenshot-sa --display-name="Screenshot app service account"
Cấp vai trò storage.admin cho tài khoản dịch vụ để tài khoản này có thể dùng để tạo các vùng lưu trữ và đối tượng.
gcloud projects add-iam-policy-binding $PROJECT_ID \ --role roles/storage.admin \ --member serviceAccount:screenshot-sa@$PROJECT_ID.iam.gserviceaccount.com
Giờ đây, bạn đã sẵn sàng triển khai một công việc Cloud Run có cấu hình cần thiết để chạy công việc đó.
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
Thao tác này sử dụng quy trình triển khai dựa trên nguồn và tạo một công việc Cloud Run mà không thực thi công việc đó.
Lưu ý cách các trang web được truyền vào dưới dạng đối số. Tên của nhóm lưu ảnh chụp màn hình được truyền vào dưới dạng một biến môi trường.
Bạn có thể chạy song song nhiều bản sao của vùng chứa bằng cách chỉ định số lượng tác vụ cần chạy bằng cờ --tasks. Mỗi tác vụ đại diện cho một bản sao đang chạy của vùng chứa. Việc sử dụng nhiều tác vụ sẽ hữu ích nếu mỗi tác vụ có thể xử lý độc lập một tập hợp con dữ liệu của bạn. Để tạo điều kiện thuận lợi cho việc này, mỗi tác vụ đều biết chỉ mục của mình, được lưu trữ trong biến môi trường CLOUD_RUN_TASK_INDEX. Mã của bạn chịu trách nhiệm xác định tác vụ nào xử lý tập hợp con nào của dữ liệu. Hãy chú ý đến --tasks=2 trong mẫu này. Điều này đảm bảo 2 vùng chứa chạy cho 2 URL mà chúng ta muốn xử lý.
Mỗi tác vụ có thể chạy trong tối đa 24 giờ. Bạn có thể giảm thời gian chờ này bằng cờ --task-timeout, như chúng ta đã làm trong ví dụ này. Tất cả các tác vụ đều phải thành công thì công việc mới hoàn tất. Theo mặc định, các tác vụ không thành công sẽ không được thử lại. Bạn có thể định cấu hình để các tác vụ được thử lại khi không thành công. Nếu bất kỳ tác vụ nào vượt quá số lần thử lại, thì toàn bộ tác vụ sẽ không thành công.
Theo mặc định, công việc của bạn sẽ chạy song song với nhiều tác vụ nhất có thể. Số này sẽ bằng với số lượng nhiệm vụ cho công việc của bạn, tối đa là 100. Bạn nên đặt mức song song thấp hơn cho những công việc truy cập vào một phần phụ trợ có khả năng mở rộng hạn chế. Ví dụ: một cơ sở dữ liệu chỉ hỗ trợ một số lượng kết nối đang hoạt động nhất định. Bạn có thể giảm mức độ song song bằng cờ --parallelism.
6. Chạy một công việc
Trước khi chạy lệnh, hãy liệt kê lệnh đó để xem lệnh đã được tạo hay chưa:
gcloud run jobs list ✔ JOB: screenshot REGION: us-central LAST RUN AT: CREATED: 2022-02-22 12:20:50 UTC
Chạy lệnh sau để thực hiện công việc:
gcloud run jobs execute screenshot --region=$REGION
Thao tác này sẽ thực thi lệnh. Bạn có thể liệt kê các lần thực thi hiện tại và trước đây:
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
Mô tả quá trình thực thi. Bạn sẽ thấy dấu kiểm màu xanh lục và thông báo 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
Bạn cũng có thể kiểm tra trang công việc Cloud Run của Cloud Console để xem trạng thái:

Nếu kiểm tra bộ chứa Cloud Storage, bạn sẽ thấy 2 tệp ảnh chụp màn hình đã tạo:

Đôi khi, bạn có thể cần dừng một quá trình thực thi trước khi quá trình đó hoàn tất – có thể là do bạn nhận ra mình cần chạy công việc với các tham số khác hoặc có lỗi trong mã và bạn không muốn sử dụng thời gian tính toán không cần thiết.
Để dừng thực thi một công việc, bạn cần xoá quá trình thực thi đó:
gcloud run jobs executions delete screenshot-znkmm --region=$REGION
7. Cập nhật công việc
Các phiên bản mới của vùng chứa sẽ không được các tác vụ Cloud Run tự động chọn trong lần thực thi tiếp theo. Nếu thay đổi mã cho công việc, bạn cần phải tạo lại vùng chứa và cập nhật công việc. Việc sử dụng hình ảnh được gắn thẻ sẽ giúp bạn xác định phiên bản hình ảnh hiện đang được sử dụng.
Tương tự, bạn cũng cần cập nhật công việc nếu muốn cập nhật một số biến cấu hình. Các lần thực thi tiếp theo của lệnh sẽ sử dụng vùng chứa và chế độ cài đặt cấu hình mới.
Cập nhật công việc và thay đổi các trang mà ứng dụng chụp ảnh màn hình trong cờ --args. Đồng thời, hãy cập nhật cờ --tasks để phản ánh số lượng trang.
gcloud run jobs update screenshot \ --args="https://www.pinterest.com" \ --args="https://www.apartmenttherapy.com" \ --args="https://www.google.com" \ --region=$REGION \ --tasks=3
Chạy lại lệnh. Truyền thời gian này vào cờ --wait để chờ quá trình thực thi hoàn tất:
gcloud run jobs execute screenshot --region=$REGION --wait
Sau vài giây, bạn sẽ thấy 3 ảnh chụp màn hình khác được thêm vào nhóm:

8. Lên lịch cho một công việc
Cho đến nay, bạn đang chạy các công việc theo cách thủ công. Trong trường hợp thực tế, có thể bạn muốn chạy các công việc để phản hồi một sự kiện hoặc theo lịch trình. Hãy xem cách chạy công việc chụp ảnh màn hình theo lịch bằng Cloud Scheduler.
Trước tiên, hãy đảm bảo rằng bạn đã bật Cloud Scheduler API:
gcloud services enable cloudscheduler.googleapis.com
Chuyển đến trang chi tiết về các công việc trên Cloud Run rồi nhấp vào mục Triggers:

Chọn nút Add Scheduler Trigger:

Một bảng điều khiển sẽ mở ra ở bên phải. Tạo một công việc của Trình lập lịch để chạy hằng ngày vào lúc 9:00 với cấu hình này và chọn Continue:

Trong trang tiếp theo, hãy chọn tài khoản dịch vụ điện toán mặc định rồi chọn Create:

Giờ đây, bạn sẽ thấy một trình kích hoạt Cloud Scheduler mới được tạo:

Nhấp vào View Details để chuyển đến trang Cloud Scheduler.
Bạn có thể đợi đến 9 giờ sáng để trình lập lịch bắt đầu hoạt động hoặc bạn có thể kích hoạt Cloud Scheduler theo cách thủ công bằng cách chọn Force Run:

Sau vài giây, bạn sẽ thấy công việc Cloud Scheduler được thực thi thành công:

Bạn cũng sẽ thấy 3 ảnh chụp màn hình khác do lệnh gọi từ Cloud Scheduler thêm vào:

9. Xin chúc mừng
Xin chúc mừng, bạn đã hoàn tất lớp học lập trình này!
Dọn dẹp (Không bắt buộc)
Để tránh phát sinh phí, bạn nên dọn dẹp tài nguyên.
Nếu không cần dự án đó nữa, bạn chỉ cần xoá dự án:
gcloud projects delete $PROJECT_ID
Nếu cần dự án, bạn có thể xoá từng tài nguyên.
Xoá mã nguồn:
rm -rf ~/jobs-demos/
Xoá kho lưu trữ Artifact Registry:
gcloud artifacts repositories delete containers --location=$REGION
Xoá tài khoản dịch vụ:
gcloud iam service-accounts delete screenshot-sa@$PROJECT_ID.iam.gserviceaccount.com
Xoá lệnh Cloud Run:
gcloud run jobs delete screenshot --region=$REGION
Xoá công việc Cloud Scheduler:
gcloud scheduler jobs delete screenshot-scheduler-trigger --location=$REGION
Xoá bộ chứa Cloud Storage:
gcloud storage rm --recursive gs://screenshot-$PROJECT_ID
Nội dung đã đề cập
- Cách dùng ứng dụng để chụp ảnh màn hình của các trang web.
- Cách tạo một hình ảnh vùng chứa cho ứng dụng.
- Cách tạo một công việc Cloud Run cho ứng dụng.
- Cách chạy ứng dụng dưới dạng một công việc Cloud Run.
- Cách cập nhật công việc.
- Cách lên lịch cho lệnh bằng Cloud Scheduler.