Google App Engine (簡稱 GAE) 是 Google Cloud 在 2008 年第一個推出的雲端服務,(Compute Engine 是 2012 年才推出),它的神奇之處在於,你只要上傳整包程式碼資料夾(也就是傳統的單體式架構),就可以把你的應用程式跑起來,這麼神奇?聽起來很厲害吧!
Google App Engine 環境介紹
Google App Engine Standard 環境
只要上傳程式碼就能跑,不用連進去安裝程式環境嗎?當時就是所謂的 Standard 環境,程式在運作過程中根本就用不到虛擬機器。
好處是,你完全不用維護它,因為根本沒有機器讓你來管,而且它非常的便宜,甚至可以「Scale to Zero」,沒有流量的時候,整個服務都在「睡覺」,當流量進來的瞬間,它會馬上「起床」,對於使用者來說,完全感受不到「等待」的感覺。
其實它還是有開機器,但它開的是 App Engine 專用的機器類型,並不是虛擬機器,是 100% Google Cloud 代管的機器,連 SSH 進去敲指令的機會都沒有,根本不用耗費心力去管理。
由於這樣的特性,當時吸引了非常多新創公司來使用,包含智慧型手機剛開始流行的時候,最知名的手機遊戲憤怒鳥 (Angry Birds),他們當時開發了非常多種遊戲,也不知道哪一個遊戲會爆紅,反正開發完就先上架再說,結果憤怒鳥突然爆紅,大量使用者下載來玩,好在 Google App Engine 內建 Autoscale,讓他們不用人工去維護大量爆增的主機。
Standard 環境有程式語言的限制,目前限定 Java、PHP、Python、Go、Nodejs、 Ruby 才能使用,而且不是所有 Library 都能用,此外它只支援 HTTP(S) 協定,其他協定都不能用,限制較多,相關規定你可以再去 Google Cloud 官網查詢。
Google App Engine Flexible 環境
因為 Standard 環境的限制比較多,所以 Google Cloud 後來又推出了 Flexible 環境,因為它會幫你把程式碼打包成容器,只要能夠跑得起來,就不會限定你的程式語言或版本,所有通訊協定和 Port 都能使用,自由度大為提高。
但它會建立 Compute Engine 的機器來運作你的容器,沒有辦法像 Standard 環境一樣,讓你可以 「Scale to Zero」,所以離峰時間至少還是有一台機器在跑喔!
另外要提醒的是,雖然它會開機器,也有磁碟可以使用,但因為 Autoscale 的特性,機器可能會因為流量退去之後,自動縮減(Scale Down)導致刪除機器和磁碟,所以資料一律建議寫到外部,像是 Cloud Storage 或 Cloud SQL 喔!
兩者的比較如下:
| GAE 版本 | Standard | Flexible |
| 運行環境 | 沙箱環境,限制較多 | 完整的 VM 環境 |
| 支援語言 | Java、PHP、Python、Go、Nodejs、 Ruby | 支援所有語言和框架 |
| 部署/啟動時間 | 毫秒級別(冷啟動快) | 分鐘級別(需要啟動 VM) |
| 擴展方式 | Autoscale | Autoscale |
| 最少機器數量 | 0 | 1 |
| 磁碟 | 唯讀,臨時性 | 可讀寫,但 VM 重啟會遺失 |
表 9-1-1 Google App Engine Standard 和 Flexible 環境比較
部署 GAE 程式示範
接下來我們快速看一下如何部署 GAE 程式,你可以先搜尋「google app engine nodejs」,直接點擊 「Build a Node.js app on App」,就能看到完整步驟:

我們可以在 Cloud Shell 上完成所有步驟,如文件說明,你要先執行以下指令:
建立並初始化資料夾
mkdir my-nodejs-service
進入資料夾
cd my-nodejs-service
建立 Node.js 專案和 package.json 檔案
npm init
更改 package.json 檔
vim package.json

上面只是定義套件內容,但還沒正式安裝,要再輸入以下指令來安裝套件:
npm install
建立 server.js 檔
vim server.js
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello from App Engine from Dongdong!');
});
// Listen to the App Engine-specified port, or 8080 otherwise
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log(`Server listening on port ${PORT}...`);
});
完成之後可以確認是否有以下的檔案,如果確定都準備好了可以執行下方指令,看看有沒有出現錯誤訊息,如下圖就代表程式已經順利在運作:
npm start

然後來預覽看看它呈現的樣子:

再準備一個檔案 app.yaml,這個檔案只要一行字,就是指定 Nodejs 程式的版本:
runtime: nodejs20
接著輸入 gcloud app deploy,中間會問你是否要繼續,按下 y,就可以等它部署完成:

你可以在 GCP 主控台上點擊「服務」的超連結「default」,它就會打開網頁。另外你會看到版本號碼,像我是第 7 版,因為我曾經對這支程式改過很多遍,你看到的數字應該是 1。

你可以去「版本」頁面查看,它現在顯示為 1 台機器,但是過 15 分鐘左右,它就會變成 0,就是 Scale to Zero 的表現。

同時你可以看在「執行個體」頁面,看到機器的 ID 和效能指標。

接下來要注意,Google App Engine 預設有啟動 Autoscale,你現在如果直接做壓力測試,它會馬上新增主機來應付外部的流量,非常方便。下圖就是我前陣子曾經做過壓力測試,看到它自動擴充的結果:

當時看到這個數字我也有點嚇到,如果你不希望有任何額外的成本發生,你就要去調整你的 app.yaml 設定檔,讓它的自動擴充有一個上限,範例如下:
runtime: nodejs20
env: standard
instance_class: F1
automatic_scaling:
target_cpu_utilization: 0.65
min_instances: 0
max_instances: 10
min_pending_latency: 30ms
max_pending_latency: automatic
max_concurrent_requests: 50
參數 instance_class: F1,指的是 GAE 最小規格的機器,它每天可以開 28 個小時免費,就是你可以一台機器開一整個月都不用付費。
像我目前就指定最高 10 台,CPU 使用率超過 65% 再擴充,也可以參考官方文件做更進一步的設定。
你還可以拆分流量到不同的版本,如果你有新版程式想先開放給少數使用者的話,就可以利用這個功能, 像我現在拆分流 50% 流量給舊版:

接著我就瘋狂點擊首頁網址的重新整理,你會看到它出現了另外一個版本,是我在 2024/2/22 那天測試的版本。

那你最後可能會問,我要怎麼給應用程式改版呢?你只要把前面的檔案,例如 server.js 改好 (其他檔案也行),直接按 gcloud app deploy,它就會馬上推出新的一版,目前的版本會保留下來,從 CI/CD 的角度來看,它真的非常方便喔!