單元 11:從 Google App Engine 遷移至 Cloud Functions

1. 總覽

無伺服器遷移站系列的程式碼研究室系列 (自助式實作教學課程) 和相關影片,旨在引導 Google Cloud 無伺服器開發人員透過一或多種遷移作業 (主要用於遷移舊版服務) 逐步翻新應用程式。這麼一來,您的應用程式就能更具可攜性,並提供更多選擇和使用彈性,進而整合及使用更多 Cloud 產品,也更容易升級至較新的語言版本。本系列課程一開始將著重在最早的 Cloud 使用者 (主要是 App Engine (標準環境) 開發人員),但涵蓋其他無伺服器平台,包括 Cloud FunctionsCloud Run 或其他無伺服器平台 (如適用)。

有些情況下,你可能沒有「完整的應用程式」需要 App EngineCloud Run 的資源。如果您的程式碼只包含微服務或簡單的函式,Cloud Functions 可能更適合。本程式碼研究室將說明如何遷移簡單的 App Engine 應用程式 (或將大型應用程式拆解成多個微服務),並將這些應用程式部署至 Cloud Functions。Cloud Functions 是另一個專為這類用途而打造的無伺服器平台。

在接下來的研究室中

  • 使用 Cloud Shell
  • 啟用 Google Cloud Translation API
  • 驗證 API 要求
  • 轉換小型 App Engine 應用程式,以便在 Cloud Functions 中執行
  • 將程式碼部署至 Cloud Functions

軟硬體需求

問卷調查

您會如何使用這個教學課程?

僅供閱讀 閱讀並完成練習

您對 Python 的使用體驗有何評價?

新手 中級 還算容易

針對使用 Google Cloud 服務的經驗,您會給予什麼評價?

新手 中級 還算容易

2. 背景

Google App Engine 和 Cloud Functions 等 PaaS 系統能為使用者提供許多便利。有了這些無伺服器平台,您的技術團隊就不必花時間研究要使用的平台及確認所需的硬體數量,即可專心打造業務解決方案。應用程式可以視需求自動調度資源,使用即付即用的計費模式將資源降至零,藉此控管成本,而且支援現今多種常見的開發語言。

不過,雖然 App Engine 很適合使用完整堆疊的網頁應用程式開發或複雜的後端,但開發人員常會把一些功能放到網路上,例如更新新聞動態消息或取得主隊賽事的最新比分。雖然這兩種情境都存在程式設計邏輯,但似乎不是完全公開的「應用程式」且需要 App Engine 的功能。Cloud Functions 就是派上用場的地方。

Cloud Functions 用於部署一小段程式碼,如下所示:

  • 不是整個應用程式的一部分
  • 不需要整個開發堆疊
  • 本身位於應用程式或單一的行動應用程式後端

您也可以使用 Cloud Functions,將大型的單體式應用程式拆解成多個微服務,而且每個微服務都會使用共用的通用資料庫 (例如 Cloud FirestoreCloud SQL)。或者,如果您想將函式或微服務容器化,並在 Cloud Run 上以無伺服器的方式執行,也可以這麼做。

幾乎所有遷移教學課程都提供範例 App Engine 應用程式,這是一個含有基本功能的簡短應用程式,同樣適用於 Cloud Functions。本教學課程將說明如何修改應用程式,使其在 Cloud Functions 上執行。從 App Engine 的角度來看,由於函式比整個應用程式更為簡單,因此新手入門體驗應該更簡單、快速,而且減輕負擔這項遷移作業包含下列步驟:

  • 設定/事前作業
  • 移除設定檔
  • 修改應用程式檔案

3. 設定/事前作業

由於 Cloud Functions 不支援 Python 2,因此本程式碼研究室會從 Python 3 版本的模組 2 Cloud NDB App Engine 範例應用程式開始。首先,讓我們設定專案、取得程式碼,然後部署基準應用程式,確認我們要開始編寫有效的程式碼。

1. 設定專案

如果您已完成單元 2 程式碼研究室 (並將其移植至 Python 3),建議您重複使用相同的專案 (和程式碼)。或者,您可以建立新的專案,或是重複使用其他現有專案。請確認專案具備有效的帳單帳戶,而且已啟用 App Engine 服務。

2. 取得基準範例應用程式

本程式碼研究室的必要條件之一,是擁有正常運作的模組 2 範例應用程式。如果沒有這類教學課程,請先完成上方連結中的任一教學課程,再繼續繼續操作。如果您熟悉其中的內容,可以先擷取下方的單元 2 程式碼。

無論您是使用您自己的還是我們的,我們都會在單元 2 Python 3 程式碼的位置。本單元的單元 11 會逐步引導您完成每個步驟,最後程式碼會與單元 11 存放區資料夾 (FINISH) 中的內容類似。

Python 3 單元 2 啟動檔案 (您自己或我們的) 的目錄應如下所示:

$ ls
README.md               main.py                 templates
app.yaml                requirements.txt

3. (重新) 部署基準應用程式

您目前需執行的準備作業步驟:

  1. 請重新熟悉 gcloud 指令列工具。
  2. 使用 gcloud app deploy 重新部署範例應用程式
  3. 確認應用程式在 App Engine 上執行,沒有問題

成功執行這些步驟後,即可將其轉換為 Cloud 函式。

4. 移除設定檔

app.yaml 檔案是 App Engine 構件,並未與 Cloud Functions 搭配使用,因此立即刪除。如果您忘記或忘記執行這個步驟,Cloud Functions 不需要這麼做,不會造成任何損害。這是唯一設定變更,因為 requirements.txt 與模組 2 相同。

如果您也將 Python 2 App Engine 應用程式移植到 Python 3,請刪除 appengine_config.pylib 資料夾 (如有)。這些是 Python 3 執行階段中未使用的 App Engine 構件。

5. 修改應用程式檔案

只有一個應用程式檔案 main.py,因此遷移至 Cloud Functions 的所有必要變更都會出現在這個檔案中。

匯入

因為我們僅使用函式,因此不需要網頁應用程式架構。但為了方便起見,在呼叫以 Python 為基礎的 Cloud Functions 時,這些函式會自動傳遞要求物件,以供程式碼視需要使用。(Cloud Functions 團隊選取了做為傳遞至您函式的 Flask 要求物件)。

由於網路架構不屬於 Cloud Functions 環境,因此「除非」應用程式使用其他 Flask 功能,否則不會從 Flask 匯入任何資料。這確實是我們的情況,因為轉換為函式之後,系統仍然會執行範本算繪,也就是說仍需要呼叫 flask.render_template(),因此必須從 Flask 匯入。沒有網路架構,表示不需要將 Flask 應用程式例項化,因此請刪除 app = Flask(__name__)。套用變更前後的程式碼如下所示:

變更前:

from flask import Flask, render_template, request
from google.cloud import ndb

app = Flask(__name__)
ds_client = ndb.Client()

變更後:

from flask import render_template
from google.cloud import ndb

ds_client = ndb.Client()

如果仰賴應用程式物件 (app) 或任何其他網路架構基礎架構,則您必須解決所有依附元件、找出適當的解決方法,或是完全移除其使用方式,或者找出 Proxy。只有您可以將程式碼轉換為 Cloud 函式。否則,建議您繼續使用 App Engine,或將應用程式容器化並用於 Cloud Run

更新主要處理常式函式簽章

函式簽章所需的變更如下:

  1. 將應用程式轉換為 Cloud 函式後,無法再使用 Flask,因此請移除路徑修飾符。
  2. Cloud Functions 會自動將 Flask Request 物件做為參數傳遞,因此請為該物件建立變數。在範例應用程式中,我們會將其命名為 request
  3. 已部署的 Cloud Functions 必須命名。我們的主要處理常式在 App Engine 中正確命名為 root(),以說明其為何 (根應用程式處理常式)。做為 Cloud 函式,使用這個名稱會較不合理。我們會改用 visitme 這個名稱部署 Cloud 函式,因此也請使用 Python 函式的名稱。同樣地,單元 4 和 5 也命名為 Cloud Run 服務 visitme

以下是異動前後的版本:

變更前:

@app.route('/')
def root():
    'main application (GET) handler'
    store_visit(request.remote_addr, request.user_agent)
    visits = fetch_visits(10)
    return render_template('index.html', visits=visits)

變更後:

def visitme(request):
    'main application (GET) handler'
    store_visit(request.remote_addr, request.user_agent)
    visits = fetch_visits(10)
    return render_template('index.html', visits=visits)

以上就是所有必要的更新請注意,所做變更只會影響應用程式的「基礎架構」再也不是件繁重乏味的工作核心應用程式程式碼不需要變更,應用程式功能也未經變更。以下為現狀進行的變更示意圖,以說明這一點:

668f30e3865b27a9.png

本機開發和測試

App Engine 提供 dev_appserver.py 本機開發伺服器,Cloud Functions 則是函式架構。運用這個架構,即可在本機開發及測試。您的程式碼可以部署至 Cloud Functions,但也可以部署至其他運算平台,例如 Compute EngineCloud Run,甚至是支援 Knative 的地端部署或混合式雲端系統。如要查看其他 Functions Framework 連結,請參閱下方說明。

6. 建構及部署

部署至 Cloud Functions 與 App Engine 略有不同。由於 requirements.txt 之外沒有使用設定檔,因此您必須在指令列中指定程式碼的詳細資訊。使用以下指令部署新的 HTTP 觸發的 Cloud 函式,在 Python 3.10 下執行:

$ gcloud functions deploy visitme --runtime python310 --trigger-http --allow-unauthenticated

輸出結果應該會與下列內容類似:

Deploying function (may take a while - up to 2 minutes)...⠛
For Cloud Build Logs, visit: https://console.cloud.google.com/cloud-build/builds;region=REGION/f5f6fc81-1bb3-4cdb-8bfe?project=PROJECT_ID
Deploying function (may take a while - up to 2 minutes)...done.
availableMemoryMb: 256
buildId: f5f6fc81-1bb3-4cdb-8bfe
buildName: projects/PROJECT_ID/locations/REGION/builds/f5f6fc81-1bb3-4cdb-8bfe
dockerRegistry: CONTAINER_REGISTRY
entryPoint: visitme
httpsTrigger:
  securityLevel: SECURE_OPTIONAL
  url: https://REGION-PROJECT_ID.cloudfunctions.net/visitme
ingressSettings: ALLOW_ALL
labels:
  deployment-tool: cli-gcloud
name: projects/PROJECT_ID/locations/REGION/functions/visitme
runtime: python310
serviceAccountEmail: PROJECT_ID@appspot.gserviceaccount.com
sourceUploadUrl: https://storage.googleapis.com/uploads-853031211983.REGION.cloudfunctions.appspot.com/8c923758-cee8-47ce-8e97-5720a5301c34.zip
status: ACTIVE
timeout: 60s
updateTime: '2022-05-16T18:28:06.153Z'
versionId: '8'

函式部署完成後,使用部署輸出內容的網址,並造訪您的應用程式。網址格式為:REGION-PROJECT_ID.cloudfunctions.net/visitme。輸出內容應該會與您稍早部署至 App Engine 時相同:

2732ae9218f011a2.png

如同本系列中大部分的其他程式碼研究室和影片,基本應用程式功能並未改變。此目的是為了套用一種翻新技術,讓應用程式完全由新版基礎架構驅動,例如從舊版 App Engine 舊版服務遷移至替代的 Cloud 獨立產品,或像本教學課程一樣,將應用程式移至其他 Google Cloud 無伺服器平台。

7. 摘要/清除

恭喜您將這個小型 App Engine 應用程式轉換為 Cloud 函式!另一個適當用途:將大型單體式 App Engine 應用程式拆解成一系列微服務,而每個微服務都做為 Cloud 函式。這是一種較現代化的開發技術,能引發「隨插即用」的迴響(la「JAM stack」) 樣式。這可以混合搭配,以及重複使用程式碼,但是這是兩個目標,不過,這些微服務會持續受到偵錯,意即程式碼穩定、整體維護成本也更低。

清除所用資源

完成本程式碼研究室後,您可以停用模組 2 App Engine 應用程式 (暫時或永久),以免產生帳單費用。App Engine 平台提供免費配額,因此只要未超過用量限制,就不會產生費用。同樣的原則也適用於 Datastore;詳情請參閱 Cloud Datastore 定價頁面

部署至 App Engine 和 Cloud Functions 等平台會產生少許建構和儲存空間費用。在某些區域,Cloud Build 提供的免費配額與 Cloud Storage 相同。建構作業會耗用部分配額。請留意儲存空間用量,盡可能降低潛在費用,特別是在您所在的區域沒有這類免費方案時。

不過很抱歉,Cloud Functions 並沒有「停用」而不是每個特徵的分數備份程式碼並刪除函式即可。您之後可隨時使用相同名稱重新部署這個叢集。不過,如果您不想繼續進行其他遷移程式碼研究室,且想要徹底刪除所有項目,請關閉 Cloud 專案

後續步驟

除本教學課程外,也建議尋找其他遷移模組,包括針對 Cloud Run 將 App Engine 應用程式容器化。請參閱單元 4 和單元 5 程式碼研究室的連結:

  • 模組 4:遷移至 Cloud Run 與 Docker
  • 將應用程式容器化,讓應用程式透過 Docker 在 Cloud Run 中執行
  • 這項遷移作業可讓您繼續使用 Python 2。
  • 單元 5:使用 Cloud Buildpacks 遷移至 Cloud Run
  • 將應用程式容器化,讓應用程式透過 Cloud Buildpacks 在 Cloud Run 中執行
  • 您不需要瞭解 Docker、容器或 Dockerfile 的任何資訊。
  • 需要將應用程式遷移至 Python 3 (Buildpacks 不支援 Python 2)

其他許多模組著重於開發人員如何從 App Engine 套裝組合服務遷移至獨立的 Cloud 替代服務:

  • 模組 2:從 App Engine ndb 遷移至 Cloud NDB
  • 模組 7 至 9:從 App Engine 工作佇列推送工作遷移至 Cloud Tasks
  • 模組 12-13:從 App Engine Memcache 遷移至 Cloud Memorystore
  • 模組 15 至 16:從 App Engine Blob 遷移至 Cloud Storage
  • 模組 18-19:從 App Engine 工作佇列 (提取工作) 遷移至 Cloud Pub/Sub

如果容器化已成為應用程式開發工作流程的一部分,特別是在含有 CI/CD (持續整合/持續推送軟體更新或部署) 管道的情況下,請考慮遷移至 Cloud Run,而不是 Cloud Functions。請參閱模組 4,利用 Docker 將應用程式容器化;如果沒有容器、Docker 知識或 Dockerfile,也能執行模組 5。無論您考慮使用 Cloud Functions 或 Cloud Run,是否要改用其他無伺服器平台。在進行任何變更之前,建議您考量應用程式和用途的最佳選項。

無論接下來選擇使用哪個遷移模組,所有無伺服器遷移站內容 (程式碼研究室、影片、原始碼 [如有]) 都可以透過其開放原始碼存放區存取。存放區的 README 還針對應考慮遷移的項目和任何相關的「訂單」提供指引接下來介紹遷移模組

8. 其他資源

App Engine 遷移模組程式碼研究室問題/意見回饋

如果您在本程式碼研究室中發現任何問題,請先搜尋您的問題再提出申請。搜尋及建立新問題的連結:

遷移資源

下表提供模組 8 (START) 和單元 9 (FINISH) 的存放區資料夾連結。您也可以透過所有 App Engine 程式碼研究室遷移作業的存放區存取這些資料,可以複製或下載 ZIP 檔案。

Codelab

Python 3

Module 2

程式碼

單元 11

程式碼

線上資源

以下為可能與本教學課程相關的線上資源:

App Engine

Cloud Functions

其他 Cloud 資訊

影片

授權

這項內容採用的是創用 CC 姓名標示 2.0 通用授權。