本教學課程說明如何使用 WebSockets 建立多室即時通訊服務,並透過永久連線進行雙向通訊。使用 WebSockets 時,用戶端和伺服器可以互相推送訊息,不必輪詢伺服器以取得更新。
雖然您可以設定 Cloud Run 使用工作階段相依性,但這項功能只能盡量提供相依性,也就是說,任何新要求仍有可能會轉送至其他執行個體。因此,聊天服務中的使用者訊息必須在所有執行個體之間同步處理,而不只是在連線至單一執行個體的用戶端之間同步處理。
設計總覽
這個範例即時通訊服務使用 Memorystore for Redis 執行個體,在所有執行個體中儲存及同步處理使用者訊息。Redis 使用 Pub/Sub 機制 (請勿與 Cloud Pub/Sub 產品混淆),將資料推送至連線至任何執行個體的訂閱用戶端,藉此淘汰 HTTP 輪詢更新。
不過,即使使用推播更新,啟動的任何執行個體也只會收到推播至容器的新訊息。如要載入先前的訊息,必須先將訊息記錄儲存在永久儲存解決方案中,然後再從該處擷取。這個範例使用 Redis 的傳統物件儲存功能,快取及擷取訊息記錄。

Redis 執行個體使用的是私人 IP,不會連結至網際網路,因此能夠受到保護。另外,執行個體的存取權也受到控管,只有與 Redis 執行個體在同一個虛擬私人網路上執行的服務可以存取。因此,Cloud Run 服務必須透過無伺服器虛擬私有雲存取連接器,才能連線至 Redis。進一步瞭解無伺服器虛擬私有雲存取。
限制
本教學課程不會說明使用者驗證或工作階段快取。如要進一步瞭解使用者驗證,請參閱 Cloud Run 的使用者驗證教學課程。
本教學課程不會實作 Firestore 等資料庫,以便無限期儲存及擷取即時通訊訊息記錄。
這個範例服務還需要其他元素,才能用於正式環境。建議使用標準級 Redis 執行個體,透過複製和自動容錯移轉功能提供高可用性。
目標
撰寫、建構及部署使用 WebSocket 的 Cloud Run 服務。
連線至 Memorystore for Redis 執行個體,在執行個體之間發布及訂閱新訊息。
使用無伺服器虛擬私有雲存取連接器,將 Cloud Run 服務連線至 Memorystore。
費用
在本文件中,您會使用 Google Cloud的下列計費元件:
如要根據預測用量估算費用,請使用 Pricing Calculator。
事前準備
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Verify that billing is enabled for your Google Cloud project.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Verify that billing is enabled for your Google Cloud project.
-
Enable the Cloud Run, Memorystore for Redis, Serverless VPC Access, Artifact Registry, and Cloud Build APIs.
- 安裝並初始化 gcloud CLI。
-
Artifact Registry 讀取者 (
roles/artifactregistry.reader
) -
Cloud Build 編輯器 (
roles/cloudbuild.builds.editor
) -
Cloud Memorystore Redis 管理員 (
roles/redis.admin
) -
Cloud Run Admin (
roles/run.admin
) -
建立服務帳戶 (
roles/iam.serviceAccountCreator
) -
專案 IAM 管理員 (
roles/resourcemanager.projectIamAdmin
) -
無伺服器 VPC 存取服務代理 (
roles/vpcaccess.serviceAgent
) -
服務帳戶管理員 (
roles/iam.serviceAccountAdmin
) -
服務用量消費者 (
roles/serviceusage.serviceUsageConsumer
)
必要的角色
如要取得完成本教學課程所需的權限,請要求管理員為您授予專案的下列 IAM 角色:
如要進一步瞭解如何授予角色,請參閱「管理專案、資料夾和機構的存取權」。
設定 gcloud
預設值
如要針對 Cloud Run 服務設定 gcloud 的預設值:
設定您的預設專案:
gcloud config set project PROJECT_ID
將 PROJECT_ID 改為您為本教學課程建立的專案名稱。
為所選區域設定 gcloud:
gcloud config set run/region REGION
將 REGION 改為您所選擇的支援 Cloud Run 地區。
Cloud Run 位置
Cloud Run 具有「地區性」,這表示執行 Cloud Run 服務的基礎架構位於特定地區,並由 Google 代管,可為該地區內所有區域提供備援功能。
選擇 Cloud Run 服務的執行地區時,請將延遲時間、可用性或耐用性需求做為主要考量。一般而言,您可以選擇最靠近使用者的地區,但您應考量 Cloud Run 服務所使用的其他 Google Cloud
產品位置。使用分散在不同位置的 Google Cloud 產品,可能會影響服務的延遲時間和費用。
Cloud Run 可在下列地區使用:
採用級別 1 定價
asia-east1
(臺灣)asia-northeast1
(東京)asia-northeast2
(大阪)asia-south1
(印度孟買)europe-north1
(芬蘭)二氧化碳排放量低
europe-north2
(斯德哥爾摩)二氧化碳排放量低2
europe-southwest1
(馬德里)二氧化碳排放量低
europe-west1
(比利時)二氧化碳排放量低2
europe-west4
(荷蘭)二氧化碳排放量低
europe-west8
(米蘭)europe-west9
(巴黎)二氧化碳排放量低
me-west1
(特拉維夫)northamerica-south1
(墨西哥)us-central1
(愛荷華州)二氧化碳排放量低
us-east1
(南卡羅來納州)us-east4
(北維吉尼亞州)us-east5
(哥倫布)us-south1
(達拉斯)二氧化碳排放量低
us-west1
(奧勒岡州)二氧化碳排放量低
採用級別 2 定價
africa-south1
(約翰尼斯堡)asia-east2
(香港)asia-northeast3
(韓國首爾)asia-southeast1
(新加坡)asia-southeast2
(雅加達)asia-south2
(印度德里)australia-southeast1
(雪梨)australia-southeast2
(墨爾本)europe-central2
(波蘭華沙)europe-west10
(柏林)二氧化碳排放量低
europe-west12
(杜林)europe-west2
(英國倫敦)二氧化碳排放量低
europe-west3
(德國法蘭克福)europe-west6
(瑞士蘇黎世)二氧化碳排放量低
me-central1
(杜哈)me-central2
(達曼)northamerica-northeast1
(蒙特婁)二氧化碳排放量低
northamerica-northeast2
(多倫多)二氧化碳排放量低
southamerica-east1
(巴西聖保羅)二氧化碳排放量低
southamerica-west1
(智利聖地牙哥)二氧化碳排放量低
us-west2
(洛杉磯)us-west3
(鹽湖城)us-west4
(拉斯維加斯)
如果您已建立 Cloud Run 服務,即可在 Google Cloud 控制台的 Cloud Run 資訊主頁中查看地區。
擷取程式碼範例
如要擷取要使用的程式碼範例:
將範例存放區複製到本機電腦中:
Node.js
git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git
您也可以 下載 zip 格式的範例,然後解壓縮該檔案。
變更為包含 Cloud Run 程式碼範例的目錄:
Node.js
cd nodejs-docs-samples/run/websockets/
瞭解程式碼
Socket.io 程式庫可讓瀏覽器與伺服器進行即時雙向通訊。雖然 Socket.io 並非 WebSocket 實作項目,但它會包裝功能,為多個通訊協定提供更簡單的 API,並提供其他功能,例如提升可靠性、自動重新連線,以及向所有或部分用戶端廣播。
用戶端整合
用戶端會為每個連線例項建立新的 Socket 例項。由於這個範例是伺服器端算繪,因此不需要定義伺服器網址。插座執行個體可以發出及監聽事件。
伺服器端整合
在伺服器端,系統會初始化 Socket.io 伺服器,並附加至 HTTP 伺服器。與用戶端類似,Socket.io 伺服器與用戶端建立連線後,系統會為每個連線建立通訊端執行個體,可用於發出及監聽訊息。Socket.io 也提供簡單的介面,可建立「聊天室」或任意管道,供 Socket 加入及離開。
Socket.io 也提供 Redis 轉接器,可將事件播送至所有用戶端,無論哪個伺服器提供 Socket 服務都沒問題。Socket.io 只會使用 Redis 的 Pub/Sub 機制,不會儲存任何資料。
Socket.io 的 Redis 介面卡可以重複使用 Redis 用戶端,儲存聊天室的訊息記錄。每個容器都會建立與 Redis 執行個體的連線,而 Cloud Run 可以建立大量執行個體。這遠低於 Redis 支援的 65,000 個連線。如要支援這麼大的流量,您也需要評估無伺服器虛擬私有雲存取連接器的輸送量。
重新連線
Cloud Run 的逾時時間上限為 60 分鐘。因此您需要新增重新連線邏輯,以防逾時。在某些情況下,Socket.io 會在中斷連線或連線錯誤事件後,自動嘗試重新連線。無法保證用戶端會重新連線至相同執行個體。
如果連線處於啟用狀態,執行個體就會持續存在,直到所有要求關閉或逾時為止。即使使用 Cloud Run 工作階段相依性,系統仍可能將新要求負載平衡至作用中容器,讓容器縮減規模。如果擔心流量暴增後會留下大量容器,可以調低逾時上限值,以便更頻繁地清除未使用的通訊端。
運送服務
建立 Memorystore for Redis 執行個體:
gcloud redis instances create INSTANCE_ID --size=1 --region=REGION
將 INSTANCE_ID 替換為執行個體的名稱,例如
my-redis-instance
,並將 REGION_ID 替換為所有資源和服務的區域,例如europe-west1
。系統會從預設服務網路範圍中,自動為執行個體分配 IP 範圍。本教學課程會使用 1 GB 的記憶體,做為 Redis 執行個體中訊息的本機快取。進一步瞭解如何根據用途決定 Memorystore 執行個體的初始大小。
設定無伺服器虛擬私有雲存取連接器:
如要連線至 Redis 執行個體,Cloud Run 服務必須有權存取 Redis 執行個體的授權虛擬私有雲網路。
每個虛擬私有雲連接器都需具備自己的
/28
子網路,以便放置連接器執行個體。這個 IP 範圍不得與虛擬私人雲端網路中的任何現有 IP 位址保留項目重疊。舉例來說,10.8.0.0
(/28
) 適用於大多數新專案,您也可以指定其他未使用的自訂 IP 範圍,例如10.9.0.0
(/28
)。您可以在 Google Cloud 控制台中查看目前保留的 IP 範圍。gcloud compute networks vpc-access connectors create CONNECTOR_NAME \ --region REGION \ --range "10.8.0.0/28"
將 CONNECTOR_NAME 替換為連接器的名稱。
這個指令會在預設 VPC 網路中建立連接器 (與 Redis 執行個體相同),並使用
e2-micro
機器大小。增加連接器的機器大小可以提高連接器的輸送量,但也會增加費用。連接器也必須與 Redis 執行個體位於相同地區。進一步瞭解如何設定無伺服器虛擬私有雲存取。使用 Redis 執行個體授權網路的 IP 位址定義環境變數:
export REDISHOST=$(gcloud redis instances describe INSTANCE_ID --region REGION --format "value(host)")
建立服務帳戶做為服務身分。根據預設,除了專案成員資格外,這項角色沒有其他權限。
gcloud iam service-accounts create chat-identity gcloud projects add-iam-policy-binding PROJECT_ID \ --member=serviceAccount:chat-identity@PROJECT_ID.iam.gserviceaccount.com \ --role=roles/serviceusage.serviceUsageConsumer
建構容器映像檔並部署至 Cloud Run:
gcloud run deploy chat-app --source . \ --vpc-connector CONNECTOR_NAME \ --allow-unauthenticated \ --timeout 3600 \ --service-account chat-identity \ --update-env-vars REDISHOST=$REDISHOST
如果系統提示安裝必要 API,請在提示時輸入
y
。這項操作只需要為專案執行一次。如果尚未如設定頁面所述,為平台和區域設定預設值,請提供這些資訊來回應其他提示。進一步瞭解如何從原始碼部署。
立即體驗
如要試用完整服務:
在瀏覽器中前往上述部署步驟提供的網址。
新增名稱和聊天室即可登入。
傳送訊息至聊天室!
如果您選擇繼續開發這些服務,請注意,這些服務對其餘服務的存取權受到身分與存取權管理 (IAM) 限制,且需要額外指派 IAM 角色,才能存取許多其他服務。 Google Cloud
清除所用資源
如果您是為了這個教學課程建立新專案,請刪除專案。如果您使用現有專案,並想保留專案,但不要在本教學課程中新增的變更,請刪除為本教學課程建立的資源。
刪除專案
如要避免付費,最簡單的方法就是刪除您為了本教學課程所建立的專案。
如要刪除專案:
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
刪除教學課程資源
刪除您在本教學課程中部署的 Cloud Run 服務:
gcloud run services delete SERVICE-NAME
其中 SERVICE-NAME 是您選擇的服務名稱。
您也可以從Google Cloud 控制台刪除 Cloud Run 服務。
移除您在教學課程設定期間新增的 gcloud 預設區域設定:
gcloud config unset run/region
移除專案設定:
gcloud config unset project
刪除在本教學課程中建立的其他 Google Cloud 資源:
後續步驟
進一步瞭解 Socket.io 的運作方式和更進階的用法。
進一步瞭解如何設定無伺服器虛擬私有雲存取。
請參閱 Memorystore 和在 Cloud Run 上使用 WebSocket 的最佳做法。
如要排解任何無伺服器網路問題,請使用無伺服器虛擬私有雲存取診斷工具。