Ho da qualche parte nelle vicinanze di 4,2 milioni di immagini ho bisogno di spostarmi dagli Stati Uniti centro-nord a Stati Uniti occidentali, come parte di una migrazione di grandi dimensioni per sfruttare il supporto di Azure VM (per quelli che non lo sanno, gli Stati Uniti del Nord Centrale non li sostengono). Le immagini sono tutte in un unico contenitore, suddivise in circa 119.000 directory.Spostamento di milioni di elementi da un account di archiviazione a un altro
sto utilizzando la seguente dal API Copia Blob:
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);
}
}
Il problema è che è troppo lento. Waaaay troppo lento. Alla velocità che sta impiegando per emettere comandi per copiare tutte queste cose, ci vorranno da qualche parte nel vicinato di quattro giorni. Non sono veramente sicuro di quale sia il collo di bottiglia (lato del client del limite di connessione, limitazione della velocità su Azure, multithreading, ecc.).
Quindi, mi chiedo quali sono le mie opzioni. C'è un modo per velocizzare le cose o sono semplicemente bloccato con un lavoro che richiederà quattro giorni per essere completato?
Edit: Come sto distribuendo il lavoro per copiare tutto
//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());
Stai utilizzando molti thread per farlo? Il più delle volte è nella copia. Potresti parallelizzarlo enormemente, penso. Forse con un sacco di ruoli di lavoro in azzurro. –
Ho avuto lo stesso pensiero; inizialmente stavo eseguendo tutto in modo sincrono. Dopo alcuni test, ci sarebbero voluti quasi due settimane, quindi l'ho riscritto per utilizzare BeginStartCopyFromBlob() e ho avvolto le chiamate su CopyBlobDirectory() in Parallel.ForEach.Tuttavia, il framework Parallel rifiuta di farmi eseguire più di 5 lavori in una volta (anche se ho impostato un grado più alto); Non sono sicuro di come costringerlo a correre di più. – Dusda
Puoi semplicemente generare molti thread come questo: http://stackoverflow.com/questions/5041153/how-to-create-multiple-threads-in-windows-azure-worker-role, dici 1000 per istanza di lavoro e poi far girare qualche dozzina di ruoli dei lavoratori? –