使用 Go 基于异步计划复制 Blob
本文介绍了如何使用适用于 Go 的 Azure 存储客户端模块基于异步计划复制 Blob。 你可以从同一存储帐户中的源、不同存储帐户中的源或从通过 HTTP GET 请求在给定 URL 上检索的任何可访问对象复制 Blob。 还可以中止挂起的复制操作。
本文中介绍的方法将使用 Copy Blob REST API 操作,并且可以在想要基于异步计划执行复制时使用。 对于要将数据移动到存储帐户且具有源对象的 URL 的大多数复制方案,请参阅使用 Go 从源对象 URL 复制 Blob。
先决条件
设置你的环境
如果没有现有项目,请查看本部分,其中介绍了如何设置项目来使用适用于 Go 的 Azure Blob 存储客户端模块。 步骤包括模块安装、添加 import
路径以及创建授权的客户端对象。 有关详细信息,请参阅 Azure Blob 存储和 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 存储,请使用 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 数据参与者”或更高级别的角色。 若要了解详细信息,请参阅复制 Blob 或中止复制 Blob 的授权指导。
关于基于异步计划复制 Blob
Copy Blob
操作可以异步完成,并且是在尽最大努力的基础上执行的,这意味着该操作不一定会立即开始或在指定的时间范围内完成。 复制操作是在后台安排的,并在服务器具有可用资源时执行。 如果复制发生在同一存储帐户内,则操作可以同步完成。
Copy Blob
操作可以执行以下任何操作:
- 将源 Blob 复制到具有不同名称的目标 Blob。 目标 Blob 可以是相同类型(块、追加或页类型)的现有 Blob,也可以是复制操作创建的新 Blob。
- 将源 Blob 复制到具有相同名称的目标 Blob,从而替换目标 Blob。 此类复制操作会移除所有未提交的块,并覆盖目标 Blob 的元数据。
- 将 Azure 文件服务中的源文件复制到目标 Blob。 目标 Blob 可以是现有的块 Blob,也可以是复制操作创建的新块 Blob。 不支持从文件复制到页 Blob 或追加 Blob。
- 将快照复制到其基本 Blob 上。 通过将快照提升到基本 Blob 的位置,可还原早期版本的 Blob。
- 将快照复制到具有不同名称的目标 Blob。 生成的目标 Blob 是可写的 Blob,而不是快照。
复制操作的源 Blob 可以是以下类型之一:块 Blob、追加 Blob、页 Blob、Blob 快照或 Blob 版本。 该复制操作会始终复制整个源 Blob 或文件。 不支持复制字节范围或块集。
如果目标 Blob 已存在,则其类型必须与源 Blob 相同,并且系统将会覆盖现有目标 Blob。 进行复制操作时无法修改目标 Blob,并且目标 Blob 只能有一个未完成的复制操作。
若要详细了解 Copy Blob
操作,包括有关属性、索引标记、元数据和计费的信息,请参阅 Copy Blob 注解。
基于异步计划复制 Blob
本部分概述了适用于 Go 的 Azure 存储客户端模块提供的基于异步计划执行复制操作的方法。
以下方法将会封装 Copy Blob REST API 操作,并开始从源 Blob 异步复制数据:
在 Azure 中从源复制 blob
如果要在同一存储帐户中复制 Blob,操作可以同步完成。 可以通过 Microsoft Entra ID(推荐)、共享访问签名 (SAS) 或帐户密钥来授权对源 Blob 的访问。 有关引起改变的同步复制操作,请参阅使用 Go 从源对象 URL 复制 Blob。
如果复制源是其他存储帐户中的 Blob,则操作可以异步完成。 源 Blob 必须是公共的或通过 SAS 令牌获得授权。 SAS 令牌需要包含读取 ('r') 权限。 若要详细了解 SAS 令牌,请参阅使用共享访问签名委派权限。
以下示例演示使用异步计划从其他存储帐户复制源 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, ©Options)
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.chinacloudapi.cn/"
destURL := "https://<dest-storage-account-name>.blob.core.chinacloudapi.cn/"
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)
注意
用户委派 SAS 令牌提供了更高的安全性,因为它们是使用 Microsoft Entra 凭据而不是帐户密钥进行签名的。 若要创建用户委托 SAS 令牌,Microsoft Entra 安全主体需要适当的权限。 有关授权要求,请参阅获取用户委派密钥。
从 Azure 外部的源复制 Blob
你可以对可通过 HTTP GET 请求在给定 URL 上检索的任何源对象执行复制操作,包括 Azure 外部的可访问对象。 以下示例演示了从可访问的源对象 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, ©Options)
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 长度为零。 但是,目标 Blob 的元数据将包含从源 Blob 复制的新值,或者在复制操作过程中显式设置的新值。 若要在复制之前保留原始元数据,请在调用一个复制方法之前创建目标 Blob 的快照。
要中止挂起的复制操作,请调用以下某个操作:
此方法会包装中止复制 Blob REST API 操作,这会取消挂起的 Copy Blob
操作。 以下代码示例演示了如何中止挂起的 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 存储客户端模块来通过异步计划复制 blob,请参阅以下资源。
代码示例
REST API 操作
Azure SDK for Go 包含基于 Azure REST API 而生成的库,从而允许你通过熟悉的 Go 范式与 REST API 操作进行交互。 本文中介绍的方法使用以下 REST API 操作:
客户端模块资源
相关内容
- 本文是适用于 Go 的 Blob 存储开发人员指南的一部分。 若要了解详细信息,请参阅构建 Go 应用中的完整开发人员指南文章列表。