Pic-a-daily: Lab 5 – Dọn dẹp sau khi xoá hình ảnh

1. Tổng quan

Trong lớp học lập trình này, bạn sẽ tạo một dịch vụ Cloud Run mới có tên là trình thu thập rác hình ảnh. Dịch vụ này sẽ được Eventarc, một dịch vụ mới để nhận các sự kiện trong Cloud Run kích hoạt. Khi một ảnh bị xoá khỏi bộ chứa ảnh, dịch vụ sẽ nhận được một sự kiện từ Eventarc. Sau đó, hệ thống sẽ xoá hình ảnh khỏi bộ chứa hình thu nhỏ, đồng thời xoá hình ảnh đó khỏi bộ sưu tập ảnh trên Firestore.

d93345bfc235f81e.png

Kiến thức bạn sẽ học được

  • Cloud Run
  • Cloud Storage
  • Cloud Firestore
  • Eventarc

2. Thiết lập và yêu cầu

Thiết lập môi trường theo tiến độ riêng

  1. Đăng nhập vào Google Cloud Console rồi tạo dự án mới hoặc sử dụng lại 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.

96a9c957bc475304.pngS

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

  • 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ự không được API của Google sử dụng và bạn có thể cập nhật chuỗi này bất cứ lúc nào.
  • Mã dự án phải là duy nhất trong tất cả các dự án Google Cloud và không thể thay đổi (không thể thay đổi sau khi đã đặt). Cloud Console sẽ tự động tạo một chuỗi duy nhất; thường bạn không quan tâm đến sản phẩm đó là gì. 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 (và mã này thường được xác định là PROJECT_ID). Vì vậy, nếu không thích, bạn có thể tạo một mã ngẫu nhiên khác hoặc bạn có thể thử mã của riêng mình để xem có mã này chưa. Sau đó, video sẽ được "đóng băng" sau khi tạo dự án.
  • Có giá trị thứ ba là Project Number (Số dự án) mà một số API sử dụng. Tìm hiểu thêm về cả ba giá trị này trong tài liệu này.
  1. Tiếp theo, bạn sẽ cần bật tính năng thanh toán trong Cloud Console để sử dụng tài nguyên/API trên Cloud. Việc chạy qua lớp học lập trình này sẽ không tốn nhiều chi phí. Để tắt các tài nguyên để bạn không phải chịu thanh toán ngoài hướng dẫn này, hãy làm theo mọi thao tác "dọn dẹp" hướng dẫn ở cuối lớp học lập trình. 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ù bạn 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 trong Đám mây.

Trong Bảng điều khiển GCP, hãy nhấp vào biểu tượng Cloud Shell ở thanh công cụ trên cùng bên phải:

bce75f34b2c53987.png

Sẽ chỉ mất một chút thời gian để cấp phép và kết nối với môi trường. Sau khi hoàn tất, bạn sẽ thấy như sau:

f6ef2b5f13479f3a.png

Máy ảo này chứa tất cả các công cụ phát triển mà bạn cần. Phiên bản này cung cấp thư mục gốc có dung lượng ổn định 5 GB và chạy trên Google Cloud, giúp nâng cao đáng kể hiệu suất và khả năng xác thực của mạng. Bạn có thể thực hiện tất cả công việc trong phòng thí nghiệm này chỉ bằng một trình duyệt.

3. Giới thiệu về Eventarc

Eventarc giúp bạn dễ dàng kết nối các dịch vụ Cloud Run với các sự kiện từ nhiều nguồn. Dịch vụ này đảm nhận việc nhập, phân phối, bảo mật, uỷ quyền và xử lý lỗi sự kiện cho bạn.

776ed63706ca9683.pngS

Bạn có thể vẽ sự kiện từ các nguồn trên Google Cloud và các ứng dụng tuỳ chỉnh xuất bản lên Cloud Pub/Sub rồi gửi chúng tới các bồn lưu trữ dữ liệu của Google Cloud Run.

Các sự kiện từ nhiều nguồn trên Google Cloud được cung cấp thông qua Nhật ký kiểm tra của Cloud. Độ trễ và khả năng cung cấp sự kiện từ các nguồn này gắn liền với dữ liệu của Nhật ký kiểm tra đám mây. Bất cứ khi nào một sự kiện từ một nguồn trên Google Cloud được kích hoạt, một mục tương ứng trong Nhật ký kiểm tra của Cloud sẽ được tạo.

Các ứng dụng tuỳ chỉnh xuất bản lên Cloud Pub/Sub có thể phát hành thông báo theo chủ đề Pub/Sub mà họ chỉ định ở bất kỳ định dạng nào.

Trình kích hoạt sự kiện là cơ chế lọc để chỉ định sự kiện nào cần phân phối đến bồn lưu trữ dữ liệu nào.

Tất cả các sự kiện đều được phân phối ở định dạng CloudEvents v1.0 để có khả năng tương tác trên nhiều dịch vụ.

4. Trước khi bắt đầu

Bật API

Bạn cần có dịch vụ Eventarc để kích hoạt dịch vụ Cloud Run. Đảm bảo bạn đã bật chế độ này:

gcloud services enable eventarc.googleapis.com

Bạn sẽ thấy thao tác hoàn tất thành công:

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

Định cấu hình tài khoản dịch vụ

Tài khoản dịch vụ mặc định của điện toán sẽ được dùng trong các điều kiện kích hoạt. Cấp vai trò eventarc.eventReceiver cho tài khoản dịch vụ mặc định của Compute Engine:

PROJECT_NUMBER=$(gcloud projects describe $GOOGLE_CLOUD_PROJECT --format='value(projectNumber)')

gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \
    --member serviceAccount:$PROJECT_NUMBER-compute@developer.gserviceaccount.com \
    --role roles/eventarc.eventReceiver

Cấp vai trò pubsub.publisher cho tài khoản dịch vụ Cloud Storage. Điều này là cần thiết cho trình kích hoạt Eventarc Cloud Storage:

SERVICE_ACCOUNT=$(gsutil kms serviceaccount -p $PROJECT_NUMBER)

gcloud projects add-iam-policy-binding $PROJECT_NUMBER \
    --member serviceAccount:$SERVICE_ACCOUNT \
    --role roles/pubsub.publisher

Nếu bạn bật tài khoản dịch vụ Pub/Sub từ ngày 8 tháng 4 năm 2021 trở về trước, hãy cấp vai trò iam.serviceAccountTokenCreator cho tài khoản dịch vụ Pub/Sub:

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member serviceAccount:service-$PROJECT_NUMBER@gcp-sa-pubsub.iam.gserviceaccount.com \
  --role roles/iam.serviceAccountTokenCreator

5. Sao chép mã

Sao chép mã nếu bạn chưa truy cập vào lớp học lập trình trước đó:

git clone https://github.com/GoogleCloudPlatform/serverless-photosharing-workshop

Sau đó, bạn có thể chuyển đến thư mục chứa dịch vụ:

cd serverless-photosharing-workshop/services/garbage-collector/nodejs

Bạn sẽ có bố cục tệp sau đây cho dịch vụ:

services
 |
 ├── garbage-collector
      |
      ├── nodejs
           |
           ├── index.js
           ├── package.json

Bên trong thư mục này, bạn có 3 tệp:

  • index.js chứa mã Node.js
  • package.json xác định các phần phụ thuộc của thư viện

6. Khám phá đoạn mã

Phần phụ thuộc

Tệp package.json xác định các phần phụ thuộc cần thiết của thư viện:

{
  "name": "garbage_collector_service",
  "version": "0.0.1",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "dependencies": {
    "cloudevents": "^4.0.1",
    "express": "^4.17.1",
    "@google/events": "^3.1.0",
    "@google-cloud/firestore": "^4.9.9",
    "@google-cloud/storage": "^5.8.3"
  }
}

Chúng tôi dựa vào thư viện Cloud Storage để xoá hình ảnh trong Cloud Storage. Chúng tôi khai báo một phần phụ thuộc trên Cloud Firestore để xoá cả siêu dữ liệu hình ảnh mà chúng tôi đã lưu trữ trước đây. Ngoài ra, chúng tôi còn sử dụng SDK CloudEvents và thư viện Sự kiện của Google để đọc các sự kiện CloudEvents do Eventarc gửi. Express là một khung web dành cho JavaScript / Nút. Bluebird được sử dụng để xử lý lời hứa.

index.js

Hãy xem xét kỹ hơn mã index.js của chúng ta:

const express = require('express');
const {Storage} = require('@google-cloud/storage');
const Firestore = require('@google-cloud/firestore');
const { HTTP } = require("cloudevents");
const {toStorageObjectData} = require('@google/events/cloud/storage/v1/StorageObjectData');

Chúng tôi yêu cầu nhiều phần phụ thuộc cần thiết để chạy chương trình: Express là khung web Nút mà chúng tôi sẽ sử dụng, Bluebird là thư viện xử lý các lời hứa về JavaScript, Storage và Firestore hoạt động tương ứng với Google Cloud Storage (bộ chứa hình ảnh của chúng tôi) và kho dữ liệu Cloud Firestore. Ngoài ra, chúng tôi yêu cầu CloudEvent đọc CloudEvent do Eventarc StoreObjectData gửi từ thư viện Sự kiện của Google để đọc nội dung sự kiện trên Cloud Storage của CloudEvent.

const app = express();
app.use(express.json());

app.post('/', async (req, res) => {
    try {
        const cloudEvent = HTTP.toEvent({ headers: req.headers, body: req.body });
        console.log(cloudEvent);


        /* ... */

    } catch (err) {
        console.log(`Error: ${err}`);
        res.status(500).send(err);
    }
});

Ở trên, chúng ta có cấu trúc của trình xử lý Nút: ứng dụng phản hồi các yêu cầu POST qua HTTP. Nó đọc CloudEvent từ yêu cầu HTTP và chúng tôi đang xử lý một số lỗi trong trường hợp có sự cố. Bây giờ, hãy cùng xem bên trong cấu trúc này là gì.

Bước tiếp theo là truy xuất và phân tích cú pháp nội dung CloudEvent và truy xuất tên đối tượng:

const storageObjectData = toStorageObjectData(cloudEvent.data);
console.log(storageObjectData);

const objectName = storageObjectData.name;

Sau khi biết tên hình ảnh, chúng tôi có thể xoá hình ảnh đó khỏi bộ chứa hình thu nhỏ:

try {
    await storage.bucket(bucketThumbnails).file(objectName).delete();
    console.log(`Deleted '${objectName}' from bucket '${bucketThumbnails}'.`);
}
catch(err) {
    console.log(`Failed to delete '${objectName}' from bucket '${bucketThumbnails}': ${err}.`);
}

Bước cuối cùng, hãy xoá siêu dữ liệu hình ảnh khỏi bộ sưu tập Firestore:

try {
    const pictureStore = new Firestore().collection('pictures');
    const docRef = pictureStore.doc(objectName);
    await docRef.delete();

    console.log(`Deleted '${objectName}' from Firestore collection 'pictures'`);
}
catch(err) {
    console.log(`Failed to delete '${objectName}' from Firestore: ${err}.`);
}

res.status(200).send(`Processed '${objectName}'.`);

Bây giờ, đã đến lúc để tập lệnh Nút xử lý các yêu cầu gửi đến. Ngoài ra, hãy kiểm tra để đảm bảo bạn đã thiết lập các biến môi trường bắt buộc:

app.listen(PORT, () => {
    if (!bucketThumbnails) throw new Error("BUCKET_THUMBNAILS not set");
    console.log(`Started service on port ${PORT}`);
});

7. Kiểm thử cục bộ

Kiểm thử mã trên thiết bị để đảm bảo mã hoạt động trước khi triển khai lên đám mây.

Bên trong thư mục garbage-collector/nodejs, hãy cài đặt các phần phụ thuộc npm và khởi động máy chủ:

export BUCKET_THUMBNAILS=thumbnails-$GOOGLE_CLOUD_PROJECT

npm install; npm start

Nếu mọi thứ diễn ra suôn sẻ, máy chủ sẽ khởi động trên cổng 8080:

Started service on port 8080

Sử dụng CTRL-C để thoát.

8. Xây dựng và triển khai Cloud Run

Trước khi triển khai lên Cloud Run, hãy đặt khu vực Cloud Run thành một trong những khu vực và nền tảng được hỗ trợ thành managed:

REGION=europe-west1
gcloud config set run/region $REGION
gcloud config set run/platform managed

Bạn có thể kiểm tra để đảm bảo cấu hình đã được thiết lập:

gcloud config list

...
[run]
platform = managed
region = europe-west1

Thay vì tạo và xuất bản hình ảnh vùng chứa bằng Cloud Build theo cách thủ công, bạn cũng có thể dựa vào Cloud Run để tạo hình ảnh vùng chứa cho mình bằng cách sử dụng Google Cloud Buildpacks.

Chạy lệnh sau để tạo hình ảnh vùng chứa bằng Google Cloud Buildpack rồi triển khai hình ảnh vùng chứa cho Cloud Run:

SERVICE_NAME=garbage-collector-service

gcloud run deploy $SERVICE_NAME \
    --source . \
    --no-allow-unauthenticated \
    --update-env-vars BUCKET_THUMBNAILS=$BUCKET_THUMBNAILS

Lưu ý cờ –-source. Thao tác này sẽ gắn cờ Cloud Run để sử dụng Google Cloud Buildpacks nhằm tạo hình ảnh vùng chứa mà không có Dockerfile. Cờ --no-allow-unauthenticated khiến dịch vụ Cloud Run trở thành dịch vụ nội bộ chỉ do các tài khoản dịch vụ cụ thể kích hoạt. Sau đó, bạn sẽ tạo một Trình kích hoạt bằng tài khoản dịch vụ điện toán mặc định có vai trò run.invoker để gọi các dịch vụ Cloud Run nội bộ.

9. Tạo điều kiện kích hoạt

Trong Eventarc, một Trình kích hoạt xác định dịch vụ nào sẽ nhận loại sự kiện nào. Trong trường hợp này, bạn muốn dịch vụ nhận các sự kiện khi một tệp bị xoá trong một bộ chứa.

Đặt vị trí của Trình kích hoạt trong cùng một khu vực với nhóm hình ảnh đã tải lên:

gcloud config set eventarc/location eu

Tạo điều kiện kích hoạt CheckLog để lọc các sự kiện storage.objects.delete và gửi đến dịch vụ Cloud Run:

BUCKET_IMAGES=uploaded-pictures-$GOOGLE_CLOUD_PROJECT

gcloud eventarc triggers create trigger-$SERVICE_NAME \
  --destination-run-service=$SERVICE_NAME \
  --destination-run-region=$REGION \
  --event-filters="type=google.cloud.storage.object.v1.deleted" \
  --event-filters="bucket=$BUCKET_IMAGES" \
  --service-account=$PROJECT_NUMBER-compute@developer.gserviceaccount.com

Bạn có thể kiểm tra kỹ để đảm bảo Trình kích hoạt được tạo bằng lệnh sau:

gcloud eventarc triggers list

10. Kiểm thử dịch vụ

Để kiểm tra xem dịch vụ có đang hoạt động hay không, hãy chuyển đến bộ chứa uploaded-pictures và xoá một trong các ảnh. Trong nhật ký của dịch vụ, bạn sẽ thấy rằng dịch vụ này đã xoá ảnh có liên quan trong bộ chứa thumbnails, đồng thời xoá tài liệu của dịch vụ đó khỏi bộ sưu tập của pictures trên Firestore.

519abf90e7ea4d12.pngs

11. Dọn dẹp (Không bắt buộc)

Nếu không có ý định tiếp tục sử dụng các phòng thí nghiệm khác trong chuỗi chương trình này, bạn có thể dọn dẹp các tài nguyên để tiết kiệm chi phí và trở thành một công dân tốt về công nghệ đám mây. Bạn có thể dọn dẹp từng tài nguyên như sau.

Xoá dịch vụ:

gcloud run services delete $SERVICE_NAME -q

Xoá trình kích hoạt Eventarc:

gcloud eventarc triggers delete trigger-$SERVICE_NAME -q

Ngoài ra, bạn có thể xoá toàn bộ dự án theo cách sau:

gcloud projects delete $GOOGLE_CLOUD_PROJECT

12. Xin chúc mừng!

Xin chúc mừng! Bạn đã tạo một dịch vụ Cloud Run, trình thu thập dữ liệu rác hình ảnh. Dịch vụ này được kích hoạt bởi Eventarc, một dịch vụ mới để nhận các sự kiện trong Cloud Run. Khi một ảnh bị xoá khỏi bộ chứa ảnh, dịch vụ sẽ nhận được một sự kiện từ Eventarc. Sau đó, hệ thống sẽ xoá hình ảnh khỏi bộ chứa hình thu nhỏ, đồng thời xoá hình ảnh đó khỏi bộ sưu tập ảnh trên Firestore.

Nội dung đã đề cập

  • Cloud Run
  • Cloud Storage
  • Cloud Firestore
  • Eventarc