Go を使用して非同期スケジュールで BLOB をコピーする

この記事では、Go 用の Azure Storage クライアント モジュールを使用し、非同期スケジュールで BLOB をコピーする方法を説明します。 BLOB は、同じストレージ アカウント内のソースからでも、別のストレージ アカウント内のソースからでも、特定の URL に対する HTTP GET 要求を介して取得されたアクセス可能なオブジェクトからでもコピーできます。 保留中のコピー操作を中止することもできます。

この記事で取り上げるメソッドは、Copy Blob REST API 操作を使用するものであり、非同期スケジュールでコピーを実行する場合に使用できます。 データの移動先がストレージ アカウントでありソース オブジェクトの URL があるような大半のコピー シナリオについては、Go を使用してソース オブジェクト URL から BLOB をコピーする場合についての情報を参照してください。

前提条件

環境を設定する

既存のプロジェクトがない場合、Go 用 Azure Blob Storage クライアント モジュールを操作するためのプロジェクトを設定する方法についてこのセクションで説明します。 この手順には、モジュールのインストール、import パスの追加、認可されているクライアント オブジェクトの作成が含まれます。 詳細については、Azure Blob Storage および Go の概要に関するページを参照してください。

モジュールのインストール

次のコマンドを使用して、azblob モジュールをインストールします。

go get github.com/Azure/azure-sdk-for-go/sdk/storage/azblob

Microsoft Entra ID で認証するには (推奨)、次のコマンドを使用して azidentity モジュールをインストールします。

go get github.com/Azure/azure-sdk-for-go/sdk/azidentity

インポート パスの追加

コード ファイルに、次のインポートを追加します。

import (
    "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
	"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob"
)

これらのインポート パスは、作業を始めるために最低限必要なものを表します。 この記事の一部のコード例では、追加のインポート パスが必要な場合があります。 具体的な詳細と使用例についてはコード サンプルに関するページを参照してください。

クライアント オブジェクトの作成

アプリを Blob Storage に接続するには、azblob.NewClient を使用してクライアント オブジェクトを作成します。 次の例では、認可のために DefaultAzureCredential を使用してクライアント オブジェクトを作成する方法を示します。

func getServiceClientTokenCredential(accountURL string) *azblob.Client {
    // Create a new service client with token credential
    credential, err := azidentity.NewDefaultAzureCredential(nil)
    handleError(err)

    client, err := azblob.NewClient(accountURL, credential, nil)
    handleError(err)

    return client
}

承認

認可メカニズムには、コピー操作を実行または保留中のコピーを中止するために必要な権限が必要です。 Microsoft Entra ID を使用した認可 (推奨) には、Azure RBAC 組み込みロールのストレージ BLOB データ共同作成者以上が必要です。 詳細については、Copy Blob または Abort Copy Blob の承認ガイダンスを参照してください。

非同期スケジュールを設定した BLOB のコピーについて

Copy Blob 操作は、非同期的に完了でき、ベスト エフォートで実行されます。つまり、即座に開始することも、指定の時間枠内に完了することも保証されていません。 コピー操作はバックグラウンドでスケジュールされ、サーバーに使用可能なリソースがある場合に実行されます。 コピーが同じストレージ アカウント内で行われる場合、操作は同期的に完了できます。

Copy Blob 操作では、次のいずれかのアクションを実行できます。

  • コピー元 BLOB を別の名前でコピー先 BLOB にコピーします。 コピー先 BLOB は、同じ BLOB の種類 (ブロック、アペンド、またはページ) の既存の BLOB でも、コピー操作によって作成される新しい BLOB でもかまいません。
  • ソース BLOB を同じ名前でコピー先 BLOB にコピーして、コピー先 BLOB を置き換えます。 この種のコピー操作では、コミットされていないブロックはすべて削除され、コピー先 BLOB のメタデータが上書きされます。
  • Azure File Service 内のコピー元ファイルをコピー先 BLOB にコピーします。 コピー先 BLOB は、既存のブロック BLOB でも、コピー操作によって作成される新しいブロック BLOB でもかまいません。 ファイルからページ BLOB またはアペンド BLOB へのコピーはサポートされていません。
  • スナップショットをベース BLOB にコピーします。 スナップショットをベース BLOB に昇格することにより、BLOB を以前のバージョンに復元できます。
  • スナップショットを別の名前でコピー先 BLOB にコピーします。 結果として得られるコピー先 BLOB は書き込み可能な BLOB であり、スナップショットではありません。

コピー操作のソース BLOB の種類は、ブロック BLOB、追加 BLOB、ページ BLOB、BLOB スナップショット、BLOB バージョンのいずれかです。 コピー操作では、常にソース BLOB またはファイル全体がコピーされます。 バイト範囲またはブロックのセットのコピーはサポートされていません。

コピー先 BLOB が既に存在する場合は、ソース BLOB と同じ種類の BLOB である必要があり、また既存のコピー先 BLOB は上書きされます。 コピー操作の進行中はコピー先 BLOB を変更できません。また、コピー先 BLOB には未処理のコピー操作が 1 つだけ存在することができます。

プロパティ、インデックス タグ、メタデータ、課金に関する情報など、Copy Blob 操作の詳細については、BLOB リマークのコピーに関するページを参照してください。

非同期スケジュールを設定して BLOB をコピーする

このセクションでは、Go 用の Azure Storage クライアント モジュールによって提供されている、非同期スケジュールでコピー操作を実行する各種メソッドの概要を説明します。

次のメソッドは、Copy Blob REST API 操作をラップし、ソース BLOB からのデータの非同期コピーを開始します。

Azure 内のソースから BLOB をコピーする

同じストレージ アカウント内の BLOB をコピーする場合、操作は同期的に完了できます。 ソース BLOB に対するアクセスの承認には、Microsoft Entra ID (推奨)、Shared Access Signature (SAS)、またはアカウント キーを使用できます。 代替となる同期コピー操作については、Go を使用してソース オブジェクト URL から BLOB をコピーする場合についての情報を参照してください。

コピー ソースが別のストレージ アカウント内の BLOB である場合、操作は非同期的に完了できます。 ソース BLOB は、パブリックであるか、SAS トークンを介して認可されている必要があります。 SAS トークンには Read ('r') アクセス許可を含める必要があります。 SAS トークンの詳細については、「Shared Access Signatures によるアクセスの委任」を参照してください。

次の例は、非同期スケジュールを使用して別のストレージ アカウントからソース BLOB をコピーするシナリオを示しています。 この例では、追加されたユーザー委任 SAS トークンを使用してソース BLOB URL を作成します。 この例では、開発者が独自に SAS を提供する場合を想定しています。 この例では、コピー操作中にソース BLOB をリースして、別のクライアントから BLOB が変更されないようにする方法も示します。 Copy Blob 操作では、コピー操作の開始時にソース BLOB の ETag 値が保存されます。 コピー操作が完了する前に ETag 値が変更されると、操作は失敗します。 また、StartCopyFromURLOptions 構造体を使用し、宛先 BLOB のアクセス層を Cool に設定します。

func copyFromSourceAsync(srcBlob *blockblob.Client, destBlob *blockblob.Client) {
    // Lease the source blob during copy to prevent other clients from modifying it
    blobLeaseClient, err := lease.NewBlobClient(srcBlob, nil)
    handleError(err)

    _, err = blobLeaseClient.AcquireLease(context.TODO(), int32(60), nil)
    handleError(err)

    // Retrieve the SAS token for the source blob and append it to the URL
    sas := "<sas-token>"
    url := srcBlob.URL() + "?" + sas

    // Set copy options
    copyOptions := blob.StartCopyFromURLOptions{
        Tier: to.Ptr(blob.AccessTierCool),
    }

    // Copy the blob from the source URL to the destination blob
    startCopy, err := destBlob.StartCopyFromURL(context.TODO(), url, &copyOptions)
    handleError(err)

    // If startCopy.CopyStatus returns a status of "pending", the operation has started asynchronously
    // You can optionally add logic to poll the copy status and wait for the operation to complete
    // Example:
    copyStatus := *startCopy.CopyStatus
    for copyStatus == blob.CopyStatusTypePending {
        time.Sleep(time.Second * 2)

        properties, err := destBlob.GetProperties(context.TODO(), nil)
        handleError(err)

        copyStatus = *properties.CopyStatus
    }

    // Release the lease on the source blob
    _, err = blobLeaseClient.ReleaseLease(context.TODO(), nil)
    handleError(err)
}

使用例を以下に示します。

// TODO: replace <storage-account-name> placeholders with actual storage account names
srcURL := "https://<src-storage-account-name>.blob.core.windows.net/"
destURL := "https://<dest-storage-account-name>.blob.core.windows.net/"

credential, err := azidentity.NewDefaultAzureCredential(nil)
handleError(err)

srcClient, err := azblob.NewClient(srcURL, credential, nil)
handleError(err)
destClient, err := azblob.NewClient(destURL, credential, nil)
handleError(err)

srcBlob := srcClient.ServiceClient().NewContainerClient("source-container").NewBlockBlobClient("source-blob")
destBlob := destClient.ServiceClient().NewContainerClient("destination-container").NewBlockBlobClient("destination-blob-1")

copyFromSourceAsync(srcBlob, destBlob)

Note

ユーザー委任 SAS トークンでは、アカウント キーではなく Microsoft Entra の資格情報で署名されているため、セキュリティが強化されます。 ユーザー委任 SAS トークンを作成するには、Microsoft Entra セキュリティ プリンシパルに適切なアクセス許可が必要です。 認可要件については、「ユーザー委任キーを取得する」を参照してください。

Azure 外部のソースから BLOB をコピーする

Azure 外部にあるアクセス可能なオブジェクトを含め、特定の URL に対する HTTP GET 要求を介して取得できる任意のソース オブジェクトにコピー操作を実行できます。 以下の例は、アクセス可能なソース オブジェクト URL から BLOB をコピーするシナリオを示しています。

func copyFromExternalSourceAsync(srcURL string, destBlob *blockblob.Client) {
    // Set copy options
    copyOptions := blob.StartCopyFromURLOptions{
        Tier: to.Ptr(blob.AccessTierCool),
    }

    // Copy the blob from the source URL to the destination blob
    startCopy, err := destBlob.StartCopyFromURL(context.TODO(), srcURL, &copyOptions)
    handleError(err)

    // If startCopy.CopyStatus returns a status of "pending", the operation has started asynchronously
    // You can optionally add logic to poll the copy status and wait for the operation to complete
    // Example:
    copyStatus := *startCopy.CopyStatus
    for copyStatus == blob.CopyStatusTypePending {
        time.Sleep(time.Second * 2)

        properties, err := destBlob.GetProperties(context.TODO(), nil)
        handleError(err)

        copyStatus = *properties.CopyStatus
    }
}

使用例を以下に示します。

externalURL := "<source-url>"

destBlob = destClient.ServiceClient().NewContainerClient("destination-container").NewBlockBlobClient("destination-blob-2")

copyFromExternalSourceAsync(externalURL, destBlob)

コピー操作の状態を確認する

非同期 Copy Blob 操作の状態をチェックするには、GetProperties メソッドをポーリングし、コピーの状態を確認します。

次のコード例は、コピー操作の状態を確認する方法を示しています。

func checkCopyStatus(destBlob *blockblob.Client) {
    // Retrieve the properties from the destination blob
    properties, err := destBlob.GetProperties(context.TODO(), nil)
    handleError(err)

    copyID := *properties.CopyID
    copyStatus := *properties.CopyStatus

    fmt.Printf("Copy operation %s is %s\n", copyID, copyStatus)
}

コピー操作を中止する

保留中の Copy Blob 操作を中止すると、コピー先 BLOB の長さは 0 になります。 ただし、コピー先 BLOB のメタデータは、ソース BLOB からコピーされた値、またはコピー操作中に明示的に設定された値に変わります。 コピー前のメタデータを元のまま維持するには、いずれかのコピー方法を呼び出す前に、コピー先 BLOB のスナップショットを作成します。

保留中のコピー操作を中止するには、次の操作を呼び出します。

このメソッドは、保留中の Copy Blob 操作を取り消す Abort Copy Blob REST API 操作をラップします。 次のコード例は、保留中の Copy Blob 操作を中止する方法を示しています。

func abortCopy(destBlob *blockblob.Client) {
    // Retrieve the copy ID from the destination blob
    properties, err := destBlob.GetProperties(context.TODO(), nil)
    handleError(err)

    copyID := *properties.CopyID
    copyStatus := *properties.CopyStatus

    // Abort the copy operation if it's still pending
    if copyStatus == blob.CopyStatusTypePending {
        _, err := destBlob.AbortCopyFromURL(context.TODO(), copyID, nil)
        handleError(err)

        fmt.Printf("Copy operation %s aborted\n", copyID)
    }
}

リソース

Go 用の Azure Blob Storage クライアント モジュールを使用し、非同期スケジュールで BLOB をコピーする方法の詳細については、以下のリソースを参照してください。

コード サンプル

REST API の操作

Azure SDK for Go には Azure REST API に基づき構築されたライブラリが含まれるため、使い慣れた Go パラダイムを通じて REST API 操作を実施できます。 この記事で取り上げるメソッドでは、以下の REST API 操作を使用します。

クライアント モジュール リソース

  • この記事は、Go の Blob Storage 開発者ガイドの一部です。 詳細については、Go アプリの構築に関するセクションにある、すべての開発者ガイド記事の一覧を参照してください。