パフォーマンスを改善

このドキュメントでは、アプリケーションのパフォーマンスを向上させるためのテクニックをいくつか説明します。場合によっては他の API や汎用 API を使用していますが、Google Drive API にも同じ概念が適用されます。

gzip を使用した圧縮

各リクエストに必要な帯域幅を削減するための簡単で便利な方法として、gzip 圧縮を有効にする方法があります。この方法では、結果を解凍するために CPU 時間が余分に必要になりますが、ネットワーク費用とのバランスを考えると、時間をかける価値は十分にあります。

gzip でエンコードされたレスポンスを受け取るには、2 つの準備作業が必要です。1 つは、Accept-Encoding ヘッダーを設定すること、もう 1 つは、ユーザー エージェントに gzip という文字列を追加することです。以下に、gzip 圧縮を有効にするための正しい形式の HTTP ヘッダーの例を示します。

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

リソースの部分的な使用

API 呼び出しのパフォーマンスを向上させるためのもう 1 つの方法は、データの必要な部分のみを送受信することです。これにより、アプリケーションが不要なフィールドを転送、解析、格納することがなくなるため、ネットワーク、CPU、メモリなどのリソースをより効率的に使用できます。

部分リクエストには次の 2 種類があります。

  • 部分レスポンス: どのフィールドをレスポンスに含めるかを指定するリクエスト(fields リクエスト パラメータを使用)。
  • パッチ: 変更するフィールドのみを送信する更新リクエスト(PATCH HTTP 動詞を使用)。

以下の各セクションで、部分リクエストの作成方法の詳細について説明します。

部分レスポンス

デフォルトでは、サーバーはリクエストを処理した後、リソースを完全な形で返します。パフォーマンスを向上させるには、サーバーが必要なフィールドのみを送信し、それによって部分レスポンスを取得するように指定します。

部分レスポンスをリクエストするには、fields リクエスト パラメータを使用して取得するフィールドを指定します。このパラメータは、レスポンス データを返す任意のリクエストに指定できます。

fields パラメータはレスポンス データにのみ影響を与えます。送信する必要があるデータには影響を与えません。リソースを変更するときに送信するデータ量を削減するには、patch リクエストを使用します。

パッチ(部分更新)

リソースを変更する際に不要なデータの送信を回避する方法もあります。変更する個々のフィールドについてのみ更新したデータを送信するには、HTTP 動詞 PATCH を使用します。このドキュメントで説明する PATCH 構文は、部分更新の古い実装 GData の PATCH 構文に比べて簡素化されています。

以下に示す簡単な例は、パッチを使用して、小さな更新を行うために送信する必要があるデータを最小化する方法を示しています。

パッチに対するレスポンスを処理する

有効なパッチ リクエストを処理すると、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 接続の回数を減らす方法について説明します。

具体的には、1 件の HTTP リクエストを送信してバッチ リクエストを行う方法を取り上げます。Google クライアント ライブラリを使用してバッチ リクエストを行う場合は、クライアント ライブラリのドキュメントをご覧ください。

概要

クライアントで HTTP 接続を行うたびに、ある程度のオーバーヘッドが発生します。Google Drive API はバッチ処理をサポートしているため、クライアントは複数の API 呼び出しを 1 つの HTTP リクエストにまとめることができます。

バッチ処理は次のような状況で使用します。

  • 多数のファイルのメタデータを取得する。
  • メタデータまたはプロパティを一括で更新する。
  • 新しいユーザーやグループの追加など、多数のファイルの権限を変更する。
  • ローカル クライアント データを初めて同期する場合や、長時間オフラインだった後に同期する場合。

いずれの場合も、各呼び出しを個別に送信するのではなく、1 つの HTTP リクエストにまとめることができます。内部リクエストはすべて同じ Google API に送信する必要があります。

1 つのバッチ リクエストに含めることができる呼び出しの上限は 100 個です。これ以上の呼び出しを行う必要がある場合は、バッチ リクエストを複数使用します。

: Google Drive API のバッチシステムは OData バッチ処理システムと同じ構文を使用しますが、セマンティクスは異なります。

その他の制約には次のものがあります。

  • 100 を超える呼び出しを含むバッチ リクエストはエラーになる可能性があります。
  • 内部リクエストごとに URL の長さに 8,000 文字の上限があります。
  • Google ドライブでは、メディアの一括操作(アップロード、ダウンロード、ファイルのエクスポート)はサポートされていません。

バッチ リクエストの詳細

バッチ リクエストは、複数の API 呼び出しを 1 つの HTTP リクエストにまとめたもので、API ディスカバリ ドキュメントで指定されている batchPath に送信できます。デフォルトのパスは /batch/api_name/api_version です。このセクションでは、バッチ リクエストの構文について詳しく説明し、最後にを紹介します。

: n 件のリクエストを 1 つにまとめたバッチ リクエストは、1 件のリクエストではなく n 件のリクエストとして使用量上限に加算されます。バッチ リクエストは、個々のリクエストに分割されてから処理されます。

バッチ リクエストの形式

バッチ リクエストは、multipart/mixed コンテンツ タイプを使用した単一の標準 HTTP リクエストで、複数の Google Drive API 呼び出しから構成されます。そのメインの HTTP リクエスト内の各パーツには、ネストされた HTTP リクエストが含まれます。

各パーツはそれぞれ Content-Type: application/http という形式の HTTP ヘッダーで始まり、オプションの Content-ID ヘッダーを指定することもできます。ただし、パーツヘッダーはパーツの開始箇所を示すためだけに存在していて、ネストされたリクエストとは分かれています。サーバーがバッチ リクエストを別々のリクエストにアンラップした後、パーツヘッダーは無視されます。

各パーツのボディは、独自の動詞、URL、ヘッダー、ボディを含む完全な HTTP リクエストです。これらの HTTP リクエストには URL のパス部分のみを含める必要があり、完全な URL は、バッチ リクエストでは許可されていません。

外側のバッチ リクエストの HTTP ヘッダー(Content-Type などの Content- ヘッダー以外)はバッチ リクエスト内の各リクエストに適用されます。ある HTTP ヘッダーを外側のリクエストと個々の呼び出しの両方で指定した場合、個々の呼び出しのヘッダー値は外側のバッチ リクエストのヘッダー値を上書きします。個々の呼び出しのヘッダーはその呼び出しにのみ適用されます。

たとえば、ある呼び出しに Authorization ヘッダーを指定した場合、そのヘッダーはその呼び出しにのみ適用されます。Authorization ヘッダーを外側のリクエストに指定した場合、そのヘッダーはすべての呼び出しに適用されます。ただし、各呼び出しに独自の Authorization ヘッダーを指定している場合は各呼び出しの Authorization ヘッダーで上書きされます。

サーバーがバッチ リクエストを受信すると、外側のリクエストのクエリ パラメータとヘッダー(指定した場合)を各パーツに適用し、各パーツを個別の HTTP リクエストとして処理します。

バッチ リクエストへのレスポンス

サーバーのレスポンスは multipart/mixed コンテンツ タイプを使用した単一の標準 HTTP レスポンスです。各パーツはバッチ リクエスト内の個々のリクエストに対するレスポンスで、リクエストと同じ順序にネストされます。

レスポンスの各パーツは、リクエストのパーツと同様にステータス コード、ヘッダー、ボディを含む完全な HTTP レスポンスになっています。また、リクエストのパーツと同様に、レスポンスの各パーツはパーツの開始箇所を示す Content-Type ヘッダーから始まります。

リクエストのパーツに Content-ID ヘッダーがある場合、対応するレスポンスのパーツには、それに一致する Content-ID ヘッダーが指定されます。レスポンスのパーツのヘッダーは、以下の例に示すように、元の値の先頭に文字列 response- が付いた値となります。

: サーバーはバッチ リクエスト内の呼び出しを順番どおりに処理するとは限りません。指定した順序で実行されると想定しないでください。2 つの呼び出しを特定の順序で実行したい場合は、1 つのバッチ リクエストで送信することはできません。代わりに、最初の呼び出しを送信してレスポンスが返ってきてから、2 番目の呼び出しを送信します。

次の例は、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 システム パラメータを使用します。詳細については、特定のフィールドを返すをご覧ください。

aboutcommentsdelete を除く)、repliesdelete を除く)リソースのすべてのメソッドで、fields パラメータを設定する必要があります。これらのメソッドは、デフォルトのフィールドセットを返しません。