本教學課程說明如何使用 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 執行個體,透過複製和自動容錯移轉功能提供高可用性。 
設定 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(斯德哥爾摩)- 二氧化碳排放量低 
- europe-southwest1(馬德里)- 二氧化碳排放量低 
- europe-west1(比利時)- 二氧化碳排放量低 
- 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