複合オブジェクトと並列アップロード

並列アップロードや制限付きの追加 / 編集機能をサポートするために、Cloud Storage では、ユーザーは追加のオブジェクト データを転送しなくても、新しいオブジェクト内に最大 32 個の既存のオブジェクトを作成することができます。

作成オペレーション

作成オペレーションでは、新規オブジェクトを作成します。このオブジェクトは、最大 32 のコンポーネント オブジェクトの配列を連結したもので、同一バケット下に構成されます。これらのコンポーネントは、この処理の影響を受けず、結果として得られる複合は、コンポーネントが置換または削除された場合でも変わりません。

コンポーネントの合計数が 1,024 を超過していないことを条件として、他の既存のコンポジットから複合オブジェクトを作成することもできます。作成可能なコンポーネント数にはプロジェクトごとのレート制限があり、1 秒あたり約 200 個を作成することができます。複合オブジェクトをコピーする場合、複合オブジェクトに追加されるコンポーネントだけでなく、複合オブジェクトにコピーされるコンポーネントの両方が制限の対象となります。

コンポーネント カウント プロパティ

各オブジェクトは、そのオブジェクトが作成された当初にアップロードされたオブジェクト数を指定する、component count プロパティを保持します。オブジェクトのシーケンスを作成すると、そのコンポーネント カウントは、シーケンス内の各複合オブジェクトのコンポーネント カウントに、シーケンス内の各非複合オブジェクトにつき 1 を足した合計になります。たとえば、作成オペレーションを実行する際に、最初の 2 個のコンポーネントが非複合オブジェクトで、3 番目のコンポーネントがコンポーネント カウントが 12 の複合オブジェクトの場合、この作成オペレーションのコンポーネント カウントは 14 になります。コンポーネント カウントが 1,024 を超える作成オペレーションは許可されません。コンポーネント カウントが 1,024 の複合オブジェクトにオブジェクトを追加するには、まずその複合オブジェクトをダウンロードして新しいオブジェクトにコピーしてから、そのオブジェクトをアップロードする必要があります。例については、gsutil を使用したオブジェクト作成の実行を参照してください。

複合オブジェクトの整合性チェック

Cloud Storage は、アップロード時に各複合コンポーネントの整合性チェックを実行し、ダウンロード時に発信者が結果の複合オブジェクトの整合性チェックを実行できるようにするために、CRC32C を使用します。CRC32C は、そのコンポーネントの CRC32C 値から効率的に計算することができる誤り検出符号です。アプリケーションで以下のように CRC32C を使用する必要があります。

  • コンポーネント オブジェクトをアップロードする場合、下記にリストされているような CRC32C ライブラリを使用して各オブジェクトの CRC32C を計算し、その値をリクエストに含める必要があります。
  • 作成オペレーションでは、リクエストに CRC32C を含める必要があります。Cloud Storage は、複合オブジェクトの CRC32C に応答します。Cloud Storage は、複合オブジェクトの MD5 値を計算しません。
  • ダウンロード時には、ダウンロードしたオブジェクトの CRC32C を計算し、その値をレスポンスに含まれた値と比較する必要があります。
  • コンポーネント オブジェクトのアップロード時と作成時との間に、アプリケーションでオブジェクトが変更される可能性がある場合は、競合状態を防止するために、ソース オブジェクトに世代固有の名前を付ける必要があります。

CRC32C 値を計算するためのライブラリには、C++ の Boost、Java の GoogleCloudPlatform crc32c、Python の crcmod、Ruby の digest-crc があります。また、CRC32C は、現在の Intel CPU のハードウェアでもサポートされています。

以前は、Cloud Storage は MD5 を使用して ETag 値を構築していました。これは、複合オブジェクトの場合は当てはまりません。クライアント コードでは、複合オブジェクトの ETag 値は基になるオブジェクトが HTTP / 1.1 の IETF 仕様に応じて変化するたびに変化するということ以外、ETag 値について仮定することはできません。

並列アップロード

オブジェクト作成を使用して、オブジェクトを並行してアップロードすることができます。単純に、データを複数のチャンクに分割して、各チャンクを一意のオブジェクトに並行してアップロードし、最終的なオブジェクトを作成してから、一時オブジェクトをすべて削除します。

アップロード リクエストと作成リクエストの間に、コンポーネント オブジェクトが変更されないようにするためには、ユーザーは、各コンポーネントに予想される世代番号を付与する必要があります。オブジェクトの世代の詳細については、世代と前提条件をご覧ください。

制限付きの追加と編集

作成オペレーションを使用して、オブジェクトの制限付きの追加と編集を実行することもできます。

追加を実行するには、データを新しい一時オブジェクトにアップロードし、この新しいデータとともに追加したいオブジェクトを作成し、一時オブジェクトを削除します。この機能は、上記のコンポーネント カウント プロパティによって制限されています。

また、作成オペレーションを使用して、オブジェクト編集の基本的な機能をサポートすることもできます。たとえば、シーケンス {Y1, Y2, Y3} からオブジェクト X を作成し、Y2 のコンテンツを変更して、同じコンポーネントで X を再作成することができます。これを行うには、これらのコンポーネントとコンポジットに対して課金されるようにするために、Y1、Y2、Y3 を削除せずに残しておく必要がありますので注意してください。

gsutil を使用したオブジェクト作成の実行

gsutil は、compose コマンドとともにオブジェクトの作成をサポートします。詳細については、次のコマンドを実行して組み込みのドキュメントをご覧ください。

gsutil help compose

たとえば、3 つのオブジェクト(component-obj-1component-obj-2component-obj-3)から 1 つのオブジェクト(composite-object)を作成するには、次のコマンドを使用することができます。

gsutil compose gs://example-bucket/component-obj-1 gs://example-bucket/component-obj-2 gs://example-bucket/component-obj-3 gs://example-bucket/composite-object

あるいは、作成中のオブジェクトが component-obj- という接頭辞を持つ唯一のオブジェクトである場合は、次の例で示すように、compose コマンドでワイルドカードを使用することができます。

gsutil compose gs://example-bucket/component-obj-* gs://example-bucket/composite-object

作成オペレーションの後、次のコマンドを使用してコンポーネント カウントを確認することができます。

gsutil stat gs://example-bucket/composite-object

この例では、コンポーネント カウントは 3 です。しかし、コンポーネント カウントが 1,024 に達しており、さらにオブジェクトを作成したい場合は、この複合オブジェクトをダウンロードして新しいオブジェクトにコピーしてから、そのオブジェクトをアップロードする必要があります。この処理は、cp コマンドのデイジー チェーン(-D)オプションを使用して実行することができます。-D オプションを省略した場合、gsutil はクラウドの複合オブジェクトをコピーするため、そのコンポーネント カウントは変更されず、オブジェクトをさらに追加することはできなくなります。

次の 2 つのコマンドは、composite-objectnew-object にコピーした後、new-object を元の名前を使用するように戻します。どちらのコマンドも、gsutil がオブジェクトの ACL を保持できるようにするために、cp コマンドの -p オプションを使用します。

gsutil cp -D -p gs://example-bucket/composite-object gs://example-bucket/new-object
gsutil mv -p gs://example-bucket/new-object gs://example-bucket/composite-object

XML API を使用したオブジェクト作成の実行

次の例に示すように、XML API では、compose クエリ パラメータを指定して PUT Object リクエストを発行し、コンポーネント オブジェクトを名前順にリストした XML 本文を含めることによってオブジェクトを作成します。

PUT /example-bucket/composite-object?compose HTTP/1.1
Host: storage.googleapis.com
Content-Length: 153
Authorization: Bearer ya29.AHES6ZRVmB7fkLtd1XTmq6mo0S1wqZZi3-Lh_s-6Uw7p8vtgSwg

<ComposeRequest>
  <Component>
    <Name>component-obj-1</Name>
  </Component>
  <Component>
    <Name>component-obj-2</Name>
    <Generation>1361471441094000</Generation>
  </Component>
  <Component>
    <Name>component-obj-3</Name>
    <IfGenerationMatch>1361471441094000</IfGenerationMatch>
  </Component>
</ComposeRequest>

前述のとおり、ソース オブジェクトと宛先オブジェクトはすべて同じバケットの下になければならないため、コンポーネント オブジェクトのバケットは指定されていません。

また、上記のリクエストの例では component-obj-2 の世代番号が指定されていますが、これは、この世代が現在の世代でなくなっても、このリクエストによってオブジェクトの世代 1361471441094000 が作成されるようにするためです。

3 番目のコンポーネントでは、IfGenerationMatch リクエストの要素を使用した条件付き生成が指定されています。これにより、指定された世代番号がコンポーネントの現在の世代を表していない場合、リクエストは失敗します。

上記のオブジェクト作成リクエストに対するレスポンスは次のようになります。

Server: HTTP Upload Server Built on Mar 6 2013 16:24:27 (1362615867)
ETag: "-CKicn4fknbUCEAE="
x-goog-generation: 1362768951202000
x-goog-metageneration: 1
x-goog-hash: crc32c=fbWtZQ==
x-goog-component-count: 3
Vary: Origin
Date: Fri, 08 Mar 2013 18:55:51 GMT
Pragma: no-cache
Expires: Mon, 01 Jan 1990 00:00:00 GMT
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 0
Content-Type: text/html; charset=UTF-8

x-goog-hash ヘッダーは、オブジェクトの CRC32C 値を報告します。この値は、オブジェクトが作成された CRC32C 値から CRC32C 値を構築することによって検証することができます。

新しい複合オブジェクトのコンポーネント カウントは、x-goog-component-count レスポンス ヘッダーの値になります。

JSON API を使用したオブジェクト作成の実行

以下の例に示すように、JSON API では、コンポーネント オブジェクトを名前順にリストした JSON 本文を含む compose リクエストを発行することによって、オブジェクトを作成します。

POST /storage/v1/b/example-bucket/o/composite-object/compose
Host: www.googleapis.com
Content-Length: 216
Content-Type: application/json
Authorization: Bearer ya29.AHES6ZRVmB7fkLtd1XTmq6mo0S1wqZZi3-Lh_s-6Uw7p8vtgSwg

{
  "sourceObjects": [
    {
      "name": "component-obj-1"
    },
    { "name": "component-obj-2"
    },
    { "name": "component-obj-3"
    }
  ],
  "destination": {
   "contentType": "application/octet-stream"
 }
}

上記のオブジェクト作成リクエストへのレスポンスには、コンポーネント カウントを含むオブジェクト リソースが含まれます。

{
 "kind": "storage#object",
 "id": "bucket/composite-object/1388778813188000",
 "selfLink": "https://www.googleapis.com/storage/v1/b/example-bucket/o/composite-object",
 "name": "composite-object",
 "bucket": "bucket",
 "generation": "1388778813188000",
 "metageneration": "1",
 "contentType": "application/octet-stream",
 "updated": "2014-01-03T19:53:33.188Z",
 "size": "524052",
 "mediaLink": "https://www.googleapis.com/download/storage/v1/b/example-bucket/o/composite-object?generation=1388778813188000&alt=media",
 "crc32c": "V9kcXg==",
 "componentCount": 3,
 "etag": "CKDP057k4rsCEAE="
}

フィードバックを送信...