计算要计费的 Blob 容器总大小

此脚本出于估算计费成本的目的,计算 Azure Blob 存储中的容器大小。 此脚本计算容器中各 blob 的大小总和。

本示例需要 Azure PowerShell 模块 5.1.1 或更高版本。 运行 Get-Module -ListAvailable AzureRM 即可查找版本。 如果需要进行安装或升级,请参阅安装 Azure PowerShell 模块

运行 Login-AzureRmAccount -EnvironmentName AzureChinaCloud,创建与 Azure 的连接。

Note

如果没有 Azure 订阅,可在开始前创建一个试用帐户

Note

此 PowerShell 脚本出于计费目的计算容器大小。 如果要出于其他目的计算容器大小,请参阅计算 Blob 存储容器的总大小,获取进行估算的更简单的脚本。

确定 Blob 容器的大小

Blob 容器的总大小包括容器自身大小,以及容器内所有 blob 的大小。

下述部分介绍 Blob 容器和 blob 的存储容量计算方法。 在下一部分中,Len(X) 表示字符串中的字符数。

Blob 容器

下述计算介绍如何估算每个 Blob 容器使用的存储量:

48 bytes + Len(ContainerName) * 2 bytes + For-Each Metadata[3 bytes + Len(MetadataName) + Len(Value)] + For-Each Signed Identifier[512 bytes]

以下是明细信息:

  • 每个容器 48 字节的开销,包括上次修改时间、权限、公共设置,以及其他系统元数据。

  • 容器名称以 Unicode 形式存储,因此字节数按字符数乘以 2 计算。

  • 对于存储的每个 Blob 容器元数据块,我们将存储名称 (ASCII) 长度,再加上字符串值的长度。

  • 每个签名标识符(512 字节)包括签名标识符名称、开始时间、到期时间和权限。

Blob

下述计算显示如何估算每个 blob 使用的存储量。

  • 块 blob(基本 blob 或快照):

    124 bytes + Len(BlobName) * 2 bytes + For-Each Metadata[3 bytes + Len(MetadataName) + Len(Value)] + 8 bytes + number of committed and uncommitted blocks * Block ID Size in bytes + SizeInBytes(data in unique committed data blocks stored) + SizeInBytes(data in uncommitted data blocks)

  • 页 blob(基本 blob 或快照):

    124 bytes + Len(BlobName) * 2 bytes + For-Each Metadata[3 bytes + Len(MetadataName) + Len(Value)] + number of nonconsecutive page ranges with data * 12 bytes + SizeInBytes(data in unique pages stored)

以下是明细信息:

  • Blob 的开销为 124 字节,其中包括:

    • 上次修改时间
    • 大小
    • Cache-Control
    • Content-Type
    • Content-Language
    • Content-Encoding
    • Content-MD5
    • 权限
    • 快照信息
    • 租约
    • 某些系统元数据
  • Blob 名称以 Unicode 形式存储,因此字节数按字符数乘以 2 计算。

  • 对于每个存储的元数据块,添加名称长度(以 ASCII 码存储),再加上字符串值的长度。

  • 对于块 blob:

    • 块列表为 8 字节。
    • 块数乘以块 ID 大小(按字节计)。
    • 所有已提交和未提交块中数据的大小。

      Note

      使用快照时,大小仅包括此基本或快照 blob 的唯一数据。 如果未提交块在一周后未被使用,则回收到垃圾桶。 之后不计入账单。

  • 对于页 blob:

    • 字节数按具有数据的不连续页面范围数乘以 12 计算。 这是在调用 GetPageRanges API 时看到的唯一页面范围数。

    • 所有存储页面中的数据大小(按字节计)。

      Note

      使用快照时,大小仅包含要计数的基本 blob 或快照 blob 的唯一页面。

示例脚本


# this script will show how to get the total size of the blobs in a container
# before running this, you need to create a storage account, create a container,
#    and upload some blobs into the container
# note: this retrieves all of the blobs in the container in one command.
#       connect Azure with Login-AzureRmAccount before you run the script.
# command line usage: script.ps1 -ResourceGroup {YourResourceGroupName} -StorageAccountName {YourAccountName} -ContainerName {YourContainerName}
#

param(
    [Parameter(Mandatory=$true)]
    [string]$ResourceGroup,

    [Parameter(Mandatory=$true)]
    [string]$StorageAccountName,

    [Parameter(Mandatory=$true)]
    [string]$ContainerName
)

#Set-StrictMode will cause Get-AzureStorageBlob returns result in different data types when there is only one blob
#Set-StrictMode -Version 2

$VerbosePreference = "Continue"

if((Get-Module -ListAvailable Azure) -eq $null)
{
    throw "Azure Powershell not found! Please install from http://www.windowsazure.com/en-us/downloads/#cmd-line-tools"
}

# function Get-BlobBytes

function Get-BlobBytes
{
    param(
        [Parameter(Mandatory=$true)]
        $Blob)

    # Base + blobname
    $blobSizeInBytes = 124 + $Blob.Name.Length * 2

    # Get size of metadata
    $metadataEnumerator=$Blob.ICloudBlob.Metadata.GetEnumerator()
    while($metadataEnumerator.MoveNext())
    {
        $blobSizeInBytes += 3 + $metadataEnumerator.Current.Key.Length + $metadataEnumerator.Current.Value.Length
    }

    if($Blob.BlobType -eq [Microsoft.WindowsAzure.Storage.Blob.BlobType]::BlockBlob)
    {
        $blobSizeInBytes += 8
        # Default is Microsoft.WindowsAzure.Storage.Blob.BlockListingFilter.Committed. Need All
        $Blob.ICloudBlob.DownloadBlockList([Microsoft.WindowsAzure.Storage.Blob.BlockListingFilter]::All) |
            ForEach-Object { $blobSizeInBytes += $_.Length + $_.Name.Length }
    }
    else
    {
        $Blob.ICloudBlob.GetPageRanges() |
            ForEach-Object { $blobSizeInBytes += 12 + $_.EndOffset - $_.StartOffset }
    }

    return $blobSizeInBytes
}

# function Get-ContainerBytes

function Get-ContainerBytes
{
    param(
        [Parameter(Mandatory=$true)]
        [Microsoft.WindowsAzure.Storage.Blob.CloudBlobContainer]$Container)

    # Base + name of container
    $containerSizeInBytes = 48 + $Container.Name.Length*2

    # Get size of metadata
    $metadataEnumerator = $Container.Metadata.GetEnumerator()
    while($metadataEnumerator.MoveNext())
    {
        $containerSizeInBytes += 3 + $metadataEnumerator.Current.Key.Length + $metadataEnumerator.Current.Value.Length
    }

    # Get size for SharedAccessPolicies
    $containerSizeInBytes += $Container.GetPermissions().SharedAccessPolicies.Count * 512

    # Calculate size of all blobs.
    $blobCount = 0
    $Token = $Null
    $MaxReturn = 5000

    do {
        $Blobs = Get-AzureStorageBlob -Context $storageContext -Container $Container.Name -MaxCount $MaxReturn -ContinuationToken $Token
        if($Blobs -eq $Null) { break }

        #Set-StrictMode will cause Get-AzureStorageBlob returns result in different data types when there is only one blob
        if($Blobs.GetType().Name -eq "AzureStorageBlob")
        {
            $Token = $Null
        }
        else
        {
            $Token = $Blobs[$Blobs.Count - 1].ContinuationToken;
        }

        $Blobs | ForEach-Object {
                $blobSize = Get-BlobBytes $_
                $containerSizeInBytes += $blobSize
                $blobCount++

                if(($blobCount % 1000) -eq 0)
                {
                    Write-Verbose("Counting {0} Sizing {1} " -f $blobCount, $containerSizeInBytes)
                }
            }
    }
    While ($Token -ne $Null)

    return @{ "containerSize" = $containerSizeInBytes; "blobCount" = $blobCount }
}

#Login-AzureRmAccount

$storageAccount = Get-AzureRmStorageAccount -ResourceGroupName $ResourceGroup -Name $StorageAccountName -ErrorAction SilentlyContinue
if($storageAccount -eq $null)
{
    throw "The storage account specified does not exist in this subscription."
}

$storageContext = $storageAccount.Context

$containers = New-Object System.Collections.ArrayList
if($ContainerName.Length -ne 0)
{
    $container = Get-AzureStorageContainer -Context $storageContext -Name $ContainerName -ErrorAction SilentlyContinue |
        ForEach-Object { $containers.Add($_) } | Out-Null
}
else
{
    Get-AzureStorageContainer -Context $storageContext | ForEach-Object { $containers.Add($_) } | Out-Null
}

$sizeInBytes = 0

if($containers.Count -gt 0)
{
    $containers | ForEach-Object {
        Write-Output("Calculating container {0} ..." -f $_.CloudBlobContainer.Name)
        $result = Get-ContainerBytes $_.CloudBlobContainer
        $sizeInBytes += $result.containerSize

        Write-Output("Container '{0}' with {1} blobs has a sizeof {2:F2} MB." -f $_.CloudBlobContainer.Name,$result.blobCount,($result.containerSize/1MB))
    }
}
else
{
    Write-Warning "No containers found to process in storage account '$StorageAccountName'."
}

后续步骤