透過 Remote API 存取 App Engine

所有 Python 用戶端都可透過 Remote API 程式庫存取 App Engine 應用程式的可用服務。

舉例來說,如果 App Engine 應用程式使用 Cloud Datastore 或 Google Cloud Storage,Python 用戶端即可透過 Remote API 存取這些儲存空間資源。

若要存取應用程式的資料儲存庫,您可以透過 Remote API 從本機機器上執行的應用程式或從本機互動式 Remote API 殼層來執行存取作業。Remote API 會與實際服務互動,因此存取作業會用到配額與計費資源。

Python 專用的 App Engine SDK 包含 Remote API 程式庫。

啟用應用程式的 Remote API 存取

如要啟用應用程式的 Remote API,最簡單的方式是在應用程式的 app.yaml 檔案中使用 builtins 指令來指定預設網址 /_ah/remote_api/。不過,您也可以在相同檔案中使用 url 指令來指定其他網址。

builtin

app.yaml 檔案中使用 builtins 指令,可在預設網址 /_ah/remote_api 提供 Remote API:

runtime: python27
api_version: 1
threadsafe: true

builtins:
- remote_api: on

URL

app.yaml 中使用 url 指令,可指定與 Remote API 搭配使用的其他網址:

- url: /some-URL/*
  script: google.appengine.ext.remote_api.handler.application

進行這項變更後,請務必將應用程式部署至 App Engine。

使用 Remote API 殼層

Python SDK 包含 Remote API 殼層,可讓您在應用程式使用的 App Engine 服務上叫用 Python 指令。您無需額外提供任何驗證,因為這會自動使用您將應用程式上傳至 App Engine 時的相同憑證。

如要啟動 Remote API 殼層:

  1. 從本機電腦中的終端機視窗叫用下列指令:

     [SDK-INSTALL-DIRECTORY]/remote_api_shell.py -s [YOUR-PROJECT-ID].appspot.com
    

    [SDK-INSTALL-DIRECTORY] 替換為 Python 專用 App Engine SDK 的路徑,並將 [YOUR-PROJECT-ID] 替換為您的專案 ID。

  2. 在接著顯示的互動式殼層中,叫用您要執行的 Python 指令。舉例來說,如果應用程式使用了 Cloud Datastore,您可以叫用下列 NDB 查詢來擷取 10 筆記錄:

     >>> from google.appengine.ext import ndb
     >>>
     >>> # Fetch 10 keys from the datastore
     >>> ndb.Query().fetch(10, keys_only=True)
    

在本機用戶端上使用 Remote API

您也可以在本機應用程式中使用 Remote API,以便存取在 App Engine 中執行的應用程式所使用的服務。

如要在本機應用程式上使用 Remote API:

  1. 啟用 Remote API

  2. 匯出 Python 目錄中的 PYTHONPATH 環境變數,例如:

     export PYTHONPATH=/usr/somedir/v3/bin/python2.7
    

    以實際的 Python 位置值取代該路徑。

  3. 將 Python 專用的 App Engine SDK 的位置新增至 PYTHONPATH

     export GAE_SDK_ROOT="/usr/local/home/mydir/google_appengine"
     export PYTHONPATH=${GAE_SDK_ROOT}:${PYTHONPATH}
    

    以 App Engine SDK 的實際路徑取代上方的 SDK 路徑。

  4. 在用戶端程式碼中匯入 dev_appserver 並呼叫 dev_appserver.fix_sys_path(),確保所有的 App Engine SDK 模組均已正確匯入:

    try:
        import dev_appserver
        dev_appserver.fix_sys_path()
  5. 將下列 remote_api_stub 程式碼新增至應用程式,並確認在程式碼中傳送專案 ID:

    remote_api_stub.ConfigureRemoteApiForOAuth(
        '{}.appspot.com'.format(project_id),
        '/_ah/remote_api')

    如果您不是使用 Remote API 的預設網址 /_ah/remote_api,您必須變更上述程式碼以反映您使用的網址。如需 remote_api_stub.ConfigureRemoteApiForOAuth 的定義與說明文件,請參閱下列 SDK 檔案:[SDK-INSTALL-DIRECTORY]/google/appengine/ext/remote_api/remote_api_stub.py

  6. 新增任何必要 App Engine 匯入項目和 Python 程式碼,以便使用所需的 App Engine 服務。執行以下程式碼範例,即可存取專案的資料儲存庫:

    
    import argparse
    
    try:
        import dev_appserver
        dev_appserver.fix_sys_path()
    except ImportError:
        print('Please make sure the App Engine SDK is in your PYTHONPATH.')
        raise
    
    from google.appengine.ext import ndb
    from google.appengine.ext.remote_api import remote_api_stub
    
    def main(project_id):
        remote_api_stub.ConfigureRemoteApiForOAuth(
            '{}.appspot.com'.format(project_id),
            '/_ah/remote_api')
    
        # List the first 10 keys in the datastore.
        keys = ndb.Query().fetch(10, keys_only=True)
    
        for key in keys:
            print(key)
    
    if __name__ == '__main__':
        parser = argparse.ArgumentParser(
            description=__doc__,
            formatter_class=argparse.RawDescriptionHelpFormatter)
        parser.add_argument('project_id', help='Your Project ID.')
    
        args = parser.parse_args()
    
        main(args.project_id)
  7. 在應用程式部署至 App Engine 的情況下,啟動 Remote API 用戶端:

     python your-client.py YOUR-PROJECT-ID
    

    以您的用戶端模組取代 your-client.py,並以您的專案 ID 取代 YOUR-PROJECT-ID。這項操作是假設您的用戶端會按照 client.py 程式碼範例接受指令列輸入內容中的專案 ID。

限制與最佳做法

remote_api 模組會盡所有可能,使其運作方式與原生 App Engine 資料儲存庫完全相同。在某些情況下,這意謂著該運作效率可能會較原有運作方式低。使用 remote_api 時,必須記住幾個重點:

每個資料儲存庫要求都需要一去一回

由於您是透過 HTTP 存取資料儲存庫,因此產生的負擔與延遲會比本機存取略高一些。為加快速度並減少負荷,請透過批次取得與放入,以及批次從查詢擷取實體,嘗試限制去回的次數。無論是對於 remote_api,還是在一般情況下使用資料儲存庫,這都是值得參考的建議,因為系統只會將批次作業視為單一資料儲存庫作業。舉例來說,如果您不希望這麼做:

for key in keys:
  rec = key.get()
  rec.foo = bar
  rec.put()

可以改為執行:

records = ndb.get_multi(keys)
for rec in records:
  rec.foo = bar
  ndb.put_multi(records)

這兩個範例的效果相同,但後者總共只需要兩次去回,前者的每個實體則都需要兩次去回。

向 remote_api 發出的要求會使用配額

由於 remote_api 透過 HTTP 操作,因此您每次呼叫資料儲存庫都會針對 HTTP 要求產生配額使用量、接收和傳送的位元組,以及您預期的一般資料儲存庫配額。如果您是透過 remote_api 執行批次更新,請務必記住這一點。

適用 1 MB API 限制

跟在本機執行時一樣,API 要求和回應的 1MB 限制仍然適用。如果您的實體數量特別龐大,您可能需要限制一次擷取或放入的數量,以符合這個限制。不幸的是,這會與去回次數的最小化發生衝突,因此最好的做法是,使用不超過要求或回應限制的最大批次操作數量。但是,就大多數的實體來說,這不會是一個問題。

避免疊代處理查詢

以下是一個常見的資料儲存庫存取模式:

q = MyModel.query()
for entity in q:
  # Do something with entity

如果您採用這個模式,SDK 會以 20 個實體為一個批次的方式從資料儲存庫中擷取實體,並在現有實體耗盡時擷取新的一批實體。remote_api 必須透過不同的要求擷取各批實體,因此效率較低。有鑑於此,remote_api 會改用偏移功能進一步擷取結果,為每個批次執行全新的查詢。

如果您可以掌握所需實體數量,則能直接在單次要求中擷取所需數量來完成整項擷取工作。

entities = MyModel.query().fetch(100)
for entity in entities:
  # Do something with entity

如果您無法掌握所需實體數量,可以使用游標有效率地疊代處理大型結果集。這也可以讓您規避一般資料儲存庫查詢的 1000 個實體限制。

交易的效率較低

為了透過 remote_api 實作交易,將累積在交易內部擷取的實體資訊,以及在交易內部放置或刪除的實體副本。認可交易之後,系統會將這些資訊全數傳送至 App Engine 伺服器,而其必須在此處再次擷取交易所使用的所有實體、確認這些實體未遭到修改,然後放入並刪除交易所做的所有變更,再予以認可。如果發生衝突,伺服器會退回交易,並通知用戶端,然後用戶端必須重複整個過程。

這個方法是行得通的,而且會在本機資料儲存庫上完整重現交易所提供的功能,不過效率較低。總而言之,您可以視需求使用交易,不過請嘗試限制所執行交易的數量與複雜程度,以免效率過低。

本頁內容對您是否有任何幫助?請提供意見:

傳送您對下列選項的寶貴意見...

這個網頁
Python 2 適用的 App Engine 標準環境