1. Giới thiệu

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. Nó cho phép bạn xây dựng các cấu trúc hướng sự kiện, trong đó các vi dịch vụ được liên kết lỏng lẻo và phân tán. Nền tảng này sẽ xử lý việc tiếp nhận, phân phối, bảo mật, uỷ quyền và xử lý lỗi cho bạn.
Workflows là một nền tảng điều phối được quản lý toàn diện, thực thi các dịch vụ theo thứ tự mà bạn xác định: một quy trình công việc. Các quy trình này có thể kết hợp các dịch vụ được lưu trữ trên Cloud Run hoặc Cloud Functions, các dịch vụ của Google Cloud như Cloud Vision AI và BigQuery, cũng như mọi API dựa trên HTTP.
Trong lớp học lập trình này, bạn sẽ tạo một quy trình điều phối dựa trên sự kiện của các vi dịch vụ để xử lý hình ảnh. Bạn sẽ sử dụng Workflows để điều phối thứ tự, đầu vào và đầu ra của 4 Cloud Functions xử lý hình ảnh. Sau đó, bạn sẽ bật quy trình điều phối để phản hồi các sự kiện Cloud Storage theo cách kết hợp lỏng lẻo với Eventarc.
Cuối cùng, bạn sẽ có được một kiến trúc linh hoạt nhưng có cấu trúc không cần máy chủ để xử lý hình ảnh.

Kiến thức bạn sẽ học được
- Tổng quan về Eventarc và Workflows
- Cách triển khai các dịch vụ Cloud Functions
- Cách điều phối các dịch vụ bằng quy trình công việc
- Cách tạo quy trình công việc để phản hồi các sự kiện Cloud Storage bằng Eventarc
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 ứng dụng. Lưu các giá trị này dưới dạng biến PROJECT_ID và REGION. Hãy xem vị trí của Cloud Functions để biết các khu vực có sẵn.
PROJECT_ID=your-project-id gcloud config set project $PROJECT_ID
Lấy mã nguồn
Mã nguồn của ứng dụng nằm trong thư mục processing-pipelines của kho lưu trữ eventarc-samples.
Sao chép kho lưu trữ:
git clone https://github.com/GoogleCloudPlatform/eventarc-samples.git
Chuyển đến thư mục eventarc-samples/processing-pipelines:
cd eventarc-samples/processing-pipelines
3. Tổng quan về cấu trúc
Cấu trúc của ứng dụng như sau:

- Một hình ảnh được lưu vào bộ chứa đầu vào, tạo ra một sự kiện tạo Cloud Storage.
- Sự kiện tạo Cloud Storage được Eventarc đọc thông qua một trình kích hoạt Cloud Storage và được truyền đến Workflows dưới dạng một CloudEvent.
- Trong bước đầu tiên của quy trình, Bộ lọc (một dịch vụ Cloud Functions) sẽ dùng Vision API để xác định xem hình ảnh có an toàn hay không. Nếu hình ảnh an toàn, Workflows sẽ tiếp tục với các bước tiếp theo.
- Trong bước thứ hai của quy trình làm việc, Labeler (một dịch vụ Cloud Functions) sẽ trích xuất nhãn của hình ảnh bằng Vision API và lưu nhãn vào vùng chứa đầu ra.
- Ở bước thứ ba, Resizer (một dịch vụ Cloud Functions khác) sẽ đổi kích thước hình ảnh bằng ImageSharp và lưu hình ảnh đã đổi kích thước vào vùng chứa đầu ra.
- Ở bước cuối cùng, Watermarker (một dịch vụ Cloud Functions khác) sẽ thêm hình mờ của các nhãn từ Labeler vào hình ảnh đã đổi kích thước bằng ImageSharp và lưu hình ảnh vào vùng lưu trữ đầu ra.
Ứng dụng được kích hoạt bởi một sự kiện Cloud Storage, do đó, ứng dụng này là hướng sự kiện. Việc xử lý hình ảnh diễn ra trong một quy trình làm việc, do đó, đây là một quy trình điều phối. Cuối cùng, đây là một quy trình điều phối dựa trên sự kiện cho một kiến trúc không máy chủ linh hoạt nhưng có cấu trúc để xử lý hình ảnh.
4. Tạo nhóm
Tạo một vùng lưu trữ đầu vào để người dùng tải hình ảnh lên và một vùng lưu trữ đầu ra để quy trình xử lý hình ảnh lưu hình ảnh đã xử lý.
Chạy lệnh sau trong Cloud Shell:
REGION=us-central1 BUCKET1=$PROJECT_ID-images-input-$RANDOM BUCKET2=$PROJECT_ID-images-output-$RANDOM gsutil mb -l $REGION gs://$BUCKET1 gsutil mb -l $REGION gs://$BUCKET2
5. Triển khai dịch vụ lọc
Hãy bắt đầu bằng cách triển khai dịch vụ đầu tiên. Dịch vụ Cloud Functions này nhận thông tin về nhóm và tệp, xác định xem hình ảnh có an toàn hay không bằng Vision API và trả về kết quả.
Trước tiên, hãy bật các dịch vụ bắt buộc cho Cloud Functions thế hệ thứ 2 và Vision API:
gcloud services enable \ artifactregistry.googleapis.com \ cloudbuild.googleapis.com \ cloudfunctions.googleapis.com \ run.googleapis.com \ vision.googleapis.com
Trong thư mục processing-pipelines cấp cao nhất, hãy triển khai dịch vụ:
SERVICE_NAME=filter gcloud functions deploy $SERVICE_NAME \ --gen2 \ --allow-unauthenticated \ --runtime dotnet3 \ --trigger-http \ --region=$REGION \ --entry-point Filter.Function \ --set-build-env-vars GOOGLE_BUILDABLE=image-v3/filter/csharp
Sau khi triển khai hàm, hãy đặt URL dịch vụ trong một biến. Chúng ta sẽ cần biến này sau:
FILTER_URL=$(gcloud functions describe $SERVICE_NAME --region=$REGION --gen2 --format 'value(serviceConfig.uri)')
6. Triển khai dịch vụ gắn nhãn
Dịch vụ Cloud Functions thứ hai nhận thông tin về vùng lưu trữ và tệp, trích xuất nhãn của hình ảnh bằng Vision API và lưu nhãn vào vùng lưu trữ đầu ra.
Trong thư mục processing-pipelines cấp cao nhất, hãy triển khai dịch vụ:
SERVICE_NAME=labeler gcloud functions deploy $SERVICE_NAME \ --gen2 \ --allow-unauthenticated \ --runtime dotnet3 \ --trigger-http \ --region=$REGION \ --set-env-vars BUCKET=$BUCKET2 \ --entry-point Labeler.Function \ --set-build-env-vars GOOGLE_BUILDABLE=image-v2/labeler/csharp
Sau khi triển khai hàm, hãy đặt URL dịch vụ trong một biến. Chúng ta sẽ cần biến này sau:
LABELER_URL=$(gcloud functions describe $SERVICE_NAME --region=$REGION --gen2 --format 'value(serviceConfig.uri)')
7. Triển khai dịch vụ thay đổi kích thước
Dịch vụ Cloud Functions này nhận thông tin về vùng lưu trữ và tệp, đổi kích thước hình ảnh bằng ImageSharp rồi lưu hình ảnh vào vùng lưu trữ đầu ra.
Trong thư mục processing-pipelines cấp cao nhất, hãy triển khai dịch vụ:
SERVICE_NAME=resizer gcloud functions deploy $SERVICE_NAME \ --gen2 \ --allow-unauthenticated \ --runtime dotnet3 \ --trigger-http \ --region=$REGION \ --set-env-vars BUCKET=$BUCKET2 \ --entry-point Resizer.Function \ --set-build-env-vars GOOGLE_BUILDABLE=image-v2/resizer/csharp \ --timeout=120s
Lưu ý giá trị timeout là 2 phút để cho phép hàm thay đổi kích thước có thêm thời gian xử lý.
Sau khi triển khai hàm, hãy đặt URL dịch vụ trong một biến. Chúng ta sẽ cần biến này sau:
RESIZER_URL=$(gcloud functions describe $SERVICE_NAME --region=$REGION --gen2 --format 'value(serviceConfig.uri)')
8. Triển khai dịch vụ đánh dấu bản quyền
Dịch vụ Cloud Functions này nhận thông tin về vùng lưu trữ, tệp và nhãn, đọc tệp, thêm nhãn làm hình mờ vào hình ảnh bằng ImageSharp và lưu hình ảnh vào vùng lưu trữ đầu ra.
Trong thư mục processing-pipelines cấp cao nhất, hãy triển khai dịch vụ:
SERVICE_NAME=watermarker gcloud functions deploy $SERVICE_NAME \ --gen2 \ --allow-unauthenticated \ --runtime dotnet3 \ --trigger-http \ --region=$REGION \ --set-env-vars BUCKET=$BUCKET2 \ --entry-point Watermarker.Function \ --set-build-env-vars GOOGLE_BUILDABLE=image-v2/watermarker/csharp
Sau khi triển khai hàm, hãy đặt URL dịch vụ trong một biến. Chúng ta sẽ cần biến này sau:
WATERMARKER_URL=$(gcloud functions describe $SERVICE_NAME --region=$REGION --gen2 --format 'value(serviceConfig.uri)')
Tại thời điểm này, cả 4 Cloud Functions đều phải được triển khai và chạy:

9. Xác định và triển khai quy trình làm việc
Sử dụng quy trình để kết hợp các dịch vụ bộ lọc, trình gắn nhãn, trình đổi kích thước và trình đóng dấu bản quyền vào một quy trình. Quy trình công việc sẽ điều phối việc gọi các dịch vụ này theo thứ tự và với các thông số mà chúng ta xác định.
Trước tiên, hãy bật các dịch vụ bắt buộc cho quy trình công việc:
gcloud services enable \ workflows.googleapis.com \ workflowexecutions.googleapis.com
Định nghĩa
Quy trình công việc nhận một CloudEvent làm tham số. Giá trị này sẽ đến từ Eventarc sau khi chúng ta tạo một trình kích hoạt. Trong hai bước đầu tiên, quy trình công việc sẽ ghi lại sự kiện và trích xuất thông tin về nhóm và tệp từ sự kiện:
main:
params: [event]
steps:
- log_event:
call: sys.log
args:
text: ${event}
severity: INFO
- extract_bucket_and_file:
assign:
- bucket: ${event.data.bucket}
- file: ${event.data.name}
Trong bước filter, quy trình công việc sẽ gọi dịch vụ lọc mà chúng ta đã triển khai trước đó. Sau đó, hệ thống sẽ ghi nhật ký và kiểm tra độ an toàn của tệp:
- filter:
call: http.post
args:
url: FILTER_URL # TODO: Replace
auth:
type: OIDC
body:
bucket: ${bucket}
file: ${file}
result: filterResponse
- log_safety:
call: sys.log
args:
text: ${filterResponse.body.safe}
severity: INFO
- check_safety:
switch:
- condition: ${filterResponse.body.safe == true}
next: label
next: end
Trong bước label, quy trình công việc sẽ gọi dịch vụ gắn nhãn và ghi lại phản hồi (3 nhãn hàng đầu):
- label:
call: http.post
args:
url: LABELER_URL # TODO: Replace
auth:
type: OIDC
body:
bucket: ${bucket}
file: ${file}
result: labelResponse
Ở bước resize, Workflows sẽ gọi dịch vụ thay đổi kích thước và ghi lại phản hồi (thùng chứa và tệp của hình ảnh đã thay đổi kích thước):
- resize:
call: http.post
args:
url: RESIZER_URL # TODO: Replace
auth:
type: OIDC
body:
bucket: ${bucket}
file: ${file}
result: resizeResponse
Ở bước watermark, quy trình công việc sẽ gọi dịch vụ đánh dấu bản quyền bằng hình ảnh và nhãn đã đổi kích thước, đồng thời ghi lại kết quả (hình ảnh đã đổi kích thước và được đánh dấu bản quyền):
- watermark:
call: http.post
args:
url: WATERMARKER_URL # TODO: Replace
auth:
type: OIDC
body:
bucket: ${resizeResponse.body.bucket}
file: ${resizeResponse.body.file}
labels: ${labelResponse.body.labels}
result: watermarkResponse
Trong bước final, Workflows sẽ trả về mã trạng thái HTTP từ các dịch vụ gắn nhãn, đổi kích thước và đóng dấu bản quyền:
- final:
return:
label: ${labelResponse.code}
resize: ${resizeResponse.code}
watermark: ${watermarkResponse.code}
Triển khai
Trước khi triển khai quy trình công việc, hãy đảm bảo rằng các URL dịch vụ được thay thế bằng URL của các hàm đã triển khai theo cách thủ công hoặc bằng cách sử dụng sed:
Bên trong thư mục processing-pipelines cấp cao nhất, hãy chuyển đến thư mục image-v3 nơi có tệp workflows.yaml:
cd image-v3/
Chạy sed để thay thế các URL giữ chỗ bằng URL thực tế của các dịch vụ đã triển khai:
sed -i -e "s|FILTER_URL|${FILTER_URL}|" workflow.yaml
sed -i -e "s|LABELER_URL|${LABELER_URL}|" workflow.yaml
sed -i -e "s|RESIZER_URL|${RESIZER_URL}|" workflow.yaml
sed -i -e "s|WATERMARKER_URL|${WATERMARKER_URL}|" workflow.yaml
Triển khai quy trình công việc:
WORKFLOW_NAME=image-processing
gcloud workflows deploy $WORKFLOW_NAME \
--source=workflow.yaml \
--location=$REGION
Sau vài giây, bạn sẽ thấy quy trình được triển khai trong bảng điều khiển:

10. Tạo điều kiện kích hoạt
Giờ đây, quy trình công việc đã được triển khai, bước cuối cùng là kết nối quy trình đó với các sự kiện Cloud Storage bằng một trình kích hoạt Eventarc.
Thiết lập một lần
Trước tiên, hãy bật các dịch vụ bắt buộc cho Eventarc:
gcloud services enable \ eventarc.googleapis.com
Tạo một tài khoản dịch vụ mà bạn sẽ dùng trong trình kích hoạt Eventarc.
SERVICE_ACCOUNT=eventarc-trigger-imageproc-sa gcloud iam service-accounts create $SERVICE_ACCOUNT \ --display-name="Eventarc trigger image processing service account"
Cấp vai trò workflows.invoker để có thể dùng tài khoản dịch vụ này để gọi quy trình công việc từ Eventarc:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --role roles/workflows.invoker \ --member serviceAccount:$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com
Cấp vai trò eventarc.eventReceiver để có thể sử dụng tài khoản dịch vụ trong
Trình kích hoạt Cloud Storage:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --role roles/eventarc.eventReceiver \ --member serviceAccount:$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com
Cấp vai trò pubsub.publisher cho tài khoản dịch vụ Cloud Storage. Đây là điều kiện cần thiết cho trình kích hoạt Cloud Storage của Eventarc:
STORAGE_SERVICE_ACCOUNT="$(gsutil kms serviceaccount -p $PROJECT_ID)"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member serviceAccount:$STORAGE_SERVICE_ACCOUNT \
--role roles/pubsub.publisher
Tạo
Chạy lệnh sau để tạo một điều kiện kích hoạt. Trình kích hoạt này lọc các sự kiện tạo tệp mới từ bộ chứa Cloud Storage đầu vào và chuyển các sự kiện đó vào quy trình mà chúng ta đã xác định trước đó:
TRIGGER_NAME=trigger-image-processing gcloud eventarc triggers create $TRIGGER_NAME \ --location=$REGION \ --destination-workflow=$WORKFLOW_NAME \ --destination-workflow-location=$REGION \ --event-filters="type=google.cloud.storage.object.v1.finalized" \ --event-filters="bucket=$BUCKET1" \ --service-account=$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com
Bạn có thể thấy rằng sự kiện kích hoạt đã được tạo và sẵn sàng trong phần Eventarc của Cloud Console:

11. Kiểm thử quy trình
Quy trình xử lý hình ảnh đã sẵn sàng nhận các sự kiện từ Cloud Storage. Để kiểm thử quy trình, hãy tải một hình ảnh lên vùng chứa đầu vào:
gsutil cp beach.jpg gs://$BUCKET1
Ngay khi tải hình ảnh lên, bạn sẽ thấy một quy trình thực thi Workflows ở trạng thái đang hoạt động:

Sau khoảng một phút, bạn sẽ thấy quá trình thực thi thành công. Bạn cũng có thể xem đầu vào và đầu ra của quy trình công việc:

Nếu liệt kê nội dung của vùng lưu trữ đầu ra, bạn sẽ thấy hình ảnh đã đổi kích thước, hình ảnh đã đổi kích thước và có hình mờ cũng như nhãn của hình ảnh:
gsutil ls gs://$BUCKET2 gs://$PROJECT_ID-images-output-$RANDOM/beach-400x400-watermark.jpeg gs://$PROJECT_ID-images-output-$RANDOM/beach-400x400.png gs://$PROJECT_ID-images-output-$RANDOM/beach-labels.txt
Để kiểm tra lại, bạn có thể mở hình ảnh đã được đổi kích thước và gắn dấu bản quyền để xem kết quả:

12. 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!
Nội dung đã đề cập
- Tổng quan về Eventarc và Workflows
- Cách triển khai các dịch vụ Cloud Functions
- Cách điều phối các dịch vụ bằng quy trình công việc
- Cách tạo quy trình công việc để phản hồi các sự kiện Cloud Storage bằng Eventarc