提升效能

本文說明提升應用程式成效的幾個技巧。在某些情況下,我們會使用其他 API 或通用 API 的範例來說明這些技巧背後的概念。不過,同樣的概念也適用於 Google Drive API。

使用 gzip 壓縮

要減少每個要求占用的頻寬,最簡單的方法就是使用 gzip 壓縮檔。雖然此方法需要額外的 CPU 作業時間解壓縮,但相對可省下可觀的網路成本。

如果要接收以 gzip 編碼的回應,您必須執行下列兩項操作:設定 Accept-Encoding 標頭,並修改您的使用者代理程式來加入字串 gzip。以下是一個啟用 gzip 壓縮的正確 HTTP 標頭格式範例:

Accept-Encoding: gzip
User-Agent: my program (gzip)

使用部分資源

另一種提高 API 呼叫成效的方式,就是只收發您有興趣的資料。這麼做可避免讓您的應用程式傳輸、剖析及儲存不需要的欄位,進而更有效地使用網路、CPU 以及記憶體等資源。

部分要求分為兩類:

  • 部分回應:您可以在這類要求中,指定要在回應中加入哪些欄位 (使用 fields 要求參數)。
  • 修補:透過這類更新要求,您可以只傳送想要變更的欄位 (使用 PATCH HTTP 動詞)。

接下來的章節將會詳細說明如何提交部分要求。

部分回應

根據預設,伺服器會在處理要求後傳回完整的資源表示法。為改善成效,您可以要求伺服器只傳送您真正需要的欄位,並改為取得「部分回應」

如果要請求部分回應,請使用 fields 要求參數來指定您想要傳回的欄位。您可以將此參數搭配任何會傳回回應資料的要求使用。

請注意,fields 參數只會影響回應資料;不會影響您需要傳送的資料 (如果有的話)。如果要減少您在修改資源時傳送的資料量,請使用修補要求。

範例

修補 (部分更新)

修改資源時,您也可以避免傳送不必要的資料。如果是僅為要變更的特定欄位傳送更新資料,請使用 HTTP PATCH 動詞。相較於舊版的 GData 部分更新執行方式,在本文中,「修補」一詞的語意變得更加簡單。

下面的簡短範例將會示範如何使用修補功能,在進行小規模更新時將您需要傳送的資料量減到最小。

範例

處理修補回應

API 會在處理完有效的修補要求之後,傳回 200 OK HTTP 回應代碼以及修改後資源的完整表示法。如果 API 有使用 ETag 的話,伺服器會在成功處理完修補要求時更新 ETag 的值,就像 PUT 一樣。

修補要求會傳回整個資源表示法,除非您使用 fields 參數來減少傳回的資料量。

如果 修補 要求產生的新資源狀態具有無效的語法或語意,則伺服器會傳回 400 Bad Request 或 422 Unprocessable Entity HTTP 狀態碼,且資源狀態維持不變。舉例來說,如果您嘗試刪除必填欄位的值,則伺服器會傳回錯誤。

當 PATCH HTTP 動詞未受支援時可使用的替代標示方法

如果您的防火牆禁止使用 HTTP PATCH 要求,請執行 HTTP POST 要求,並將替換標頭設定為 PATCH,如下所示:

POST https://www.googleapis.com/...
X-HTTP-Method-Override: PATCH
...

修補和更新之間的差異

就實務層面而言,為使用了 HTTP PUT 動詞的更新要求傳送資料時,您只需要傳送必填或選填欄位;如果您傳送了由伺服器設定的欄位值,這些值將會遭到忽略。雖然這看起來像是執行部分更新的另一種方法,但此方法有一些限制存在。使用 HTTP PUT 動詞進行更新時,如果您沒有提供必要參數,則要求將會失敗;此外,如果您沒有提供選用參數,則要求將會清除先前設定的資料。

這也是在此情況下使用修補更加安全的原因。您只需要為您想要變更的欄位提供資料,而您省略的欄位將不會被清除。此規則唯一的例外便是重複元素或陣列:如果您全數省略,它們將會保持原狀;如果您提供了任何重複元素或陣列,則整組元素或陣列都會替換成您提供的組合。

批次要求

本文說明如何批次處理 API 呼叫,以減少用戶端必須建立的 HTTP 連線數量。

本文專門說明如何透過傳送 HTTP 要求來提交批次要求。如果您是使用 Google 用戶端程式庫提交批次要求,請參閱用戶端程式庫的說明文件

總覽

用戶端建立的每個 HTTP 連線都會造成一定程度的負擔。Google Drive API 支援批次作業,可以讓用戶端在單一 HTTP 要求中加入數個 API 呼叫。

以下是您可能想要使用批次作業的狀況範例:

  • 擷取大量檔案的中繼資料。
  • 大量更新中繼資料或屬性。
  • 變更大量檔案的權限,例如新增使用者或群組。
  • 首次同步處理本機用戶端資料,或在離線一段時間後同步處理。

在任一案例中,都不需要個別傳送每一個呼叫,只需將這些呼叫分組後組成單一 HTTP 要求。所有內部要求都必須前往相同的 Google API。

單一批次要求最多能包含 100 個呼叫,如果您必須進行更多呼叫,請使用多個批次要求。

注意:Google Drive API 的批次系統使用的語法與 OData 批次處理系統相同,但語意不同。

其他限制包括:

  • 包含超過 100 個呼叫的批次要求可能會導致錯誤。
  • 每個內部要求的網址長度上限為 8,000 個半形字元。
  • Google 雲端硬碟不支援媒體的批次作業,包括上傳/下載或匯出檔案。

批次詳細資料

批次要求是由多個 API 呼叫合併成一個 HTTP 要求,系統會將這個要求傳送至 API 探索文件中指定的 batchPath。預設路徑為 /batch/api_name/api_version。本節詳細說明批次語法,並在後半段提供範例

注意:組成批次的 n 個要求在用量限制中會算成 n 個要求,而不是一個要求。批次要求會先分解成一組要求再進行處理。

批次要求的格式

批次要求是單一標準 HTTP 要求,內含多個使用 multipart/mixed 內容類型的 Google Drive API 呼叫。在主要 HTTP 要求中,每個分部都含有一個巢狀的 HTTP 要求。

每個部分的開頭都會加上專屬的 Content-Type: application/http HTTP 標頭。也可以有選用的 Content-ID 標頭。不過,部分標頭只是用來標示部分的開頭,與巢狀要求分開。伺服器將批次要求展開為個別要求後,就會忽略部分標頭。

每個部分的主體都是完整的 HTTP 要求,各有專屬的動詞、網址、標頭和主體。HTTP 要求只能包含 URL 的路徑部分;批次要求禁止納入完整的 URL。

外部批次要求的 HTTP 標頭 (除了 Content- 標頭,例如 Content-Type) 會套用至批次中的每個要求。如果您在外部要求和個別呼叫中均指定所提供的 HTTP 標頭,則個別呼叫標頭的值會覆寫外部批次要求標頭的值。個別呼叫的標頭只會套用於該呼叫。

例如,如果您提供 Authorization 標頭用於特定呼叫,則該標頭只會套用於該呼叫。如果您提供 Authorization 標頭用於外部要求,則除非個別呼叫以自己的 Authorization 標頭覆寫所提供的標頭,否則所提供的 Authorization 標頭會套用於所有個別呼叫。

當伺服器收到批次要求時,即會將外部要求的查詢參數和標頭 (在適用情況下) 套用至每一個分部,然後將每個分部視為不同的 HTTP 要求。

回應批次要求

伺服器的回應是單一標準 HTTP 回應,內含 multipart/mixed 內容類型;每個部分都是對批次要求中某個要求的回應,並按照要求的順序排列。

就像要求中的分部一樣,每個回應分部都含有完整的 HTTP 回應,包括狀態碼、標頭和內文;就像要求中的部分一樣,每個回應部分前面都會加上 Content-Type 標頭,標示部分的開頭。

如果要求的特定部分含有 Content-ID 標頭,則回應的對應部分就會含有相符的 Content-ID 標頭,原始值前方會加上字串 response-,如以下範例所示。

注意:伺服器可能會以任意順序執行您的呼叫。不要期望呼叫會按您的指定順序執行。如果您想要確保兩個呼叫依指定順序執行,就不能以單一要求傳送它們,而要先傳送第一個呼叫,然後等到第一個呼叫的回應後才能傳送第二個呼叫。

範例

以下範例說明如何使用 Google Drive API 的批次作業。

批次要求範例

POST https://www.googleapis.com/batch/drive/v3
Accept-Encoding: gzip
User-Agent: Google-HTTP-Java-Client/1.20.0 (gzip)
Content-Type: multipart/mixed; boundary=END_OF_PART
Content-Length: 963

--END_OF_PART Content-Length: 337 Content-Type: application/http content-id: 1 content-transfer-encoding: binary

POST https://www.googleapis.com/drive/v3/files/fileId/permissions?fields=id Authorization: Bearer authorization_token Content-Length: 70 Content-Type: application/json; charset=UTF-8

{ "emailAddress":"example@appsrocks.com", "role":"writer", "type":"user" } --END_OF_PART Content-Length: 353 Content-Type: application/http content-id: 2 content-transfer-encoding: binary

POST https://www.googleapis.com/drive/v3/files/fileId/permissions?fields=id&sendNotificationEmail=false Authorization: Bearer authorization_token Content-Length: 58 Content-Type: application/json; charset=UTF-8

{ "domain":"appsrocks.com", "role":"reader", "type":"domain" } --END_OF_PART--

批次回應範例

這是前一節中範例要求的回應。

HTTP/1.1 200 OK
Alt-Svc: quic=":443"; p="1"; ma=604800
Server: GSE
Alternate-Protocol: 443:quic,p=1
X-Frame-Options: SAMEORIGIN
Content-Encoding: gzip
X-XSS-Protection: 1; mode=block
Content-Type: multipart/mixed; boundary=batch_6VIxXCQbJoQ_AATxy_GgFUk
Transfer-Encoding: chunked
X-Content-Type-Options: nosniff
Date: Fri, 13 Nov 2015 19:28:59 GMT
Cache-Control: private, max-age=0
Vary: X-Origin
Vary: Origin
Expires: Fri, 13 Nov 2015 19:28:59 GMT

--batch_6VIxXCQbJoQ_AATxy_GgFUk Content-Type: application/http Content-ID: response-1

HTTP/1.1 200 OK Content-Type: application/json; charset=UTF-8 Date: Fri, 13 Nov 2015 19:28:59 GMT Expires: Fri, 13 Nov 2015 19:28:59 GMT Cache-Control: private, max-age=0 Content-Length: 35

{ "id": "12218244892818058021i" }

--batch_6VIxXCQbJoQ_AATxy_GgFUk Content-Type: application/http Content-ID: response-2

HTTP/1.1 200 OK Content-Type: application/json; charset=UTF-8 Date: Fri, 13 Nov 2015 19:28:59 GMT Expires: Fri, 13 Nov 2015 19:28:59 GMT Cache-Control: private, max-age=0 Content-Length: 35

{ "id": "04109509152946699072k" }

--batch_6VIxXCQbJoQ_AATxy_GgFUk--

傳回要求中的特定欄位

如果您未指定 fields 參數,伺服器會傳回方法專屬的預設欄位組合。舉例來說,files.list 方法只會傳回 kindidnamemimeType 欄位。

系統傳回的預設欄位可能不是您需要的欄位。如果您想指定回應中要傳回的欄位,請使用 fields 系統參數。詳情請參閱「傳回特定欄位」。

對於 aboutcomments (不含 delete) 和 replies (不含 delete) 資源的所有方法,您必須設定 fields 參數。這些方法不會傳回預設欄位組合。