1. Giới thiệu

Bạn có thể sử dụng Quy trình công việc để tạo quy trình công việc không máy chủ, liên kết một loạt các tác vụ không máy chủ với nhau theo thứ tự mà bạn xác định. Bạn có thể kết hợp sức mạnh của các API của Google Cloud, các sản phẩm không máy chủ như Cloud Functions và Cloud Run, cũng như các lệnh gọi đến các API bên ngoài để tạo các ứng dụng không máy chủ linh hoạt.
Workflows không yêu cầu quản lý cơ sở hạ tầng và có thể mở rộng quy mô một cách liền mạch theo nhu cầu, kể cả khi giảm quy mô xuống 0. Với mô hình thanh toán theo mức sử dụng, bạn chỉ trả tiền cho thời gian thực thi.
Trong lớp học lập trình này, bạn sẽ tìm hiểu cách kết nối nhiều dịch vụ của Google Cloud và API HTTP bên ngoài với Workflows. Cụ thể hơn, bạn sẽ kết nối 2 dịch vụ Cloud Functions công khai, 1 dịch vụ Cloud Run riêng tư và một API HTTP công khai bên ngoài vào một quy trình.
Kiến thức bạn sẽ học được
- Kiến thức cơ bản về Workflows.
- Cách kết nối Cloud Functions công khai với quy trình công việc.
- Cách kết nối các dịch vụ Cloud Run riêng tư với Workflows.
- Cách kết nối các API HTTP bên ngoài với quy trình công việc.
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 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 G Suite, bạn phải tạo một tài khoản.)
Hãy nhớ mã dự án, một tên duy nhất trên tất cả các dự án trên Google Cloud (tên ở trên đã được sử dụng và sẽ không hoạt động đối với bạn, xin lỗi!). Sau này trong lớp học lập trình này, chúng ta sẽ gọi nó là PROJECT_ID.
- 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 của Google 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ó. Hãy nhớ làm theo mọi hướng dẫn trong phần "Dọn dẹp" để biết cách 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. 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í trị giá 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 GCP, 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ó 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 chỉ cần một trình duyệt là có thể thực hiện mọi thao tác trong phòng thí nghiệm này.
3. Tổng quan về quy trình công việc
Thông tin cơ bản
Quy trình công việc bao gồm một chuỗi các bước được mô tả bằng cú pháp dựa trên YAML của Workflows. Đây là định nghĩa của quy trình công việc. Để biết nội dung giải thích chi tiết về cú pháp YAML của quy trình công việc, hãy xem trang Tài liệu tham khảo về cú pháp.
Khi được tạo, quy trình công việc sẽ được triển khai, giúp quy trình công việc sẵn sàng thực thi. Quá trình thực thi là một lần chạy duy nhất của logic có trong định nghĩa của quy trình công việc. Tất cả các lần thực thi quy trình đều độc lập và sản phẩm hỗ trợ một số lượng lớn các lần thực thi đồng thời.
Bật các dịch vụ
Trong lớp học lập trình này, bạn sẽ kết nối Cloud Functions, các dịch vụ Cloud Run với Workflows. Bạn cũng sẽ sử dụng Cloud Build và Cloud Storage trong quá trình tạo dịch vụ.
Bật tất cả các dịch vụ cần thiết:
gcloud services enable \ cloudfunctions.googleapis.com \ run.googleapis.com \ workflows.googleapis.com \ cloudbuild.googleapis.com \ storage.googleapis.com
Trong bước tiếp theo, bạn sẽ kết nối 2 Cloud Functions với nhau trong một quy trình.
4. Triển khai Cloud Function đầu tiên
Hàm đầu tiên là trình tạo số ngẫu nhiên trong Python.
Tạo và chuyển đến một thư mục cho mã hàm:
mkdir ~/randomgen cd ~/randomgen
Tạo một tệp main.py trong thư mục có nội dung sau:
import random, json
from flask import jsonify
def randomgen(request):
randomNum = random.randint(1,100)
output = {"random":randomNum}
return jsonify(output)
Khi nhận được một yêu cầu HTTP, Functions này sẽ tạo một số ngẫu nhiên từ 1 đến 100 và trả về cho phương thức gọi ở định dạng JSON.
Hàm này dựa vào Flask để xử lý HTTP và chúng ta cần thêm hàm đó làm phần phụ thuộc. Các phần phụ thuộc trong Python được quản lý bằng pip và thể hiện trong một tệp siêu dữ liệu có tên là requirements.txt.
Tạo một tệp requirements.txt trong cùng thư mục có nội dung sau:
flask>=1.0.2
Triển khai hàm bằng một trình kích hoạt HTTP và cho phép các yêu cầu chưa xác thực bằng lệnh này:
gcloud functions deploy randomgen \
--runtime python312 \
--trigger-http \
--allow-unauthenticated
Sau khi triển khai hàm, bạn có thể thấy URL của hàm trong thuộc tính url xuất hiện trong bảng điều khiển hoặc xuất hiện khi dùng lệnh gcloud functions describe.
Bạn cũng có thể truy cập vào URL của hàm bằng lệnh curl sau:
curl $(gcloud functions describe randomgen --format='value(url)')
Hàm này đã sẵn sàng cho quy trình công việc.
5. Triển khai Cloud Functions thứ hai
Hàm thứ hai là hàm nhân. Thao tác này nhân giá trị đầu vào nhận được với 2.
Tạo và chuyển đến một thư mục cho mã hàm:
mkdir ~/multiply cd ~/multiply
Tạo một tệp main.py trong thư mục có nội dung sau:
import random, json
from flask import jsonify
def multiply(request):
request_json = request.get_json()
output = {"multiplied":2*request_json['input']}
return jsonify(output)
Khi nhận được một yêu cầu HTTP, hàm này sẽ trích xuất input từ nội dung JSON, nhân với 2 rồi trả về cho phương thức gọi ở định dạng JSON.
Tạo tệp requirements.txt tương tự trong cùng một thư mục với nội dung sau:
flask>=1.0.2
Triển khai hàm bằng một trình kích hoạt HTTP và cho phép các yêu cầu chưa xác thực bằng lệnh này:
gcloud functions deploy multiply \
--runtime python312 \
--trigger-http \
--allow-unauthenticated
Sau khi triển khai hàm, bạn cũng có thể truy cập vào URL của hàm đó bằng lệnh curl sau:
curl $(gcloud functions describe multiply --format='value(url)') \
-X POST \
-H "content-type: application/json" \
-d '{"input": 5}'
Hàm này đã sẵn sàng cho quy trình công việc.
6. Kết nối hai Cloud Functions
Trong quy trình công việc đầu tiên, hãy kết nối 2 hàm với nhau.
Tạo tệp workflow.yaml có nội dung sau.
- randomgenFunction:
call: http.get
args:
url: https://<region>-<project-id>.cloudfunctions.net/randomgen
result: randomgenResult
- multiplyFunction:
call: http.post
args:
url: https://<region>-<project-id>.cloudfunctions.net/multiply
body:
input: ${randomgenResult.body.random}
result: multiplyResult
- returnResult:
return: ${multiplyResult}
Trong quy trình này, bạn sẽ nhận được một số ngẫu nhiên từ hàm đầu tiên và truyền số đó đến hàm thứ hai. Kết quả là số ngẫu nhiên đã nhân.
Triển khai quy trình công việc đầu tiên:
gcloud workflows deploy workflow --source=workflow.yaml
Thực thi quy trình công việc đầu tiên:
gcloud workflows execute workflow
Sau khi quy trình được thực thi, bạn có thể xem kết quả bằng cách truyền mã thực thi được cung cấp ở bước trước:
gcloud workflows executions describe <your-execution-id> --workflow workflow
Kết quả sẽ bao gồm result và state:
result: '{"body":{"multiplied":108},"code":200 ... }
...
state: SUCCEEDED
7. Kết nối một API HTTP bên ngoài
Tiếp theo, bạn sẽ kết nối math.js làm dịch vụ bên ngoài trong quy trình công việc.
Trong math.js, bạn có thể đánh giá các biểu thức toán học như sau:
curl https://api.mathjs.org/v4/?'expr=log(56)'
Lần này, bạn sẽ sử dụng Cloud Console để cập nhật quy trình làm việc của chúng ta. Tìm Workflows trong Google Cloud Console:

Tìm quy trình làm việc của bạn rồi nhấp vào thẻ Definition:

Chỉnh sửa định nghĩa quy trình công việc và thêm một lệnh gọi đến math.js.
- randomgenFunction:
call: http.get
args:
url: https://<region>-<project-id>.cloudfunctions.net/randomgen
result: randomgenResult
- multiplyFunction:
call: http.post
args:
url: https://<region>-<project-id>.cloudfunctions.net/multiply
body:
input: ${randomgenResult.body.random}
result: multiplyResult
- logFunction:
call: http.get
args:
url: https://api.mathjs.org/v4/
query:
expr: ${"log(" + string(multiplyResult.body.multiplied) + ")"}
result: logResult
- returnResult:
return: ${logResult}
Giờ đây, quy trình công việc sẽ truyền đầu ra của hàm nhân vào một lệnh gọi hàm nhật ký trong math.js.
Giao diện người dùng sẽ hướng dẫn bạn chỉnh sửa và triển khai quy trình công việc. Sau khi triển khai, hãy nhấp vào Execute để thực thi quy trình công việc. Bạn sẽ thấy thông tin chi tiết về quá trình thực thi:

Lưu ý mã trạng thái 200 và body có đầu ra của hàm nhật ký.
Bạn vừa tích hợp một dịch vụ bên ngoài vào quy trình làm việc của chúng tôi, thật tuyệt!
8. Triển khai dịch vụ Cloud Run
Trong phần cuối cùng, hãy hoàn tất quy trình bằng cách gọi một dịch vụ Cloud Run riêng tư. Điều này có nghĩa là quy trình công việc cần được xác thực để gọi dịch vụ Cloud Run.
Dịch vụ Cloud Run trả về math.floor của số được truyền vào.
Tạo và chuyển đến một thư mục cho mã dịch vụ:
mkdir ~/floor cd ~/floor
Tạo một tệp app.py trong thư mục có nội dung sau:
import json
import logging
import os
import math
from flask import Flask, request
app = Flask(__name__)
@app.route('/', methods=['POST'])
def handle_post():
content = json.loads(request.data)
input = float(content['input'])
return f"{math.floor(input)}", 200
if __name__ != '__main__':
# Redirect Flask logs to Gunicorn logs
gunicorn_logger = logging.getLogger('gunicorn.error')
app.logger.handlers = gunicorn_logger.handlers
app.logger.setLevel(gunicorn_logger.level)
app.logger.info('Service started...')
else:
app.run(debug=True, host='0.0.0.0', port=int(os.environ.get('PORT', 8080)))
Cloud Run triển khai các vùng chứa, vì vậy bạn cần có Dockerfile và vùng chứa của bạn cần liên kết với biến môi trường 0.0.0.0 và PORT, do đó có đoạn mã ở trên.
Khi nhận được một yêu cầu HTTP, hàm này sẽ trích xuất input từ nội dung JSON, gọi math.floor và trả kết quả về cho phương thức gọi.
Trong cùng một thư mục, hãy tạo Dockerfile sau đây:
# Use an official lightweight Python image. # https://hub.docker.com/_/python FROM python:3.7-slim # Install production dependencies. RUN pip install Flask gunicorn # Copy local code to the container image. WORKDIR /app COPY . . # Run the web service on container startup. Here we use the gunicorn # webserver, with one worker process and 8 threads. # For environments with multiple CPU cores, increase the number of workers # to be equal to the cores available. CMD exec gunicorn --bind 0.0.0.0:8080 --workers 1 --threads 8 app:app
Tạo vùng chứa:
export SERVICE_NAME=floor
gcloud builds submit --tag gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME}
Sau khi tạo vùng chứa, hãy triển khai lên Cloud Run. Hãy lưu ý cờ no-allow-unauthenticated. Điều này đảm bảo rằng dịch vụ chỉ chấp nhận các lệnh gọi đã xác thực:
gcloud run deploy ${SERVICE_NAME} \
--image gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME} \
--platform managed \
--no-allow-unauthenticated
Sau khi triển khai, dịch vụ này đã sẵn sàng cho quy trình làm việc.
9. Kết nối dịch vụ Cloud Run
Trước khi có thể định cấu hình quy trình công việc để gọi dịch vụ Cloud Run riêng tư, bạn cần tạo một tài khoản dịch vụ để quy trình công việc sử dụng:
export SERVICE_ACCOUNT=workflows-sa
gcloud iam service-accounts create ${SERVICE_ACCOUNT}
Cấp vai trò run.invoker cho tài khoản dịch vụ. Thao tác này sẽ cho phép tài khoản dịch vụ gọi các dịch vụ Cloud Run đã xác thực:
gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
--member "serviceAccount:${SERVICE_ACCOUNT}@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
--role "roles/run.invoker"
Cập nhật định nghĩa quy trình công việc trong workflow.yaml để thêm dịch vụ Cloud Run. Lưu ý rằng bạn cũng đang thêm trường auth để đảm bảo Workflows truyền mã thông báo xác thực trong các lệnh gọi đến dịch vụ Cloud Run:
- randomgenFunction:
call: http.get
args:
url: https://<region>-<project-id>.cloudfunctions.net/randomgen
result: randomgenResult
- multiplyFunction:
call: http.post
args:
url: https://<region>-<project-id>.cloudfunctions.net/multiply
body:
input: ${randomgenResult.body.random}
result: multiplyResult
- logFunction:
call: http.get
args:
url: https://api.mathjs.org/v4/
query:
expr: ${"log(" + string(multiplyResult.body.multiplied) + ")"}
result: logResult
- floorFunction:
call: http.post
args:
url: https://floor-<random-hash>.run.app
auth:
type: OIDC
body:
input: ${logResult.body}
result: floorResult
- returnResult:
return: ${floorResult}
Cập nhật quy trình làm việc. Thời gian này trôi qua trong tài khoản dịch vụ:
gcloud workflows deploy workflow \
--source=workflow.yaml \
--service-account=${SERVICE_ACCOUNT}@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com
Thực thi quy trình công việc:
gcloud workflows execute workflow
Trong vài giây, bạn có thể xem quá trình thực thi quy trình công việc để xem kết quả:
gcloud workflows executions describe <your-execution-id> --workflow workflow
Kết quả sẽ bao gồm số nguyên result và state:
result: '{"body":"5","code":200 ... }
...
state: SUCCEEDED
10. Xin chúc mừng!
Chúc mừng bạn đã hoàn thành lớp học lập trình này.
Nội dung đã đề cập
- Kiến thức cơ bản về Workflows.
- Cách kết nối Cloud Functions công khai với quy trình công việc.
- Cách kết nối các dịch vụ Cloud Run riêng tư với Workflows.
- Cách kết nối các API HTTP bên ngoài với quy trình công việc.