Dav*_*yan 21 azure azure-storage azure-storage-blobs
我想将一个非常大的存储容器从一个Azure存储帐户复制到另一个(也恰好在另一个订阅中).
我想就以下选项发表意见:
使用CloudBlob的DownloadToStream()和UploadFromStream()编写一个可以连接到两个存储帐户并一次复制一个blob的工具.这似乎是最糟糕的选择,因为它会在传输数据时产生成本,而且速度很慢,因为数据必须归结为运行该工具的计算机,然后重新上传回Azure.
写一个工人角色来做同样的事情 - 理论上这应该更快,不会产生任何代价.但是,这是更多的工作.
将工具上传到正在运行的实例,绕过工作者角色部署,并在实例被回收/重置之前祈祷工具完成.
使用现有工具 - 没有发现任何有趣的东西.
关于这种方法的任何建议?
更新:我刚刚发现,2012年7月7日或之后创建的所有存储帐户最终都引入了此功能(仅适用于REST API):
http://msdn.microsoft.com/en-us/library/windowsazure/dd894037.aspx
Dre*_*ker 11
您还可以使用属于Azure SDK的AzCopy.
只需单击Windows Azure SDK的下载按钮,然后WindowsAzureStorageTools.msi从列表中选择下载AzCopy.
安装完成后,你会在AzCopy.exe这里找到:%PROGRAMFILES(X86)%\Microsoft SDKs\Windows Azure\AzCopy
您可以在此博客文章中获得有关使用AzCopy的更多信息:AzCopy - 使用跨帐户复制Blob
同样,您可以远程桌面到实例并使用此实用程序进行传输.
更新:
您也可以使用Microsoft Azure Storage Explorer在存储帐户之间复制blob数据.参考链接
由于没有直接的方法将数据从一个存储帐户迁移到另一个存储帐户,因此您需要执行类似于您的想法的操作.如果它位于同一数据中心内,则选项#2是最好的选择,并且将是最快的(特别是如果您使用XL实例,为您提供更多的网络带宽).
就复杂性而言,在工作者角色中创建此代码并不比使用本地应用程序更难.只需从worker角色的Run()方法运行此代码即可.
为了使事情更加健壮,您可以在容器中列出blob,然后将特定的文件移动请求消息放入Azure队列(并通过为每个消息放置多个对象名进行优化).然后使用辅助角色线程从队列中读取并处理对象.即使您的角色被回收,最坏的情况下您也会重新处理一条消息.为了提高性能,您可以扩展到多个辅助角色实例.传输完成后,您只需拆除部署.
更新 - 2012年6月12日,Windows Azure存储API已更新,现在允许跨帐户blob复制.有关所有详细信息,请参阅此博客文章.
以下是一些利用.NET SDK for Azure的代码,可从http://www.windowsazure.com/en-us/develop/net获取
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.WindowsAzure.StorageClient;
using System.IO;
using System.Net;
namespace benjguinAzureStorageTool
{
class Program
{
private static Context context = new Context();
static void Main(string[] args)
{
try
{
string usage = string.Format("Possible Usages:\n"
+ "benjguinAzureStorageTool CopyContainer account1SourceContainer account2SourceContainer account1Name account1Key account2Name account2Key\n"
);
if (args.Length < 1)
throw new ApplicationException(usage);
int p = 1;
switch (args[0])
{
case "CopyContainer":
if (args.Length != 7) throw new ApplicationException(usage);
context.Storage1Container = args[p++];
context.Storage2Container = args[p++];
context.Storage1Name = args[p++];
context.Storage1Key = args[p++];
context.Storage2Name = args[p++];
context.Storage2Key = args[p++];
CopyContainer();
break;
default:
throw new ApplicationException(usage);
}
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("OK");
Console.ResetColor();
}
catch (Exception ex)
{
Console.WriteLine();
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("Exception: {0}", ex.Message);
Console.ResetColor();
Console.WriteLine("Details: {0}", ex);
}
}
private static void CopyContainer()
{
CloudBlobContainer container1Reference = context.CloudBlobClient1.GetContainerReference(context.Storage1Container);
CloudBlobContainer container2Reference = context.CloudBlobClient2.GetContainerReference(context.Storage2Container);
if (container2Reference.CreateIfNotExist())
{
Console.WriteLine("Created destination container {0}. Permissions will also be copied.", context.Storage2Container);
container2Reference.SetPermissions(container1Reference.GetPermissions());
}
else
{
Console.WriteLine("destination container {0} already exists. Permissions won't be changed.", context.Storage2Container);
}
foreach (var b in container1Reference.ListBlobs(
new BlobRequestOptions(context.DefaultBlobRequestOptions)
{ UseFlatBlobListing = true, BlobListingDetails = BlobListingDetails.All }))
{
var sourceBlobReference = context.CloudBlobClient1.GetBlobReference(b.Uri.AbsoluteUri);
var targetBlobReference = container2Reference.GetBlobReference(sourceBlobReference.Name);
Console.WriteLine("Copying {0}\n to\n{1}",
sourceBlobReference.Uri.AbsoluteUri,
targetBlobReference.Uri.AbsoluteUri);
using (Stream targetStream = targetBlobReference.OpenWrite(context.DefaultBlobRequestOptions))
{
sourceBlobReference.DownloadToStream(targetStream, context.DefaultBlobRequestOptions);
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
25326 次 |
| 最近记录: |