從 Cloud Run 連線至全代管資料庫

1. 總覽

在本研究室中,您會將無伺服器資料庫(Spanner 與 Firestore) 與在 Cloud Run 中執行的應用程式(Go 和 Node.js) 整合。Cymbal Eats 應用程式包含多項在 Cloud Run 上執行的服務。在下列步驟中,您將設定服務使用 Cloud Spanner 關聯資料庫和 Cloud Firestore (NoSQL 文件資料庫)。透過適用於資料層級的無伺服器產品和應用程式執行階段,您可以省去所有基礎架構管理工作,專心建構應用程式,不必擔心增加負擔。

2. 課程內容

在本研究室中,您將瞭解如何執行下列操作:

  • 整合 Spanner
  • 啟用 Spanner 代管服務
  • 整合至程式碼
  • 部署程式碼連結至 Spanner
  • 整合 Firestore
  • 啟用 Firestore 代管服務
  • 整合至程式碼
  • 部署連結至 Firestore 的程式碼

3. 設定和需求

自修環境設定

  1. 登入 Google Cloud 控制台,建立新專案或重複使用現有專案。如果您還沒有 Gmail 或 Google Workspace 帳戶,請先建立帳戶

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • 「專案名稱」是這項專案參與者的顯示名稱。這是 Google API 未使用的字元字串。您可以隨時更新付款方式。
  • 所有 Google Cloud 專案的專案 ID 均不得重複,而且設定後即無法變更。Cloud 控制台會自動產生一個不重複的字串。但通常是在乎它何在在大部分的程式碼研究室中,您必須參照專案 ID (通常為 PROJECT_ID)。如果您對產生的 ID 不滿意,可以隨機產生一個 ID。或者,您也可以自行嘗試,看看是否支援。在這個步驟後,這個名稱即無法變更,而且在專案期間內仍會保持有效。
  • 資訊中的第三個值是專案編號,部分 API 會使用這個編號。如要進一步瞭解這三個值,請參閱說明文件
  1. 接下來,您需要在 Cloud 控制台中啟用計費功能,才能使用 Cloud 資源/API。執行本程式碼研究室不會產生任何費用 (如果有的話)。如要關閉資源,以免產生本教學課程結束後產生的費用,您可以刪除自己建立的資源或刪除專案。新使用者符合 $300 美元免費試用計畫的資格。

設定環境

  1. 建立專案 ID 變數
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')
export SPANNER_INSTANCE=inventory-instance
export SPANNER_DB=inventory-db
export REGION=us-east1
export SPANNER_CONNECTION_STRING=projects/$PROJECT_ID/instances/$SPANNER_INSTANCE/databases/$SPANNER_DB
  1. 啟用 Spanner、Cloud Run、Cloud Build 和 Artifact Registry API
gcloud services enable \
     compute.googleapis.com \
     spanner.googleapis.com \
     run.googleapis.com \
     cloudbuild.googleapis.com \
     artifactregistry.googleapis.com \
     firestore.googleapis.com \
     appengine.googleapis.com \
     artifactregistry.googleapis.com
  1. 複製存放區
git clone https://github.com/GoogleCloudPlatform/cymbal-eats.git
  1. 前往目錄
cd cymbal-eats/inventory-service/spanner

4. 建立及設定 Spanner 執行個體

Spanner 是庫存服務後端關聯資料庫,您會在下列步驟中建立 Spanner 執行個體、資料庫和結構定義。

建立執行個體

  1. 建立 Cloud Spanner 執行個體
gcloud spanner instances create $SPANNER_INSTANCE --config=regional-${REGION} \
--description="Cymbal Menu Inventory" --nodes=1

輸出內容範例

Creating instance...done.   
  1. 確認 Spanner 執行個體設定是否正確
gcloud spanner instances list

輸出範例

NAME: inventory-instance
DISPLAY_NAME: Cymbal Menu Inventory
CONFIG: regional-us-east1
NODE_COUNT: 1
PROCESSING_UNITS: 100
STATE: READY

建立資料庫和結構定義

建立新資料庫,並使用 Google 標準 SQL 的資料定義語言 (DDL) 來建立資料庫結構定義。

  1. 建立 DDL 檔案
echo "CREATE TABLE InventoryHistory (ItemRowID STRING (36) NOT NULL, ItemID INT64 NOT NULL, InventoryChange INT64, Timestamp TIMESTAMP) PRIMARY KEY(ItemRowID)" >> table.ddl
  1. 建立 Spanner 資料庫
gcloud spanner databases create $SPANNER_DB \
--instance=$SPANNER_INSTANCE \
--ddl-file=table.ddl

輸出範例

Creating database...done.

驗證資料庫狀態和結構定義

  1. 查看資料庫狀態
gcloud spanner databases describe $SPANNER_DB \
--instance=$SPANNER_INSTANCE

輸出範例

createTime: '2022-04-22T15:11:33.559300Z'
databaseDialect: GOOGLE_STANDARD_SQL
earliestVersionTime: '2022-04-22T15:11:33.559300Z'
encryptionInfo:
- encryptionType: GOOGLE_DEFAULT_ENCRYPTION
name: projects/cymbal-eats-7-348013/instances/menu-inventory/databases/menu-inventory
state: READY
versionRetentionPeriod: 1h
  1. 查看資料庫結構定義
gcloud spanner databases ddl describe $SPANNER_DB \
--instance=$SPANNER_INSTANCE

輸出範例

CREATE TABLE InventoryHistory (
  ItemRowID STRING(36) NOT NULL,
  ItemID INT64 NOT NULL,
  InventoryChange INT64,
  TimeStamp TIMESTAMP,
) PRIMARY KEY(ItemRowID);

5. 整合 Spanner

在本節中,您將瞭解如何將 Spanner 整合至應用程式。另外,SQL Spanner 也提供用戶端程式庫JDBC 驅動程式R2DBC 驅動程式REST APIRPC API,可讓您將 Spanner 整合至任何應用程式。

在下一節中,您將使用 Go 用戶端程式庫安裝、驗證及修改 Spanner 中的資料。

安裝用戶端程式庫

Cloud Spanner 用戶端程式庫會自動使用應用程式預設憑證 (ADC) 尋找服務帳戶憑證,讓您輕鬆整合 Cloud Spanner

設定驗證方法

Google Cloud CLI 和 Google Cloud 用戶端程式庫會自動偵測在 Google Cloud 中執行的情況,並使用目前 Cloud Run 修訂版本的執行階段服務帳戶。這項策略稱為「應用程式預設憑證」,可讓程式碼在多個環境中的可攜性。

不過,最佳做法是指派使用者自行管理的服務帳戶 (而非預設服務帳戶),建立專屬身分。

  1. 將 Spanner 資料庫管理員角色授予服務帳戶
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$PROJECT_NUMBER-compute@developer.gserviceaccount.com" \
--role="roles/spanner.databaseAdmin"

輸出範例

Updated IAM policy for project [cymbal-eats-6422-3462].
[...]

使用用戶端程式庫

Spanner 用戶端程式庫可簡化與 Spanner 整合的複雜作業,且適用於許多常見的程式設計語言。

建立 Spanner 用戶端

Spanner 用戶端是讀取資料並將其寫入 Cloud Spanner 資料庫的用戶端。除了其 Close 方法以外,用戶端仍可安全地並行使用。

下方的程式碼片段會建立 Spanner 用戶端

main.go

var dataClient *spanner.Client
...
dataClient, err = spanner.NewClient(ctx, databaseName)

您可以將用戶端視為資料庫連線:您與 Cloud Spanner 的所有互動都必須透過用戶端完成。一般而言,您會在應用程式啟動時建立「用戶端」,然後再次使用該用戶端來讀取、寫入及執行交易。每個用戶端都會使用 Cloud Spanner 中的資源。

修改資料

您可以透過多種方式插入、更新及刪除 Spanner 資料庫中的資料。以下列出可用的方法。

在本研究室中,您將使用變異來修改 Spanner 中的資料。

Spanner 中的異動

Mutation 是變異作業的容器。「變更」代表一系列的插入、更新和刪除作業,Cloud Spanner 會以不可分割的形式,將這些作業自動套用至 Cloud Spanner 資料庫中不同的資料列和資料表。

main.go

m := []*spanner.Mutation{}

m = append(m, spanner.Insert(
        "inventoryHistory",
         inventoryHistoryColumns,
        []interface{}{uuid.New().String(), element.ItemID, element.InventoryChange, time.Now()}))

程式碼片段會在商品目錄記錄表格中插入新資料列。

部署和測試

現在 Spanner 已設定完成,您也確認了將應用程式部署至 Cloud Run 的重要程式碼元素。

將應用程式部署至 Cloud Run

Cloud Run 可透過單一指令自動建構、推送及部署程式碼。在下列指令中,您會在 run 服務上呼叫 deploy 指令,傳入先前建立的執行中應用程式 (例如 SPANNER_CONNECTION_STRING) 使用的變數。

  1. 按一下「開啟終端機」
  2. 將庫存服務部署至 Cloud Run
gcloud run deploy inventory-service \
    --source . \
    --region $REGION \
    --update-env-vars SPANNER_CONNECTION_STRING=$SPANNER_CONNECTION_STRING \
    --allow-unauthenticated \
    --project=$PROJECT_ID \
    --quiet

輸出範例

Service [inventory-service] revision [inventory-service-00001-sug] has been deployed and is serving 100 percent of traffic.
Service URL: https://inventory-service-ilwytgcbca-uk.a.run.app
  1. 儲存服務網址
INVENTORY_SERVICE_URL=$(gcloud run services describe inventory-service \
  --platform managed \
  --region $REGION \
  --format=json | jq \
  --raw-output ".status.url")

測試 Cloud Run 應用程式

插入項目

  1. 在 Cloud Shell 中輸入下列指令,
POST_URL=$INVENTORY_SERVICE_URL/updateInventoryItem
curl -i -X POST ${POST_URL} \
--header 'Content-Type: application/json' \
--data-raw '[
    {
        "itemID": 1,
        "inventoryChange": 5
    }
]'

輸出範例

HTTP/2 200
access-control-allow-origin: *
content-type: application/json
x-cloud-trace-context: 10c32f0863d26521497dc26e86419f13;o=1
date: Fri, 22 Apr 2022 21:41:38 GMT
server: Google Frontend
content-length: 2

OK

查詢項目

  1. 查詢庫存服務
GET_URL=$INVENTORY_SERVICE_URL/getAvailableInventory
curl -i ${GET_URL}

回應範例

HTTP/2 200
access-control-allow-origin: *
content-type: text/plain; charset=utf-8
x-cloud-trace-context: b94f921e4c2ae90210472c88eb05ace8;o=1
date: Fri, 22 Apr 2022 21:45:50 GMT
server: Google Frontend
content-length: 166

[{"ItemID":1,"Inventory":5}]

6. Spanner 概念

Cloud Spanner 使用宣告式 SQL 陳述式查詢資料庫。SQL 陳述式可指出使用者想要什麼,但不會說明系統如何取得結果。

  1. 在終端機中,輸入下列指令,查詢先前建立記錄的資料表。
gcloud spanner databases execute-sql $SPANNER_DB \
--instance=$SPANNER_INSTANCE \
--sql='SELECT * FROM InventoryHistory WHERE ItemID=1'

輸出範例

ItemRowID: 1
ItemID: 1
InventoryChange: 3
Timestamp: 

查詢執行計畫

「查詢執行計畫」是 Spanner 用於取得結果的一系列步驟。有幾種方式可以取得特定 SQL 陳述式的結果。查詢執行計畫可透過控制台和用戶端程式庫存取。如要瞭解 Spanner 如何處理 SQL 查詢,請按照下列步驟操作:

  1. 在控制台中開啟 Cloud Spanner 執行個體頁面。
  2. 前往 Cloud Spanner 執行個體
  3. 按一下 Cloud Spanner 執行個體的名稱。在資料庫專區中,選取要查詢的資料庫。
  4. 點選查詢。
  5. 在查詢編輯器中輸入下列查詢
SELECT * FROM InventoryHistory WHERE ItemID=1
  1. 按一下「執行」
  2. 按一下「說明」

Cloud 控制台會顯示視覺化的查詢執行計畫。

149f8bae468f8b34.png

查詢最佳化工具

Cloud Spanner 查詢最佳化工具會比較替代的執行計畫,並選擇效率最高的執行計畫。隨著時間的推移,查詢最佳化工具會不斷擴大,擴大查詢執行計劃中的選擇,並提高能夠為這些選擇提供之估算的準確率,進而使查詢執行計畫更有效率。

Cloud Spanner 推出新的查詢最佳化工具版本,推出最佳化工具更新。根據預設,每個資料庫都會在新版本推出後的 30 天內,開始使用最新版的最佳化工具。

如要查看在 gcloud spanner 中執行查詢時使用的版本,請將 –query-mode 標記設為「PROFILE」

  1. 輸入下列指令即可查看最佳化工具版本
gcloud spanner databases execute-sql $SPANNER_DB --instance=$SPANNER_INSTANCE \
--query-mode=PROFILE --sql='SELECT * FROM InventoryHistory'

輸出範例

TOTAL_ELAPSED_TIME: 6.18 msecs
CPU_TIME: 5.17 msecs
ROWS_RETURNED: 1
ROWS_SCANNED: 1
OPTIMIZER_VERSION: 3
 RELATIONAL Distributed Union
 (1 execution, 0.11 msecs total latency)
 subquery_cluster_node: 1
    |
    +- RELATIONAL Distributed Union
    |  (1 execution, 0.09 msecs total latency)
    |  call_type: Local, subquery_cluster_node: 2
    |   |
    |   \- RELATIONAL Serialize Result
    |      (1 execution, 0.08 msecs total latency)
    |       |
    |       +- RELATIONAL Scan
    |       |  (1 execution, 0.08 msecs total latency)
    |       |  Full scan: true, scan_target: InventoryHistory, scan_type: TableScan
    |       |   |
    |       |   +- SCALAR Reference
    |       |   |  ItemRowID
    |       |   |
    |       |   +- SCALAR Reference
    |       |   |  ItemID
    |       |   |
    |       |   +- SCALAR Reference
    |       |   |  InventoryChange
    |       |   |
    |       |   \- SCALAR Reference
    |       |      Timestamp
    |       |
    |       +- SCALAR Reference
    |       |  $ItemRowID
    |       |
    |       +- SCALAR Reference
    |       |  $ItemID
    |       |
    |       +- SCALAR Reference
    |       |  $InventoryChange
    |       |
    |       \- SCALAR Reference
    |          $Timestamp
    |
    \- SCALAR Constant
       true

ItemRowID: 1
ItemID: 1
InventoryChange: 3
Timestamp:

更新最佳化工具版本

本研究室當下的最新版本為 4 版。接下來,您將更新 Spanner 資料表,在查詢最佳化工具中使用第 4 版。

  1. 更新最佳化工具
gcloud spanner databases ddl update $SPANNER_DB \
--instance=$SPANNER_INSTANCE \
--ddl='ALTER DATABASE InventoryHistory
SET OPTIONS (optimizer_version = 4)'

輸出範例

Schema updating...done. 
  1. 輸入下列指令,查看最佳化工具版本更新
gcloud spanner databases execute-sql $SPANNER_DB --instance=$SPANNER_INSTANCE \
--query-mode=PROFILE --sql='SELECT * FROM InventoryHistory'

輸出範例

TOTAL_ELAPSED_TIME: 8.57 msecs
CPU_TIME: 8.54 msecs
ROWS_RETURNED: 1
ROWS_SCANNED: 1
OPTIMIZER_VERSION: 4
[...]

在 Metrics Explorer 中以圖表呈現查詢最佳化工具版本

您可以使用 Cloud 控制台中的 Metrics Explorer,以圖表呈現資料庫執行個體的「查詢數量」。您可以在每個資料庫中查看目前使用的最佳化工具版本。

  1. 前往 Cloud 控制台中的「Monitoring」,然後選取左選單中的「Metrics Explorer」
  2. 在「Resource type」(資源類型) 欄位中,選取「Cloud Spanner Instance」(Cloud Spanner 執行個體)。
  3. 在「指標」欄位中,選取「查詢數」和「套用」。
  4. 在「Group By」(分組依據) 欄位中,選取「database_version」和「status」。

581b859c25790b21.png

7. 建立及設定 Firestore 資料庫

Firestore 是 NoSQL 文件資料庫,專為自動調整資源配置、提供高效能,以及協助輕鬆開發應用程式而打造。雖然 Firestore 介面與傳統資料庫具備的許多功能相同,但 NoSQL 資料庫與傳統資料庫的功能不同,說明資料物件之間的關係。

下列工作將逐步引導您建立以 Firestore 為基礎的 Cloud Run 訂購服務應用程式。排序服務會在開始訂單之前呼叫上一節建立的庫存服務,查詢 Spanner 資料庫。這項服務將確保存在足夠的廣告空間,並供應訂單。

6843abaf4263e112.png

8. Firestore 概念

資料模型

Firestore 資料庫由集合和文件組成,

b60acd63d4793a6c.png

文件

每份文件皆包含一組鍵/值組合。Firestore 經過最佳化調整,適合用來儲存大量小型文件。

5571cb2f261d2dbe.png

集合

您必須將所有文件儲存在集合中。文件可以含有子集合和巢狀物件,包括字串等原始欄位,或清單等複雜物件。

5811378cb721e5ec.png

建立 Firestore 資料庫

  1. 建立 Firestore 資料庫
gcloud firestore databases create --location=$REGION

輸出範例

Success! Selected Google Cloud Firestore Native database for cymbal-eats-6422-3462

9. 將 Firestore 整合至應用程式

在本節中,您將更新服務帳戶、新增 Firestore 存取服務帳戶、檢查及部署 Firestore 安全性規則,以及查看 Firestore 中的資料修改方式。

設定驗證方法

  1. 將 Datastore 使用者角色授予服務帳戶
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:$PROJECT_NUMBER-compute@developer.gserviceaccount.com" \
  --role="roles/datastore.user"

輸出範例

Updated IAM policy for project [cymbal-eats-6422-3462].

Firestore 安全性規則

安全性規則提供存取權控制和資料驗證機制,這種格式相當簡單明瞭。

  1. 前往 order-service/starter-code 目錄
cd ~/cymbal-eats/order-service
  1. 在雲端編輯器中開啟 Firestore.rules 檔案
cat firestore.rules

firestore.rules

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents { ⇐ All database
    match /{document=**} { ⇐ All documents
      allow read: if true; ⇐ Allow reads
    }
    match /{document=**} {
      allow write: if false; ⇐ Deny writes
    }
  }
}

警告:最佳做法是限制對 Firestore 儲存空間的存取權。為配合本研究室的學習目標,您可以執行所有讀取作業。我們不建議正式環境設定。

啟用 Firestore 代管服務

  1. 按一下「開啟終端機」
  2. 使用目前專案 ID 建立 .firebaserc 檔案。部署目標的設定會儲存在專案目錄中的 .firebaserc 檔案中。

firebaserc.tmpl

sed "s/PROJECT_ID/$PROJECT_ID/g" firebaserc.tmpl > .firebaserc
  1. 下載 Firebase 二進位檔
curl -sL https://firebase.tools | upgrade=true bash

輸出範例

-- Checking for existing firebase-tools on PATH...
Your machine already has firebase-tools@10.7.0 installed. Nothing to do.
-- All done!
  1. 部署 Firestore 規則。
firebase deploy 

輸出內容範例

=== Deploying to 'cymbal-eats-6422-3462'...

i  deploying firestore
i  cloud.firestore: checking firestore.rules for compilation errors...
✔  cloud.firestore: rules file firestore.rules compiled successfully
i  firestore: uploading rules firestore.rules...
✔  firestore: released rules firestore.rules to cloud.firestore

✔  Deploy complete!

Project Console: https://console.firebase.google.com/project/cymbal-eats-6422-3462/overview

修改資料

集合和文件會以隱含的方式建立在 Firestore 中。只要將資料指派給集合中的文件即可。如果集合或文件不存在,FireEye 會建立集合或文件。

將資料新增至 Firestore

您可以透過下列幾種方式將資料寫入 Cloud Firestore:

  • 在集合內設定文件的資料,並明確指定文件 ID。
  • 將新文件加入集合。在這種情況下,Cloud Firestore 會自動產生文件 ID。
  • 使用自動產生的 ID 建立空白文件,之後再指派資料給文件。

下一節將逐步說明如何使用 Set 方法建立文件。

設定文件

請使用 set() 方法建立文件。使用 set() 方法時,您必須指定要建立文件的 ID。

請看下方的程式碼片段。

index.js

const orderDoc = db.doc(`orders/123`);
await orderDoc.set({
    orderNumber: 123,
    name: Anne,
    address: 555 Bright Street,
    city: Mountain View,
    state: CA,
    zip: 94043,
    orderItems: [id: 1],
    status: 'New'
  });

這個程式碼會建立一份文件,指明使用者產生的文件 ID 123。如要讓 Firestore 代您產生 ID,請使用 add()create() 方法。

更新文件

更新方法 update() 可讓您更新部分文件欄位,而不必覆寫整份文件。

在下方程式碼片段中,程式碼將訂單 123 更新為訂單 123

index.js

const orderDoc = db.doc(`orders/123`);
await orderDoc.update(name: "Anna");

刪除文件

在 Firestore 中,您可以刪除文件中的集合、文件或特定欄位。如要刪除文件,請使用 delete() 方法。

下方程式碼片段會刪除訂單 123。

index.js

const orderDoc = db.doc(`orders/123`);
await orderDoc.delete();

10. 部署和測試

在本節中,您會將應用程式部署至 Cloud Run,並測試建立、更新及刪除方法。

將應用程式部署至 Cloud Run

  1. 將網址儲存在變數 INVENTORY_SERVICE_URL 中,以便與庫存服務整合
INVENTORY_SERVICE_URL=$(gcloud run services describe inventory-service \
 --region=$REGION \
 --format=json | jq \
 --raw-output ".status.url")
  1. 部署訂單服務
gcloud run deploy order-service \
  --source . \
  --platform managed \
  --region $REGION \
  --allow-unauthenticated \
  --project=$PROJECT_ID \
  --set-env-vars=INVENTORY_SERVICE_URL=$INVENTORY_SERVICE_URL \
  --quiet

輸出範例

[...]
Done.
Service [order-service] revision [order-service-00001-qot] has been deployed and is serving 100 percent of traffic.
Service URL: https://order-service-3jbm3exegq-uk.a.run.app

測試 Cloud Run 應用程式

建立文件

  1. 將訂單服務應用程式的網址儲存在變數中,以便進行測試
ORDER_SERVICE_URL=$(gcloud run services describe order-service \
  --platform managed \
  --region $REGION \
  --format=json | jq \
  --raw-output ".status.url")
  1. 建立訂單要求,並將新訂單發布至 Firestore 資料庫
curl --request POST $ORDER_SERVICE_URL/order \
--header 'Content-Type: application/json' \
--data-raw '{
    "name": "Jane Doe",
         "email": "Jane.Doe-cymbaleats@gmail.com",
    "address": "123 Maple",
    "city": "Buffalo",
    "state": "NY",
    "zip": "12346",
    "orderItems": [
        {
            "id": 1
        }
    ]
}'

輸出範例

{"orderNumber":46429}

儲存訂單號碼供日後使用

export ORDER_NUMBER=<value_from_output>

查看結果

在 Firestore 中查看結果

  1. 前往 Firestore 控制台
  2. 按一下「資料」

465ceca6198b2b88.png

更新文件

提交的訂單缺少數量。

  1. 更新記錄並新增數量鍵/值組合
curl --location -g --request PATCH $ORDER_SERVICE_URL/order/${ORDER_NUMBER} \
--header 'Content-Type: application/json' \
--data-raw '{
"orderItems": [
        {   
            "id": 1,
            "quantity": 1   
        }
    ]
}'

輸出範例

{"status":"success"}

查看結果

在 Firestore 中查看結果

  1. 前往 Firestore 控制台
  2. 按一下「資料」

cfcf78d200e15b84.png

刪除文件

  1. 刪除 Firestore 訂單集合中的項目 46429
curl --location -g --request DELETE $ORDER_SERVICE_URL/order/${ORDER_NUMBER}

查看結果

  1. 前往 Firestore 控制台
  2. 按一下「資料」

73e14d69211d1539.png

11. 恭喜!

恭喜,您完成了研究室!

下一步:

探索其他 Cymbal Eats 程式碼研究室:

清除所用資源

如要避免系統向您的 Google Cloud 帳戶收取本教學課程所用資源的費用,請刪除含有相關資源的專案,或者保留專案但刪除個別資源。

刪除專案

如要避免付費,最簡單的方法就是刪除您針對教學課程建立的專案。