App Engine 位置
App Engine 具有「地區性」,這表示執行應用程式的基礎架構位於特定地區,且由 Google 代管,可為該地區內的所有區域提供備援功能。
選擇應用程式的執行地區時,請將您在延遲時間、可用性和耐用性方面的要求,做為主要考量。一般來說,您可以選擇距離您應用程式使用者最近的地區,但您也應該考慮 App Engine 的可用位置,以及應用程式使用的其他Google Cloud 產品和服務的位置。如果跨多個位置使用服務,可能會影響應用程式的延遲時間和定價。
應用程式的地區設定完成後即無法更改。
如果您已建立 App Engine 應用程式,可以透過下列方式查看其區域:
請執行
gcloud app describe
指令。在 Google Cloud 控制台中開啟 App Engine 資訊主頁。區域會顯示在頁面頂端附近。
Cloud NDB 是 Python 適用的用戶端程式庫,可取代 App Engine NDB。App Engine NDB 可讓 Python 2 應用程式在 Datastore 資料庫中儲存及查詢資料。Python 2 和 Python 3 應用程式可透過 Cloud NDB 在相同資料庫中儲存及查詢資料,但管理這些資料庫的產品已從 Datastore 變更為 Datastore 模式的 Firestore。雖然 Cloud NDB 程式庫可以存取使用 App Engine NDB 建立的任何資料,但使用 Cloud NDB 儲存的部分結構化資料類型無法透過 App Engine NDB 存取。因此,遷移至 Cloud NDB 後,應視為不可逆。
建議您先遷移至 Cloud NDB,再將應用程式升級至 Python 3。這種漸進式遷移方法可讓您在整個遷移過程中,維持應用程式的運作和可測試性。
Cloud NDB 的目標是取代 App Engine NDB 中的功能,因此不會支援 Datastore 模式中 Firestore 的新功能。建議新的 Python 3 應用程式使用 Datastore 模式用戶端程式庫,而非 Cloud NDB。
如要進一步瞭解 Cloud NDB,請參閱 GitHub 上的下列頁面:
App Engine NDB 與 Cloud NDB 的比較
相似處:
- Cloud NDB 支援 App Engine NDB 支援的幾乎所有功能,方法語法只有些微差異。
差異:
依賴 App Engine Python 2.7 執行階段專屬服務的 App Engine NDB API,已更新或從 Cloud NDB 移除。
Python 3 和 Django 的新功能已不需要
google.appengine.ext.ndb.django_middleware
。您只需幾行程式碼,就能輕鬆編寫自己的中介軟體。App Engine NDB 應用程式和 Datastore 資料庫必須位於同一個 Google Cloud 專案中,App Engine 會自動提供憑證。只要正確驗證用戶端,Cloud NDB 就能存取任何專案中的 Datastore 模式資料庫。這與其他 Google Cloud API 和用戶端程式庫一致。
Cloud NDB 不會使用 App Engine Memcache 服務來快取資料。
Cloud NDB 可以在 Memorystore、Redis Labs 或其他系統管理的 Redis 記憶體內資料存放區中快取資料。雖然目前僅支援 Redis 資料儲存庫,但 Cloud NDB 已在抽象
GlobalCache
介面中定義一般化快取,可支援其他具體實作項目。如要存取 Memorystore for Redis,應用程式必須使用無伺服器虛擬私有雲存取。
Memorystore for Redis 和無伺服器虛擬私有雲存取都不提供免費層級,而且這些產品可能無法在應用程式的區域使用。詳情請參閱「遷移前須知」。
如需完整差異清單,請參閱 Cloud NDB GitHub 專案的遷移注意事項。
程式碼範例:
開始遷移前
開始遷移前,請先完成下列步驟:
如果您尚未設定 Python 開發環境,請設定該環境以使用與 Google Cloud相容的 Python 版本,並安裝測試工具來建立隔離的 Python 環境。
如要快取資料,請確認應用程式的區域支援 Serverless VPC Access 和 Memorystore for Redis。
判斷是否需要快取資料
如果應用程式需要快取資料,請注意,Memorystore for Redis 和 Serverless VPC Access 沒有免費層級,且不支援所有Google Cloud 區域。
一般而言:
如果應用程式經常讀取相同資料,快取功能可減少延遲。
應用程式處理的要求越多,快取帶來的影響就越大。
如要瞭解目前對快取資料的依賴程度,請查看 Memcache 資訊主頁,瞭解快取命中與未命中率。如果比率偏高,使用資料快取很可能大幅降低應用程式的延遲。
如要瞭解定價,請參閱「Memorystore 定價」 和「無伺服器虛擬私有雲存取定價」。
確認應用程式的區域
如要快取資料,請確認應用程式的區域支援 Memorystore for Redis 和無伺服器虛擬私有雲存取:
在 Google Cloud 控制台的 App Engine 資訊主頁頂端附近,查看應用程式的所在地區。
區域會顯示在頁面頂端附近,就在應用程式網址下方。
確認應用程式位於無伺服器虛擬私有雲存取支援的區域。
前往「建立連接器」頁面,查看「區域」清單中的區域,確認應用程式位於 Memorystore for Redis 支援的區域。
如果應用程式所在的地區不支援 Memorystore for Redis 和 Serverless VPC Access:
建立 Google Cloud 專案。
在專案中建立新的 App Engine 應用程式,然後選取支援的地區。
在新專案中建立應用程式使用的 Google Cloud 服務。
或者,您也可以更新應用程式,使用舊專案中的現有服務,但使用不同專案和區域中的服務時,價格和資源用量可能會有所不同。詳情請參閱各項服務的說明文件。
將應用程式部署至新專案。
瞭解 Datastore 模式權限
與 Google Cloud 服務的每次互動都必須經過授權。舉例來說,如要在 Datastore 模式資料庫中儲存或查詢資料,應用程式必須提供有權存取資料庫的帳戶憑證。
根據預設,應用程式會提供 App Engine 預設服務帳戶的憑證,該帳戶已獲授權可存取與應用程式位於相同專案中的資料庫。
如果符合下列任一條件,您必須使用明確提供憑證的替代驗證技術:
您的應用程式和 Datastore 模式資料庫位於不同的Google Cloud 專案。
您已變更指派給預設 App Engine 服務帳戶的角色。
如要瞭解其他驗證技術,請參閱「設定伺服器對伺服器正式版應用程式的驗證作業」一文。
轉換程序總覽
如要遷移至 Cloud NDB,請按照下列步驟操作:
-
安裝 Cloud NDB 用戶端程式庫。
更新匯入陳述式,從 Cloud NDB 匯入模組。
加入程式碼,建立 Cloud NDB 用戶端。用戶端可以讀取應用程式的環境變數,並使用這些資料向 Datastore 模式進行驗證。
新增使用用戶端執行階段環境的程式碼,在不同執行緒之間保持快取和交易分離。
移除或更新使用不再支援的方法和屬性的程式碼。
啟用快取。
測試更新。
-
如同對應用程式進行的任何變更,請考慮使用流量分配,逐步增加流量。在將更多流量導向更新後的應用程式前,請密切監控應用程式,確認沒有任何資料庫問題。
更新 Python 應用程式
為 Python 應用程式安裝 Cloud NDB 程式庫
如要在 App Engine Python 應用程式中安裝 Cloud NDB 用戶端程式庫,請按照下列步驟操作:
更新
app.yaml
檔案。 請按照您使用的 Python 版本操作:Python 2
如果是 Python 2 應用程式,請新增最新版本的
grpcio
和setuptools
程式庫。以下是
app.yaml
檔案範例:runtime: python27 threadsafe: yes api_version: 1 libraries: - name: grpcio version: latest - name: setuptools version: latest
Python 3
如果是 Python 3 應用程式,請指定
runtime
元素,並使用支援的 Python 3 版本,然後刪除不必要的行。舉例來說,您的app.yaml
檔案可能如下所示:runtime: python310 # or another support version
Python 3 執行階段會自動安裝程式庫,因此您不需要指定先前 Python 2 執行階段的內建程式庫。如果 Python 3 應用程式在遷移時使用其他舊版隨附服務,請保留
app.yaml
檔案。更新
requirements.txt
檔案。請按照您使用的 Python 版本,依下列指示操作:Python 2
在
requirements.txt
檔案的依附元件清單中,加入 Cloud NDB 適用的 Cloud 用戶端程式庫。google-cloud-ndb
然後執行
pip install -t lib -r requirements.txt
,更新應用程式的可用程式庫清單。Python 3
在
requirements.txt
檔案的依附元件清單中,新增 Cloud NDB 適用的 Cloud 用戶端程式庫。google-cloud-ndb
在 Python 3 執行階段部署應用程式時,App Engine 會自動安裝這些依附元件,因此請刪除
lib
資料夾 (如有)。如果是 Python 2 應用程式,如果應用程式使用
lib
目錄中指定的內建或複製程式庫,您必須在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)
請務必使用
pkg_resources
模組,確保應用程式使用正確的用戶端程式庫發行套件。上述範例中的
appengine_config.py
檔案假設lib
資料夾位於目前的工作目錄。如果無法確保lib
一律位於目前的工作目錄中,請指定lib
資料夾的完整路徑。例如:import os path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'lib')
部署應用程式時,App Engine 會上傳
appengine_config.py
檔案中指定目錄的所有程式庫。
更新匯入陳述式
NDB 模組的位置已移至 google.cloud.ndb
。請更新應用程式的匯入陳述式,如下表所示:
移除 | 取代憑證 |
---|---|
from google.appengine.ext import ndb |
from google.cloud import ndb |
建立 Cloud NDB 用戶端
與其他以 Google Cloud API 為基礎的用戶端程式庫一樣,使用 Cloud NDB 的第一步是建立 Client
物件。用戶端包含連線至 Datastore 模式所需的憑證和其他資料。例如:
from google.cloud import ndb
client = ndb.Client()
在先前說明的預設授權情境中,Cloud NDB 用戶端包含來自 App Engine 預設服務帳戶的憑證,該帳戶已獲授權可與 Datastore 模式互動。如果您不是在預設情境中工作,請參閱「應用程式預設憑證 (ADC)」,瞭解如何提供憑證。
使用用戶端的執行階段環境
除了提供與 Datastore 模式互動所需的憑證,Cloud NDB 用戶端也包含 context()
方法,可傳回執行階段環境。執行階段環境會將快取和交易要求,與其他並行的 Datastore 模式互動隔離。
與 Datastore 模式的所有互動都必須在 NDB 執行階段環境中進行。由於建立模型定義時不會與 Datastore 模式互動,因此您可以在建立 Cloud NDB 用戶端及擷取執行階段環境之前,定義模型類別,然後在要求處理常式中使用執行階段環境,從資料庫取得資料。
例如:
多執行緒應用程式
Cloud NDB 用戶端傳回的執行階段環境僅適用於單一執行緒。如果應用程式為單一要求使用多個執行緒,您需要為每個使用 Cloud NDB 程式庫的執行緒,分別擷取執行階段環境。
搭配 WSGI 架構使用執行階段環境
如果網頁應用程式使用 WSGI 架構,您可以建立中介軟體物件來擷取執行階段環境,然後將應用程式包裝在中介軟體物件中,為每個要求自動建立新的執行階段環境。
以下範例說明如何搭配 Flask 使用中介軟體:
middleware
方法會在 NDB 用戶端的執行階段環境中建立 WSGI 中介軟體物件。Flask 應用程式會包裝在中間件物件中。
接著,Flask 會將每項要求傳遞至中介軟體物件,中介軟體會為每項要求擷取新的 NDB 執行階段環境。
搭配 Django 使用執行階段環境
Cloud NDB 程式庫不支援 App Engine NDB 程式庫提供的 Django 中介軟體。如果您在應用程式中使用這個中介軟體 (google.appengine.ext.ndb.django_middleware
),請按照下列步驟更新應用程式:
使用 Django 的中介軟體系統,為每個要求建立新的執行階段環境。
在下列範例中:
ndb_django_middleware
方法會建立 Cloud NDB 用戶端。middleware
方法會在 NDB 用戶端的執行階段環境中建立中介軟體物件。
在 Django settings.py 檔案中,更新
MIDDLEWARE
設定,列出您建立的新中介軟體,而非google.appengine.ext.ndb.NdbDjangoMiddleware
。
Django 現在會將每個要求傳遞至您在 MIDDLEWARE
設定中列出的中介軟體物件,而這個物件會為每個要求擷取新的 NDB 執行階段環境。
更新已移除或變更的 NDB API 程式碼
依賴 App Engine 專屬 API 和服務的 NDB API 已更新或從 Cloud NDB 程式庫中移除。
如果您的程式碼使用下列任一 NDB API,就必須更新程式碼:
google.appengine.ext.ndb.Model
和模型屬性google.appengine.ext.ndb.Key
google.appengine.ext.ndb.query.QueryOptions
和PropertyOrder
google.appengine.ext.ndb.utils
google.appengine.api.namespacemanager
google.appengine.api.ext.ndb.tasklets
google.appengine.api.datastore_errors
模型和模型屬性
Cloud NDB 程式庫不支援下列 google.appengine.ext.ndb.Model
方法,因為這些方法使用 App Engine 專屬的 API,而這些 API 已不再提供。
已移除的 API | 替換 |
---|---|
Model.get_indexes 和 Model.get_indexes_async
|
無 |
Model._deserialize 和 Model._serialize
|
無 |
Model.make_connection
|
無 |
下表說明 Cloud NDB 程式庫中變更的特定
google.appengine.ext.ndb.Model
屬性:
屬性 | 變更 |
---|---|
TextProperty
|
google.cloud.ndb.TextProperty 無法建立索引。如果您嘗試設定 google.cloud.ndb.TextProperty.indexed ,系統會引發 NotImplementedError 。 |
StringProperty
|
StringProperty 一律會編入索引。如果您嘗試設定 google.cloud.ndb.StringProperty.indexed ,系統會引發 NotImplementedError 。 |
建構函式中具有 name 或 kind 引數的所有屬性。 |
name 或 kind 必須是 str 資料型別,因為 unicode 在 Python 3 中已由 str 取代。 |
下表中的類別和方法已無法使用,因為這些類別和方法使用 App Engine 專屬資源,而這些資源已無法使用。
已移除的 API | 替換 |
---|---|
google.appengine.ext.ndb.msgprop.MessageProperty 和 google.appengine.ext.ndb.msgprop.EnumProperty
|
無
如果嘗試建立這些物件,系統會引發 |
從
google.appengine.ext.ndb.model.Property :_db_get_value _db_set_value _db_set_compressed_meaning _db_set_uncompressed_meaning __creation_counter_global
|
無
這些方法依賴已變更的 Datastore 模式通訊協定緩衝區。 |
Model.make_connection
|
無 |
鍵
Cloud NDB 程式庫不提供 google.appengine.ext.ndb.Key
的下列方法。這些方法用於在 DB Datastore API 之間傳遞金鑰,但該 API 已停止支援 (DB 是 App Engine NDB 的前身)。
已移除的 API | 替換 |
---|---|
Key.from_old_key 和 Key.to_old_key
|
無 |
此外,請注意下列變更:
App Engine NDB | Cloud NDB |
---|---|
種類和字串 ID 長度不得超過 500 個位元組 | 種類和字串 ID 不得超過 1500 個位元組。 |
Key.app() 會傳回您在建立金鑰時指定的專案 ID。 |
google.cloud.ndb.Key.app() 傳回的值可能與傳遞至建構函式的原始 ID 不同。這是因為前置應用程式 ID (例如 s~example) 是 App Engine 的舊版 ID。這些 ID 已由對應的專案 ID 取代,例如「example」。 |
查詢
與 App Engine NDB 類似,Cloud NDB 提供 QueryOptions
類別 (google.cloud.ndb.query.QueryOptions
),可讓您重複使用一組特定的查詢選項,不必為每個查詢重新定義。不過,Cloud NDB 中的 QueryOptions
不會從 google.appengine.datastore.datastore_rpc.Configuration
繼承,因此不支援 ...datastore_rpc.Configuration
方法。
此外,google.appengine.datastore.datastore_query.Order
已替換為 google.cloud.ndb.query.PropertyOrder
。與 Order
類似,PropertyOrder
類別可讓您指定多個查詢的排序順序。PropertyOrder
建構函式與 Order
的建構函式相同。只有類別名稱有所變更。
已移除的 API | 替換 |
---|---|
從「google.appengine.datastore.datastore_rpc.Configuration 」複製:deadline(value) on_completion(value) read_policy(value) force_writes(value) max_entity_groups_per_rpc(value) max_allocate_ids_keys(value) max_rpc_bytes(value) max_get_keys(value) max_put_entities(value) max_delete_keys(value)
如要瞭解這些方法,請參閱原始碼。 |
無 |
google.appengine.ext.ndb.Order 例如: order=Order(-Account.birthday, Account.name)
|
google.cloud.ndb.PropertyOrder 例如: google.cloud.ndb.PropertyOrder(-Account.birthday, Account.name)
|
Utils
ndb.utils
模組 (google.appengine.ext.ndb.utils
) 已停用。該模組中的大多數方法都屬於 App Engine NDB 內部方法,有些方法因新版 ndb 的實作差異而遭到捨棄,其他方法則因新的 Python 3 功能而遭到淘汰。
舉例來說,舊版 utils
模組中的位置裝飾器宣告,函式或方法只能有前 n 個位置引數。不過,Python 3 可以使用僅限關鍵字的引數執行這項操作。過去的寫法:
@utils.positional(2)
def function1(arg1, arg2, arg3=None, arg4=None)
pass
在 Python 3 中可以寫成這樣:
def function1(arg1, arg2, *, arg3=None, arg4=None)
pass
命名空間
命名空間可讓「多租戶應用程式」為每個租戶使用各自獨立的資料孤島,同時仍使用相同的 Datastore 模式資料庫。也就是說,每個用戶群都會在自己的命名空間下儲存資料。
您可以在建立 Cloud NDB 用戶端時指定預設命名空間,然後在用戶端的執行階段環境中呼叫 Cloud NDB 方法,即可使用預設命名空間,不必使用 App Engine 專屬的 google.appengine.api.namespacemanager
。這與其他支援命名空間的 Google CloudAPI 遵循相同的模式。
已移除的 API | 替換 |
---|---|
google.appengine.api.namespace_manager.namespace_manager.set_namespace(str)
和 google.appengine.api.namespacemanager.getnamespace()
|
client=google.cloud.ndb.Client(namespace="my namespace") with client.context() as context: key = ndb.Key("SomeKind", "SomeId") key-non-default-namespace=ndb.Key("SomeKind," "AnotherId", namespace="non-default-nspace") |
所有其他 google.appengine.api.namespacemanager 方法 |
無 |
Tasklet
Tasklet 現在可以使用標準 return
陳述式傳回結果,不必引發 Return
例外狀況。例如:
App Engine NDB 程式庫 | Cloud NDB 程式庫 |
---|---|
@ndb.tasklet def get_cart(): cart = yield CartItem.query().fetch_async() raise Return(cart) |
@ndb.tasklet def get_cart(): cart = yield CartItem.query().fetch_async() return cart |
請注意,您仍可透過引發 Return
例外狀況,在 Cloud NDB 中傳回結果,但不建議這麼做。
此外,下列 Tasklets
方法和子類別已無法使用,主要是因為 Cloud NDB 程式庫建立及使用 NDB 環境的方式有所變更。
已移除的 API | 替換 |
---|---|
從
google.appengine.api.ext.ndb.tasklets :add_flow_exception make_context make_default_context set_context
|
無 |
從
google.appengine.api.ext.ndb.tasklets :QueueFuture ReducedFuture SerialQueueFuture
|
無 |
例外狀況
雖然 Cloud NDB 程式庫的 google.cloud.ndb.exceptions
模組包含許多與 App Engine NDB 程式庫相同的例外狀況,但並非所有舊的例外狀況都適用於新程式庫。下表列出不再適用的例外狀況:
已移除的 API | 替換 |
---|---|
從
google.appengine.api.datastore_errors :BadKeyError BadPropertyError CommittedButStillApplying EntityNotFoundError InternalError NeedIndexError QueryNotFoundError ReferencePropertyResolveError Timeout TransactionFailedError TransactionNotFoundError
|
google.cloud.ndb.exceptions |
啟用資料快取
Cloud NDB 可在由 Memorystore、Redis Labs 或其他系統管理的 Redis 記憶體內資料儲存庫中快取資料。本指南說明如何使用 Memorystore for Redis 快取資料:
設定無伺服器虛擬私有雲存取
應用程式只能透過無伺服器虛擬私有雲存取連接器與 Memorystore 通訊。如要設定無伺服器虛擬私有雲存取連接器,請按照下列步驟操作:
設定 Memorystore for Redis
如要設定 Memorystore for Redis,請按照下列步驟操作:
在 Memorystore 中建立 Redis 執行個體。建立執行個體時,請注意以下事項:
在「Region」(地區) 下方,選取與 App Engine 應用程式所在的地區。
在「授權網路」下方,選取無伺服器虛擬私有雲存取連接器使用的網路。
請記下您建立的 Redis 執行個體 IP 位址和通訊埠編號。 為 Cloud NDB 啟用資料快取時,您會使用這項資訊。
請務必使用
gcloud beta
指令部署應用程式更新。只有 Beta 版指令可以更新應用程式,以使用虛擬私有雲連接器。
新增 Redis 連線網址
如要連線至 Redis 快取,請在應用程式的 app.yaml
檔案中新增 REDIS_CACHE_URL
環境變數。REDIS_CACHE_URL
的值格式如下:
redis://IP address for your instance:port
舉例來說,您可以將下列程式碼新增至應用程式的 app.yaml
檔案:
env_variables:
REDIS_CACHE_URL: redis://10.0.0.3:6379
建立及使用 Redis 快取物件
如果您已將 REDIS_CACHE_URL
設為環境變數,可以使用單行程式碼建立 RedisCache 物件,然後在設定執行階段環境時,將該物件傳遞至 Client.context()
,即可使用快取:
client = ndb.Client()
global_cache = ndb.RedisCache.from_environment()
with client.context(global_cache=global_cache):
books = Book.query()
for book in books:
print(book.to_dict())
如果未將 REDIS_CACHE_URL
設為環境變數,則必須建構 Redis 用戶端,並將該用戶端傳遞至 ndb.RedisCache()
建構函式。例如:
global_cache = ndb.RedisCache(redis.StrictRedis(host=IP-address, port=redis_port))
請注意,您不需要宣告 Redis 用戶端程式庫的依附元件,因為 Cloud NDB 程式庫已依附於 Redis 用戶端程式庫。
如需建構 Redis 用戶端的範例,請參閱 Memorystore 範例應用程式。
測試更新
如要設定測試資料庫並在本機執行應用程式,然後再將應用程式部署到 App Engine,請按照下列步驟操作:
執行 Datastore 模式本機模擬器,儲存及擷取資料。
請務必按照設定環境變數的操作說明操作,讓應用程式連線至模擬器,而非實際運作的 Datastore 模式環境。
如要開始測試,並預先將資料載入資料庫,也可以將資料匯入模擬器。
使用本機開發伺服器執行應用程式。
如要確保在本地開發期間正確設定
GOOGLE_CLOUD_PROJECT
環境變數,請使用下列參數初始化dev_appserver
:--application=PROJECT_ID
將 PROJECT_ID 替換為專案 ID。 Google Cloud 您可以執行
gcloud config list project
指令,或在 Google Cloud 控制台中查看專案頁面,找出專案 ID。
部署您的應用程式
應用程式在本機開發伺服器中順利執行後,請按照下列步驟操作:
如果應用程式順利執行,請使用流量分割,逐步增加更新版應用程式的流量。在將更多流量導向更新版應用程式之前,請密切監控應用程式,確認是否有任何資料庫問題。
後續步驟
- 如需實作教學課程,請參閱從 App Engine ndb 遷移至 Cloud NDB 程式碼研究室。
- 詳情請參閱 Cloud NDB 說明文件。