1. 總覽
無伺服器遷移站系列的程式碼研究室系列 (自助式實作教學課程) 和相關影片,旨在引導 Google Cloud 無伺服器開發人員透過一或多種遷移作業 (主要用於遷移舊版服務) 逐步翻新應用程式。這麼一來,您的應用程式就能更具可攜性,並提供更多選擇和使用彈性,進而整合及使用更多 Cloud 產品,也更容易升級至較新的語言版本。本系列課程一開始將著重在最早的 Cloud 使用者 (主要是 App Engine (標準環境) 開發人員),但涵蓋其他無伺服器平台,包括 Cloud Functions 和 Cloud Run 或其他無伺服器平台 (如適用)。
本程式碼研究室將說明如何從 App Engine Blob 遷移至 Cloud Storage。以下來源也有隱含的遷移作業:
webapp2
網路架構至 Flask (請見單元 1)- App Engine NDB 連線至 Cloud NDB,以便存取 Datastore (詳情請參閱模組 2)
- Python 2 至 3 (遷移的應用程式同時與 Python 2 和 Python 3 相容)
如需逐步說明,請參閱任何相關的遷移模組。
在接下來的研究室中
- 新增 App Engine Blob API/程式庫的用法
- 將使用者上傳至 Blob 服務儲存起來
- 為遷移至 Cloud Storage 的後續步驟做好準備
軟硬體需求
- 具備有效 GCP 帳單帳戶的 Google Cloud Platform 專案
- 基本 Python 技能
- 熟悉常見的 Linux 指令
- 對開發和部署 App Engine 應用程式有基本瞭解
- 可正常運作的模組 15 App Engine 應用程式:完成模組 15 程式碼研究室 (建議),或從存放區複製模組 15 應用程式
問卷調查
您會如何使用這個教學課程?
您對 Python 的使用體驗有何評價?
針對使用 Google Cloud 服務的經驗,您會給予什麼評價?
2. 背景
本程式碼研究室會從單元 15 的範例應用程式開始,示範如何從 Blob (和 NDB) 遷移至 Cloud Storage (和 Cloud NDB)。遷移程序需要替換 App Engine 舊版套裝組合服務的依附元件,這樣您就能視需要將應用程式移至其他 Cloud 無伺服器平台或其他託管平台。
與本系列的其他遷移作業相比,這項遷移作業需要花更多精力。Blob 與原始的 Web 架構具有依附關係,因此範例應用程式採用 Web2 架構,而非 Flask。本教學課程提供遷移至 Cloud Storage、Cloud NDB、Flask 和 Python 3 等功能。
應用程式仍會登錄使用者「造訪」並顯示最近 10 項,但先前的 (單元 15) 程式碼研究室新增了功能來支援 Blob 使用:應用程式會提示使用者上傳與其「造訪」相對應的成果 (檔案)。使用者可以這麼做或選取「略過」。無論使用者的決定為何,下一頁會顯示與這個應用程式先前的載入內容相同的輸出內容,顯示最近的造訪記錄。另一個差別是,造訪具備對應構件的造訪次數會顯示為「檢視畫面」可顯示造訪構件的連結。本程式碼研究室會實作上述遷移作業,並保留上述功能。
3. 設定/事前作業
在開始教學課程的主要部分之前,我們先設定專案、取得程式碼,然後部署基準應用程式,以便瞭解要開始使用有效的程式碼。
1. 設定專案
如果您已部署模組 15 應用程式,建議您重複使用相同的專案和程式碼。或者,您可以建立新的專案,或是重複使用其他現有專案。請確認專案具備有效的帳單帳戶,且 App Engine 已啟用。
2. 取得基準範例應用程式
本程式碼研究室的必要條件之一,是擁有正常運作的模組 15 範例應用程式。如果沒有,可從單元 15「開始」取得資料夾 (連結如下)。本程式碼研究室將引導您完成每個步驟,最後程式碼會與單元 16「FINISH」單元中顯示的程式碼類似資料夾。
模組 15 START 檔案的目錄應如下所示:
$ ls README.md app.yaml main-gcs.py main.py templates
main-gcs.py
檔案是模組 15 中的 main.py
替代版本,可根據專案 ID 從應用程式指派的網址,選用不同的 Cloud Storage 值區:PROJECT_ID
.appspot.com
。在本 (單元 16) 程式碼研究室中,除了類似遷移技術,這個檔案無法套用至該檔案。
3. (重新) 部署基準應用程式
您目前需執行的準備作業步驟:
- 請重新熟悉
gcloud
指令列工具。 - 使用
gcloud app deploy
重新部署範例應用程式 - 確認應用程式在 App Engine 上執行,沒有問題
成功執行上述步驟後,確認模組 15 應用程式可正常運作。初始頁面以表單提示使用者要上傳的造訪構件檔案,並提供「略過」選項按鈕,如要停用,請按照下列步驟操作:
使用者上傳或略過檔案後,應用程式就會顯示常見的「最近造訪」記錄頁面:
有構件的造訪會顯示「檢視畫面」造訪時間戳記右方的連結,即可顯示 (或下載) 構件。確認應用程式的功能後,您就能從 App Engine 舊版服務 (Web2、NDB、Blob) 遷移至現代化的替代方案 (Flask、Cloud NDB、Cloud Storage)。
4. 更新設定檔
應用程式的更新版本使用了三個設定檔,所需工作如下:
- 更新
app.yaml
中必要的內建第三方程式庫,並保持執行 Python 3 遷移作業 - 新增
requirements.txt
,指定所有未內建的必要程式庫 - 新增
appengine_config.py
,讓應用程式支援內建和非內建的第三方程式庫
app.yaml
更新 libraries
部分,即可編輯 app.yaml
檔案。移除 jinja2
並新增 grpcio
、setuptools
和 ssl
。請針對三個程式庫選擇可用的最新版本,接著新增 Python 3 runtime
指令,但已加上註解。完成後,看起來會像這樣 (如果您選取 Python 3.9):
變更前:
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
libraries:
- name: jinja2
version: latest
變更後:
#runtime: python39
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
libraries:
- name: grpcio
version: latest
- name: setuptools
version: latest
- name: ssl
version: latest
這些異動主要處理的是 App Engine 伺服器提供的 Python 2 內建程式庫,因此您不必自行組合。我們移除了 Jinja2,因為該 Jinja2 隨附 Flask,稍後會新增至 reqs.txt。每當使用 Google Cloud 用戶端程式庫 (例如 Cloud NDB 和 Cloud Storage 的用戶端程式庫) 時,都必須使用 grpcio 和設定工具。最後,Cloud Storage 本身需要 SSL 程式庫。準備好將應用程式移植至 Python 3 時,可以使用頂端的註解排除執行階段指令。本教學課程結尾會說明這個主題。
requirements.txt
新增需要 Flask 架構的 requirements.txt
檔案,以及 Cloud NDB 和 Cloud Storage 用戶端程式庫 (但沒有內建這些程式庫)。建立含有以下內容的檔案:
flask
google-cloud-ndb
google-cloud-storage
Python 2 App Engine 執行階段需要自行組合非內建的第三方程式庫,因此請執行下列指令,將這些程式庫安裝至 lib 資料夾:
pip install -t lib -r requirements.txt
如果您的開發機器同時使用 Python 2 和 3,可能必須使用 pip2 指令確保取得這些程式庫的 Python 2 版本。升級至 Python 3 後,您就不需要自行組合。
appengine_config.py
新增支援內建和非內建第三方程式庫的 appengine_config.py
檔案。建立含有以下內容的檔案:
import pkg_resources
from google.appengine.ext import vendor
# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)
# Add libraries to pkg_resources working set to find the distribution.
pkg_resources.working_set.add_entry(PATH)
剛完成的步驟應與 App Engine 文件的「安裝 Python 2 應用程式程式庫」一節所述的步驟相似或相同,更具體來說,appengine_config.py
的內容應符合步驟 5 中的步驟。
設定檔的工作已完成,現在讓我們繼續前往應用程式。
5. 修改應用程式檔案
匯入
main.py
的第一組變更包括替換所有要替換的內容。異動內容如下:
- 「
webapp2
」已替換為 Flask - 請使用 Flask 隨附的 Jinja2 而非
webapp2_extras
的 Jinja2 - App Engine Blob 和 NDB 已由 Cloud NDB 和 Cloud Storage 取代
webapp
中的 Blob 處理常式會由io
標準程式庫模組、Flask 和werkzeug
公用程式的組合取代- 根據預設,Blob 會以應用程式網址 (
PROJECT_ID.appspot.com
) 命名的 Cloud Storage 值區。由於我們正在移植至 Cloud Storage 用戶端程式庫,因此系統會使用google.auth
取得專案 ID 以指定完全相同的值區名稱。(值區名稱仍可變更,因為系統不會再對該名稱進行硬式編碼)。
變更前:
import webapp2
from webapp2_extras import jinja2
from google.appengine.ext import blobstore, ndb
from google.appengine.ext.webapp import blobstore_handlers
將 main.py
中目前的匯入部分替換為下列程式碼片段,以實作上述清單的變更。
變更後:
import io
from flask import (Flask, abort, redirect, render_template,
request, send_file, url_for)
from werkzeug.utils import secure_filename
import google.auth
from google.cloud import exceptions, ndb, storage
初始化與不必要的 Jinja2 支援
下一個要取代的程式碼區塊是 BaseHandler
,指定從 webapp2_extras
使用 Jinja2。這是不必要的,因為 Jinja2 是 Flask 的預設範本引擎,因此請將其移除。
在模組 16 端,將舊版應用程式中沒有的物件執行個體化。這包括初始化 Flask 應用程式,以及為 Cloud NDB 和 Cloud Storage 建立 API 用戶端。最後,請按照「匯入」一節的說明,統整 Cloud Storage 值區名稱。以下是實作這些更新前後的流程:
變更前:
class BaseHandler(webapp2.RequestHandler):
'Derived request handler mixing-in Jinja2 support'
@webapp2.cached_property
def jinja2(self):
return jinja2.get_jinja2(app=self.app)
def render_response(self, _template, **context):
self.response.write(self.jinja2.render_template(_template, **context))
變更後:
app = Flask(__name__)
ds_client = ndb.Client()
gcs_client = storage.Client()
_, PROJECT_ID = google.auth.default()
BUCKET = '%s.appspot.com' % PROJECT_ID
更新 Datastore 存取權
Cloud NDB 與 App Engine NDB 最為相容。已說明的其中一項差異是必須使用 API 用戶端。另一種方式是,資料儲存庫存取權需要由 API 用戶端的 Python 結構定義管理員控管。基本上,這表示所有使用 Cloud NDB 用戶端程式庫的 Datastore 存取呼叫都只能在 Python with
區塊中執行。
就是一次變更另一種則是 blob 及其物件,例如Cloud Storage 不支援 BlobKey
,因此請將 file_blob
改為 ndb.StringProperty
。以下是資料模型類別,以及更新過的 store_visit()
和 fetch_visits()
函式,以反映這些變更:
變更前:
class Visit(ndb.Model):
'Visit entity registers visitor IP address & timestamp'
visitor = ndb.StringProperty()
timestamp = ndb.DateTimeProperty(auto_now_add=True)
file_blob = ndb.BlobKeyProperty()
def store_visit(remote_addr, user_agent, upload_key):
'create new Visit entity in Datastore'
Visit(visitor='{}: {}'.format(remote_addr, user_agent),
file_blob=upload_key).put()
def fetch_visits(limit):
'get most recent visits'
return Visit.query().order(-Visit.timestamp).fetch(limit)
變更後:
class Visit(ndb.Model):
'Visit entity registers visitor IP address & timestamp'
visitor = ndb.StringProperty()
timestamp = ndb.DateTimeProperty(auto_now_add=True)
file_blob = ndb.StringProperty()
def store_visit(remote_addr, user_agent, upload_key):
'create new Visit entity in Datastore'
with ds_client.context():
Visit(visitor='{}: {}'.format(remote_addr, user_agent),
file_blob=upload_key).put()
def fetch_visits(limit):
'get most recent visits'
with ds_client.context():
return Visit.query().order(-Visit.timestamp).fetch(limit)
以下是目前為止已完成變更的基本說明:
更新處理常式
上傳處理常式
webapp2
中的處理常式是 Flask 中函式的類別。Flask 不會使用 HTTP 動詞方法,而是使用動詞來修飾函式。blob 及其 webapp
處理常式會替換為 Cloud Storage 的功能,以及 Flask 及其公用程式:
變更前:
class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
'Upload blob (POST) handler'
def post(self):
uploads = self.get_uploads()
blob_id = uploads[0].key() if uploads else None
store_visit(self.request.remote_addr, self.request.user_agent, blob_id)
self.redirect('/', code=307)
變更後:
@app.route('/upload', methods=['POST'])
def upload():
'Upload blob (POST) handler'
fname = None
upload = request.files.get('file', None)
if upload:
fname = secure_filename(upload.filename)
blob = gcs_client.bucket(BUCKET).blob(fname)
blob.upload_from_file(upload, content_type=upload.content_type)
store_visit(request.remote_addr, request.user_agent, fname)
return redirect(url_for('root'), code=307)
本次更新的相關注意事項:
- 檔案構件不再是
blob_id
,現在會依檔案名稱 (fname
) 和None
(使用者選擇不上傳檔案) 來辨識。 - Blob 處理常式將上傳程序從使用者卸除,但 Cloud Storage 不會,因此您可以看到新增的程式碼來設定檔案的 blob 物件和位置 (值區),以及執行實際上傳作業的呼叫。(
upload_from_file()
)。 webapp2
會使用應用程式檔案底部的路徑表,而每個裝飾的處理常式都會找到 Flask 路徑。- 這兩個處理常式都會重新導向至首頁 (
/
),將功能包裝完成,同時保留使用 HTTP 307 傳回代碼的POST
要求。
下載處理常式
更新下載處理常式的模式與上傳處理常式類似,只需查看的程式碼少很多。將 Blob 和 webapp
功能替換為 Cloud Storage 和 Flask 對等項目:
變更前:
class ViewBlobHandler(blobstore_handlers.BlobstoreDownloadHandler):
'view uploaded blob (GET) handler'
def get(self, blob_key):
self.send_blob(blob_key) if blobstore.get(blob_key) else self.error(404)
變更後:
@app.route('/view/<path:fname>')
def view(fname):
'view uploaded blob (GET) handler'
blob = gcs_client.bucket(BUCKET).blob(fname)
try:
media = blob.download_as_bytes()
except exceptions.NotFound:
abort(404)
return send_file(io.BytesIO(media), mimetype=blob.content_type)
本次更新的相關注意事項:
- 再次強調,Flask 會使用其路徑來裝飾處理常式函式,而
webapp
會在底部的路徑資料表執行該函式,因此識別後者的模式比對語法('/view/([^/]+)?'
) 和 Flask 的 ('/view/<path:fname>'
)。 - 與上傳處理常式一樣,為了使用 Blob 處理常式抽取的功能,在 Cloud Storage 端需要進行一些額外工作,也就是識別有問題的檔案 (blob),並明確下載二進位檔與 blob 處理常式的單一
send_blob()
方法呼叫。 - 無論是哪一種情況,都會在找不到成果時傳回 HTTP 404 錯誤。
主要處理常式
主要應用程式的最終變更會在主要處理常式中進行。webapp2
HTTP 動詞方法會由結合其功能的單一函式所取代。將 MainHandler
類別替換為 root()
函式,並移除 webapp2
轉送資料表,如下所示:
變更前:
class MainHandler(BaseHandler):
'main application (GET/POST) handler'
def get(self):
self.render_response('index.html',
upload_url=blobstore.create_upload_url('/upload'))
def post(self):
visits = fetch_visits(10)
self.render_response('index.html', visits=visits)
app = webapp2.WSGIApplication([
('/', MainHandler),
('/upload', UploadHandler),
('/view/([^/]+)?', ViewBlobHandler),
], debug=True)
變更後:
@app.route('/', methods=['GET', 'POST'])
def root():
'main application (GET/POST) handler'
context = {}
if request.method == 'GET':
context['upload_url'] = url_for('upload')
else:
context['visits'] = fetch_visits(10)
return render_template('index.html', **context)
這些方法基本上是 root()
中的 if-else
陳述式,並未分開 get()
和 post()
方法。此外,由於 root()
是單一函式,只會呼叫一次算繪 GET
和 POST
的範本,但 webapp2
實際上無法執行。
以下是 main.py
第二組與最後一組變更的圖片示意圖:
(選用) 回溯相容性「強化」
因此,上述建立的解決方案可以完美運作...但僅適用於您從頭開始建立,且沒有 Blob 建立檔案的情況。由於我們更新了應用程式,以檔案名稱 (而非 BlobKey
) 來識別檔案,因此完成的模組 16 應用程式將無法查看 Blob 檔案。換句話說,我們做出了回溯不相容的變更,導致這項遷移作業執行時無法回溯相容。我們現在提供名為 main-migrate.py
的 main.py
替代版本 (可在存放區中找到),嘗試填補此缺口。
第一個「額外資訊」是一種資料模型,除了 StringProperty
Cloud Storage 建立的檔案之外,還有一個包含 BlobKeyProperty
的資料模型:
class Visit(ndb.Model):
'Visit entity registers visitor IP address & timestamp'
visitor = ndb.StringProperty()
timestamp = ndb.DateTimeProperty(auto_now_add=True)
file_blob = ndb.BlobKeyProperty() # backwards-compatibility
file_gcs = ndb.StringProperty()
file_blob
屬性將用來識別 Blob 建立的檔案,file_gcs
則用於 Cloud Storage 檔案。現在,在建立新的造訪時,明確在 file_gcs
中儲存值 (而非 file_blob
),所以 store_visit 的看起來會稍有不同:
變更前:
def store_visit(remote_addr, user_agent, upload_key):
'create new Visit entity in Datastore'
with ds_client.context():
Visit(visitor='{}: {}'.format(remote_addr, user_agent),
file_blob=upload_key).put()
變更後:
def store_visit(remote_addr, user_agent, upload_key):
'create new Visit entity in Datastore'
with ds_client.context():
Visit(visitor='{}: {}'.format(remote_addr, user_agent),
file_gcs=upload_key).put()
擷取最近的造訪時,請「正規化」再傳送到範本:
變更前:
@app.route('/', methods=['GET', 'POST'])
def root():
'main application (GET/POST) handler'
context = {}
if request.method == 'GET':
context['upload_url'] = url_for('upload')
else:
context['visits'] = fetch_visits(10)
return render_template('index.html', **context)
變更後:
@app.route('/', methods=['GET', 'POST'])
def root():
'main application (GET/POST) handler'
context = {}
if request.method == 'GET':
context['upload_url'] = url_for('upload')
else:
context['visits'] = etl_visits(fetch_visits(10))
return render_template('index.html', **context)
接著,請確認存在 file_blob
或 file_gcs
(或兩者皆無)。如果有可用的檔案,請選取存在的檔案,並使用該識別碼 (BlobKey
適用於 Blob 建立的檔案或 Cloud Storage 建立檔案的檔案名稱)。說到「Cloud Storage 建立的檔案」我們是指使用 Cloud Storage 用戶端程式庫建立的檔案Blob 也會寫入 Cloud Storage,但在這個範例中,就是 Blob 建立的檔案。
更重要的是,這個 etl_visits()
函式用於將使用者的資料正規化或 ETL (擷取、轉換及載入) 資料為何?這是訂閱按鈕的圖示:
def etl_visits(visits):
return [{
'visitor': v.visitor,
'timestamp': v.timestamp,
'file_blob': v.file_gcs if hasattr(v, 'file_gcs') \
and v.file_gcs else v.file_blob
} for v in visits]
這看起來可能像您預期的樣子:程式碼會在所有造訪中循環執行,每次造訪時都會逐字擷取訪客和時間戳記資料,然後檢查是否存在 file_gcs
或 file_blob
,如果有,請選擇其中一個 (如果沒有的話,請選擇 None
)。
下圖說明 main.py
和 main-migrate.py
的差異:
如果您要從頭開始,而沒有建立 Blob 建立的檔案,請使用 main.py
。不過,如果您要轉換並想支援 Blob「和」Cloud Storage 所建立的檔案,請參考 main-migrate.py
範例,瞭解如何處理各種情況,協助您為自己的應用程式規劃遷移作業。執行複雜的遷移作業時,可能會遇到特殊情況,因此這個例子展現了更傾向使用實際資料翻新實際應用程式的相依性。
6. 摘要/清除
本節總結此程式碼研究室的內容,做法是部署應用程式,確認應用程式是否正常運作,以及任何反映的輸出內容。驗證應用程式後,請執行所有清除步驟,並考慮後續步驟。
部署及驗證應用程式
重新部署應用程式之前,請務必執行 pip install -t lib -r requirements.txt
,以便在 lib 資料夾中取得這些自行封裝的第三方程式庫。如要執行回溯相容的解決方案,請先將 main-migrate.py
重新命名為 main.py
。現在執行 gcloud app deploy
,確認應用程式的運作方式與模組 15 應用程式相同。表單畫面如下所示:
最近造訪的網頁看起來如下:
恭喜您完成本程式碼研究室,以 Cloud Storage 取代 App Engine Blob、將 App Engine NDB 替換為 Cloud NDB,以及將 webapp2
替換為 Flask。您的程式碼現在應與 FINISH (Module 16) 資料夾中的內容相符。替代的 main-migrate.py
也存在於該資料夾中。
Python 3「遷移」
只要在 app.yaml
頂端加註 Python 3 runtime
指令,才能將這個應用程式移植到 Python 3。原始碼本身已經與 Python 3 相容,因此無需進行任何變更。如要部署為 Python 3 應用程式,請執行下列步驟:
- 將
app.yaml
頂端的 Python 3runtime
指令取消註解。 - 刪除
app.yaml
中的所有其他行。 - 刪除
appengine_config.py
檔案。(在 Python 3 執行階段中不使用) - 如果
lib
資料夾已存在,請刪除該資料夾。(使用 Python 3 執行階段時不需要)
清除所用資源
一般
如果您現階段已完成設定,建議您停用 App Engine 應用程式,以免產生帳單費用。不過,如果您想測試或進行其他測試,App Engine 平台提供免費配額,而且只要不超出用量限制,就不需支付任何費用。這適用於運算,但相關 App Engine 服務可能也會產生費用,詳情請參閱定價頁面。如果這項遷移作業涉及其他 Cloud 服務,我們會另外計費。無論採用哪種情況,請參閱「本程式碼研究室的專屬」以下章節。
如要完整揭露,部署至 Google Cloud 無伺服器運算平台 (如 App Engine) 會產生少許建構和儲存空間費用。Cloud Build 提供的免費配額與 Cloud Storage 相同。該映像檔的儲存空間會佔用部分配額。不過,您可能居住的區域沒有這類免費方案,因此請留意儲存空間用量,盡可能降低潛在費用。特定 Cloud Storage「資料夾」請務必查看:
console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/images
console.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com
- 上方的儲存空間連結取決於您的
PROJECT_ID
和 *LOC
*,例如「us
」如果應用程式是由美國代管
另一方面,如果您不打算繼續使用這個應用程式或其他相關的遷移程式碼研究室,且想要徹底刪除所有項目,請關閉專案。
本程式碼研究室的專屬功能
下列服務專屬於本程式碼研究室。詳情請參閱每項產品的說明文件:
- App Engine blob 服務低於儲存資料的配額與限制,因此請一併詳閱舊版套裝組合服務的定價頁面。
- Cloud Storage 在特定區域提供免費方案;請參閱一般定價頁面瞭解詳情。
- App Engine Datastore 服務是由 Cloud Datastore (Datastore 模式的 Cloud Firestore) 提供,這項服務也提供免費方案;詳情請參閱價格頁面。」
請注意,如果您從單元 15 遷移至第 16 單元,您仍會在 blob 中保留資料,因此在上方說明相關定價資訊的原因。
後續步驟
除了本教學課程之外,其他著重於淘汰舊版套裝組合服務的其他遷移模組,建議提供以下建議:
- 模組 2:從 App Engine
ndb
遷移至 Cloud NDB - 模組 7 至 9:從 App Engine 工作佇列推送工作遷移至 Cloud Tasks
- 模組 12-13:從 App Engine Memcache 遷移至 Cloud Memorystore
- 模組 18-19:從 App Engine 工作佇列 (提取工作) 遷移至 Cloud Pub/Sub
App Engine 不再是 Google Cloud 中唯一的無伺服器平台。如果您有小型 App Engine 應用程式,或功能有限,但想將其轉換為獨立微服務,或想將單體式應用程式拆解成多個可重複使用的元件,請考慮改用 Cloud Functions。如果容器化已成為應用程式開發工作流程的一部分,特別是在含有 CI/CD (持續整合/持續推送軟體更新或部署) 管道的情況下,請考慮遷移至 Cloud Run。以下單元將介紹這些情境:
- 從 App Engine 遷移至 Cloud Functions:請參閱單元 11
- 從 App Engine 遷移至 Cloud Run:請參閱模組 4,使用 Docker 將應用程式容器化;或參閱模組 5,瞭解如何在沒有容器、Docker 或
Dockerfile
的情況下執行應用程式
您可以選擇是否要改用其他無伺服器平台,在進行任何變更前,建議您考量應用程式和用途的最佳選擇。
無論接下來選擇使用哪個遷移模組,所有無伺服器遷移站內容 (程式碼研究室、影片、原始碼 [如有]) 都可以透過其開放原始碼存放區存取。存放區的 README
還針對應考慮遷移的項目和任何相關的「訂單」提供指引接下來介紹遷移模組
7. 其他資源
程式碼研究室問題/意見回饋
如果您在本程式碼研究室中發現任何問題,請先搜尋您的問題再提出申請。搜尋及建立新問題的連結:
遷移資源
下表提供模組 15 (START) 和單元 16 (FINISH) 的存放區資料夾連結。您也可以透過所有 App Engine 程式碼研究室遷移作業的存放區存取這些資料,可以複製或下載 ZIP 檔案。
Codelab | Python 2 | Python 3 |
單元 15 | 不適用 | |
單元 16 (本程式碼研究室) | (與 Python 2 相同) |
線上資源
以下為可能與本教學課程相關的線上資源:
App Engine Blob 與 Cloud Storage
App Engine 平台
- App Engine 說明文件
- Python 2 App Engine (標準環境) 執行階段
- 在 Python 2 App Engine 上使用 App Engine 內建程式庫
- Python 3 App Engine (標準環境) 執行階段
- Python 2 與3 個 App Engine (標準環境) 執行階段
- Python 2 至 3 App Engine (標準環境) 遷移指南
- App Engine 定價和配額資訊
- 第二代 App Engine 平台推出 (2018)
- 比較最初和第二代平台
- 對舊版執行階段的長期支援
- 說明文件遷移範例存放區
- 社群提供的遷移範例存放區
其他 Cloud 資訊
- 在 Google Cloud Platform 中使用 Python
- Google Cloud Python 用戶端程式庫
- Google Cloud「一律免費」級別
- Google Cloud SDK (
gcloud
指令列工具) - 所有 Google Cloud 說明文件
Python
- Django 和 Jinja2 範本系統
webapp2
個網路架構webapp2
說明文件webapp2_extras
連結webapp2_extras
Jinja2 說明文件- Flask 網路架構
影片
授權
這項內容採用的是創用 CC 姓名標示 2.0 通用授權。