5

Azure VM のサポートを利用するための大規模な移行の一環として、米国中北部から米国西部に移動する必要がある約 420 万の画像があります (知らない人のために説明すると、米国中北部はサポートされていません)。彼ら)。画像はすべて 1 つのコンテナー内にあり、約 119,000 のディレクトリに分割されています。

Copy Blob API から以下を使用しています。

public static void CopyBlobDirectory(
        CloudBlobDirectory srcDirectory,
        CloudBlobContainer destContainer)
{
    // get the SAS token to use for all blobs
    string blobToken = srcDirectory.Container.GetSharedAccessSignature(
        new SharedAccessBlobPolicy
        {
            Permissions = SharedAccessBlobPermissions.Read |
                            SharedAccessBlobPermissions.Write,
            SharedAccessExpiryTime = DateTime.UtcNow + TimeSpan.FromDays(14)
        });

    var srcBlobList = srcDirectory.ListBlobs(
        useFlatBlobListing: true,
        blobListingDetails: BlobListingDetails.None).ToList();

    foreach (var src in srcBlobList)
    {
        var srcBlob = src as ICloudBlob;

        // Create appropriate destination blob type to match the source blob
        ICloudBlob destBlob;
        if (srcBlob.Properties.BlobType == BlobType.BlockBlob)
            destBlob = destContainer.GetBlockBlobReference(srcBlob.Name);
        else
            destBlob = destContainer.GetPageBlobReference(srcBlob.Name);

        // copy using src blob as SAS
        destBlob.BeginStartCopyFromBlob(new Uri(srcBlob.Uri.AbsoluteUri + blobToken), null, null);          
    }
}

問題は、遅すぎることです。うわー遅すぎる。このすべてのものをコピーするためのコマンドを発行するのにかかる速度で、およそ 4 日かかります。ボトルネックが何であるかはよくわかりません (クライアント側の接続制限、Azure 側のレート制限、マルチスレッドなど)。

だから、私は私のオプションが何であるか疑問に思っています。作業をスピードアップする方法はありますか? それとも、完了までに 4 日かかる作業に行き詰まっているだけですか?

編集:すべてをコピーするために作業を配布する方法

//set up tracing
InitTracer();

//grab a set of photos to benchmark this
var photos = PhotoHelper.GetAllPhotos().Take(500).ToList();

//account to copy from
var from = new Microsoft.WindowsAzure.Storage.Auth.StorageCredentials(
    "oldAccount",
    "oldAccountKey");
var fromAcct = new CloudStorageAccount(from, true);
var fromClient = fromAcct.CreateCloudBlobClient();
var fromContainer = fromClient.GetContainerReference("userphotos");

//account to copy to
var to = new Microsoft.WindowsAzure.Storage.Auth.StorageCredentials(
    "newAccount",
    "newAccountKey");
var toAcct = new CloudStorageAccount(to, true);
var toClient = toAcct.CreateCloudBlobClient();

Trace.WriteLine("Starting Copy: " + DateTime.UtcNow.ToString());

//enumerate sub directories, then move them to blob storage
//note: it doesn't care how high I set the Parallelism to,
//console output indicates it won't run more than five or so at a time
var plo = new ParallelOptions { MaxDegreeOfParallelism = 10 };
Parallel.ForEach(photos, plo, (info) =>
{
    CloudBlobDirectory fromDir = fromContainer.GetDirectoryReference(info.BuildingId.ToString());

    var toContainer = toClient.GetContainerReference(info.Id.ToString());
    toContainer.CreateIfNotExists();

    Trace.WriteLine(info.BuildingId + ": Starting copy, " + info.Photos.Length + " photos...");

    BlobHelper.CopyBlobDirectory(fromDir, toContainer, info);
    //this monitors the container, so I can restart any failed
    //copies if something goes wrong
    BlobHelper.MonitorCopy(toContainer);
});

Trace.WriteLine("Done: " + DateTime.UtcNow.ToString());
4

2 に答える 2

2

非同期 BLOB コピー操作は、同じデータ センター内で非常に高速になります (最近、30 GB の vhd を別の BLOB に約 1 ~ 2 秒でコピーしました)。データセンター全体で、操作はキューに入れられ、SLA なしで予備の容量で実行されます (具体的には、この記事を参照してください)。

大まかに言えば、同じ 30 GB VHD をデータ センター全体にコピーしたところ、約 1 時間かかりました。

画像サイズはわかりませんが、平均画像サイズを 500K とすると、約 2,000 GB になります。私の例では、約 1 時間で 30GB のスループットが得られました。外挿すると、約 (2000/30) = 60 時間で 2000 GB のデータが推定されます。繰り返しますが、SLA はありません。あくまでも推測です。

他の誰かが Nagle のアルゴリズムを無効にすることを提案しました。これにより、400 万回のコピー コマンドをより迅速にプッシュし、より迅速にキューに入れることができます。コピー時間の影響はないと思います。

于 2013-03-03T02:54:47.440 に答える
1

BeginStartCopyFromBlobこれは少し長いショットですが、テーブルストレージで同様の問題が発生し、小さなリクエスト (そうあるべきだと思います) の実行が非常に遅くなりました。これは、ネットワーク トラフィックの 2 つの最適化であるNagle のアルゴリズム遅延 TCP ackの問題です。詳細については、 MSDNまたはこの男を参照してください。

結論 - Nagle のアルゴリズムをオフにします - Azure ストレージ操作を行う前に、次を呼び出します。

ServicePointManager.UseNagleAlgorithm = false;

またはブロブだけの場合:

var storageAccount = CloudStorageAccount.Parse(connectionString);
ServicePoint blobServicePoint = ServicePointManager.FindServicePoint(account.BlobEndpoint);
blobServicePoint.UseNagleAlgorithm = false;

それがあなたの問題であるかどうかを知ることは素晴らしいことです!

于 2013-03-03T00:35:09.787 に答える