2017-09-13 5 views
0

Je reçois unAzure - erreur 403 - Copie d'un grand nombre de blobs compte de stockage à un autre compte de stockage sur pay-as-you-go ACCT

403 Interdit

erreur lors de la copie un grand nombre de blobs de bloc d'un compte de stockage à un autre compte de stockage (dans une région différente en tant que sauvegarde). Après 100 000+ sont copiés, je reçois une erreur 403 Forbidden.

J'ai vu des réponses parler d'un quota mais je crois que c'est pour les comptes gratuits. J'ai un client avec un 578 000 fichiers que j'ai déplacé vers Azure à partir du local et cela a bien fonctionné mais je ne peux pas faire une copie à un autre compte de stockage que j'ai configuré pour sauvegarder (en cas de suppressions surtout).

J'utilise , puis je vérifie l'état de Copystate pour vérifier que la copie a réussi et réessaye dans mon code, mais il semble échouer sur le StartCopyAsync.

La copie fonctionne correctement jusqu'à ce que j'ai copié plus de 100 000 fichiers, puis l'erreur se produit. Je ne suis pas sûr de ce qui cause cela puisque le même code fonctionne bien pour autant de blobs d'abord. J'ai ajouté un fichier journal qui m'a indiqué quel fichier a échoué et je peux ouvrir ce fichier dans Azure Explorer.

Je peux poster le code mais en ce moment, je me demande si je suis en train de frapper une sorte de problème de devis/bande passante que je ne connais pas.

namespace BackupCloudContainers 
    { 

    class Program 
    { 
     static string privateconnectionstring = ConfigurationManager.AppSettings["StorageConnectionString"]; 
     static string privatebackupconnectionstring = ConfigurationManager.AppSettings["BackupStorageConnectionString"]; 
     static DateTime testdate = new DateTime(2017, 8, 28, 0, 0, 0); 
     static string destContainerName = ""; 
     static void Main(string[] args) 
     { 
      try 
      { 
       //Console.WriteLine("Starting Backup at " + DateTime.Now.ToString("hh:mm:ss.ffff")); 
       Log("Starting Incremental Backup (everything since " + testdate.ToString("f") + ") at " + DateTime.Now.ToString("hh:mm:ss.ffff")); 
       Backup().GetAwaiter().GetResult(); 
       // Console.WriteLine("Backup Created as " + destContainerName); 
       Log("Backup Created as " + destContainerName); 
       //Console.WriteLine("Backup ended at " + DateTime.Now.ToString("hh:mm:ss.ffff")); 
       Log("Backup ended at " + DateTime.Now.ToString("hh:mm:ss.ffff")); 
       Console.WriteLine("\n\nPress Enter to close. "); 
       Console.ReadLine(); 
      } 
      catch (Exception e) 
      { 
       //Console.WriteLine("Exception - " + e.Message); 
       Log("Exception - " + e.Message); 
       if (e.InnerException != null) 
       { 
        //Console.WriteLine("Inner Exception - " + e.InnerException.Message); 
        Log("Inner Exception - " + e.InnerException.Message); 
       } 
      } 
     } 
     static async Task Backup() 
     { 

      CloudStorageAccount _storageAccount = CloudStorageAccount.Parse(privateconnectionstring); 
      CloudStorageAccount _storageBackupAccount = CloudStorageAccount.Parse(privatebackupconnectionstring); 

      CloudBlobClient blobClient = _storageAccount.CreateCloudBlobClient(); 
      CloudBlobClient blobBackupClient = _storageBackupAccount.CreateCloudBlobClient(); 

      foreach (var srcContainer in blobClient.ListContainers()) 
      { 
       // skip any containers with a backup name 
       if (srcContainer.Name.IndexOf("-backup-") > -1) 
       { 
        continue; 
       } 
       var backupTimeInTicks = DateTime.UtcNow.Ticks; 
       //var destContainerName = srcContainer.Name + "-" + backupTimeInTicks; 
       var backupDateTime = DateTime.UtcNow.ToString("yyyyMMdd-hhmmssfff"); 
       destContainerName = srcContainer.Name + "-backup-" + backupDateTime; 

       var destContainer = blobBackupClient.GetContainerReference(destContainerName); 
//    var destContainer = blobClient.GetContainerReference(destContainerName); 

       // assume it does not exist already, 
       // as that wouldn't make sense. 
       await destContainer.CreateAsync(); 

       // ensure that the container is not accessible 
       // to the outside world, 
       // as we want all the backups to be internal. 
       BlobContainerPermissions destContainerPermissions = destContainer.GetPermissions(); 
       if (destContainerPermissions.PublicAccess != BlobContainerPublicAccessType.Off) 
       { 
        destContainerPermissions.PublicAccess = BlobContainerPublicAccessType.Off; 
        await destContainer.SetPermissionsAsync(destContainerPermissions); 
       } 

       // copy src container to dest container, 
       // note that this is synchronous operation in reality, 
       // as I want to only add real metadata to container 
       // once all the blobs have been copied successfully. 
       await CopyContainers(srcContainer, destContainer); 
       await EnsureCopySucceeded(destContainer); 

       // ensure we have some metadata for the container 
       // as this will helps us to delete older containers 
       // on a later date. 
       await destContainer.FetchAttributesAsync(); 

       var destContainerMetadata = destContainer.Metadata; 
       if (!destContainerMetadata.ContainsKey("BackupOf")) 
       { 
        string cname = srcContainer.Name.ToLowerInvariant(); 
        destContainerMetadata.Add("BackupOf", cname); 
        destContainerMetadata.Add("CreatedAt", backupTimeInTicks.ToString()); 
        destContainerMetadata.Add("CreatedDate", backupDateTime); 
        await destContainer.SetMetadataAsync(); 
        //destContainer.SetMetadata(); 
       } 
      } 

      // let's purge the older containers, 
      // if we already have multiple newer backups of them. 
      // why keep them around. 
      // just asking for trouble. 
      //var blobGroupedContainers = blobBackupClient.ListContainers() 
      // .Where(container => container.Metadata.ContainsKey("Backup-Of")) 
      // .Select(container => new 
      // { 
      //  Container = container, 
      //  BackupOf = container.Metadata["Backup-Of"], 
      //  CreatedAt = new DateTime(long.Parse(container.Metadata["Created-At"])) 
      // }).GroupBy(arg => arg.BackupOf); 

      var blobGroupedContainers = blobClient.ListContainers() 
       .Where(container => container.Metadata.ContainsKey("BackupOf")) 
       .Select(container => new 
       { 
        Container = container, 
        BackupOf = container.Metadata["BackupOf"], 
        CreatedAt = new DateTime(long.Parse(container.Metadata["CreatedAt"])) 
       }).GroupBy(arg => arg.BackupOf); 

      // Remove the Delete for now 
     //  foreach (var blobGroupedContainer in blobGroupedContainers) 
     //  { 
     //   var containersToDelete = blobGroupedContainer.Select(arg => new 
     //   { 
     //    Container = arg.Container, 
     //    CreatedAt = new DateTime(arg.CreatedAt.Year, arg.CreatedAt.Month, arg.CreatedAt.Day) 
     //   }) 
     //    .GroupBy(arg => arg.CreatedAt) 
     //    .OrderByDescending(grouping => grouping.Key) 
     //    .Skip(7) /* skip last 7 days worth of data */ 
     //    .SelectMany(grouping => grouping) 
     //    .Select(arg => arg.Container); 

     //// Remove the Delete for now 
     //   //foreach (var containerToDelete in containersToDelete) 
     //   //{ 
     //   // await containerToDelete.DeleteIfExistsAsync(); 
     //   //} 
     //  } 
     } 

     static async Task EnsureCopySucceeded(CloudBlobContainer destContainer) 
     { 
      bool pendingCopy = true; 
      var retryCountLookup = new Dictionary<string, int>(); 

      while (pendingCopy) 
      { 
       pendingCopy = false; 

       var destBlobList = destContainer.ListBlobs(null, true, BlobListingDetails.Copy); 

       foreach (var dest in destBlobList) 
       { 
        var destBlob = dest as CloudBlob; 
        if (destBlob == null) 
        { 
         continue; 
        } 

        var blobIdentifier = destBlob.Name; 

        if (destBlob.CopyState.Status == CopyStatus.Aborted || 
         destBlob.CopyState.Status == CopyStatus.Failed) 
        { 
         int retryCount; 
         if (retryCountLookup.TryGetValue(blobIdentifier, out retryCount)) 
         { 
          if (retryCount > 4) 
          { 
           throw new Exception("[CRITICAL] Failed to copy '" 
                 + destBlob.CopyState.Source.AbsolutePath + "' to '" 
                 + destBlob.StorageUri + "' due to reason of: " + 
                 destBlob.CopyState.StatusDescription); 
          } 

          retryCountLookup[blobIdentifier] = retryCount + 1; 
         } 
         else 
         { 
          retryCountLookup[blobIdentifier] = 1; 
         } 

         pendingCopy = true; 

         // restart the copy process for src and dest blobs. 
         // note we also have retry count protection, 
         // so if any of the blobs fail too much, 
         // we'll give up. 
         await destBlob.StartCopyAsync(destBlob.CopyState.Source); 
        } 
        else if (destBlob.CopyState.Status == CopyStatus.Pending) 
        { 
         pendingCopy = true; 
        } 
       } 

       Thread.Sleep(1000); 
      } 
     } 

     static async Task CopyContainers(
       CloudBlobContainer srcContainer, 
       CloudBlobContainer destContainer) 
     { 
      // get the SAS token to use for all blobs 
      string blobToken = srcContainer.GetSharedAccessSignature(new SharedAccessBlobPolicy() 
      { 
       Permissions = SharedAccessBlobPermissions.Read, 
       SharedAccessStartTime = DateTime.Now.AddMinutes(-5), 
       SharedAccessExpiryTime = DateTime.Now.AddHours(3) 
      }); 
      int ii = 0; 
      int cntr = 0; 
      int waitcntr = 0; 
      string sourceuri = ""; 
      int datecntr = 0; 
      try 
      { 

       //Console.WriteLine(" container contains " + srcContainer.ListBlobs(null, true).Count().ToString()); 
       Log(" container contains " + srcContainer.ListBlobs(null, true).Count().ToString()); 
       foreach (var srcBlob in srcContainer.ListBlobs(null, true)) 
       { 
        ii++; 

        //THIS IS FOR COUNTING Blobs that would be on the Incremental Backup 
        CloudBlob blob = (CloudBlob)srcBlob; 
        if (blob.Properties.LastModified > testdate) 
        { 
         datecntr++; 
        } 
        else 
        { 
         // We are only doing an Incremental Backup this time - so skip all other files 
         continue; 
        } 


        //if (ii > 2000) 
        //{ 
        // //Console.WriteLine(" test run ended "); 
        // Log(" test run ended "); 
        // break; 
        //} 


        cntr++; 
        if (cntr > 999) 
        { 
         //Console.WriteLine(" " + ii.ToString() + " processed at " + DateTime.Now.ToString("hh:mm:ss")); 
         Log(" " + ii.ToString() + " processed at " + DateTime.Now.ToString("hh:mm:ss")); 

         //Log(" EnsureCopySucceeded - finished at " + DateTime.Now.ToString("hh:mm:ss")); 
         //await EnsureCopySucceeded(destContainer); 
         //Log(" EnsureCopySucceeded - finished at " + DateTime.Now.ToString("hh:mm:ss")); 

         cntr = 0; 

        } 

        waitcntr++; 
        if (waitcntr > 29999) 
        { 
         Log(" EnsureCopySucceeded (ii=" + ii.ToString() + "- started at " + DateTime.Now.ToString("hh:mm:ss")); 
         await EnsureCopySucceeded(destContainer); 
         Log(" EnsureCopySucceeded - finished at " + DateTime.Now.ToString("hh:mm:ss")); 
         waitcntr = 0; 
        } 


        var srcCloudBlob = srcBlob as CloudBlob; 
        if (srcCloudBlob == null) 
        { 
         continue; 
        } 

        CloudBlob destCloudBlob; 

        if (srcCloudBlob.Properties.BlobType == BlobType.BlockBlob) 
        { 
         destCloudBlob = destContainer.GetBlockBlobReference(srcCloudBlob.Name); 
        } 
        else 
        { 
         destCloudBlob = destContainer.GetPageBlobReference(srcCloudBlob.Name); 
        } 
        sourceuri = srcCloudBlob.Uri.AbsoluteUri + blobToken; 

        try 
        { 
         await destCloudBlob.StartCopyAsync(new Uri(srcCloudBlob.Uri.AbsoluteUri + blobToken)); 
        } 
        catch (Exception e) 
        { 
         Log("Error at item " + ii.ToString() + "  Source = " + sourceuri + "  Message = " + e.Message + "  Time = " + DateTime.Now.ToString("F") + "\r\n"); 
        } 
       } 
       Log("Total Items checked = " + ii.ToString() + " backed up files = " + datecntr.ToString()); 
       Log("TestDate = " + testdate.ToString("F") + "  datecntr = " + datecntr.ToString()); 
      } 
      catch (Exception e) 
      { 
       Log("Error at item " + ii.ToString()); 
       Log("  Source = " + sourceuri); 
       Log("  Message = " + e.Message); 
       Log("  Time = " + DateTime.Now.ToString("F") + "\r\n"); 
       //throw e; 
      } 
     } 


     static void Log(string logdata) 
     { 
      Console.WriteLine(logdata); 
      File.AppendAllText("c:\\junk\\dwlog.txt", logdata + "\r\n"); 
     } 
    } 
    } 
+0

Veuillez poster le code. Les erreurs 403 ne sont pas liées au quota. –

+0

Il n'y a pas de quota autour des comptes gratuits et des transactions de stockage. S'il vous plaît poster votre code et erreur. Sinon, il est difficile (ou impossible) de déterminer le problème. –

+0

Nouveau sur Stack Overflow - comment puis-je poster un code - trop long pour "Ajouter un commentaire". – dwirth

Répondre

1

Vous avez mentionné que votre code commence à échouer après 3 heures. Eh bien, les lignes de code sont coupable suivantes pour que:

string blobToken = srcContainer.GetSharedAccessSignature(new SharedAccessBlobPolicy() 
    { 
     Permissions = SharedAccessBlobPermissions.Read, 
     SharedAccessStartTime = DateTime.Now.AddMinutes(-5), 
     SharedAccessExpiryTime = DateTime.Now.AddHours(3) 
    }); 

Si vous remarquez, vous créez une signature d'accès partagé (SAS) qui est valable pour une durée de 3 heures et que vous utilisez ce SAS tous les blobs. Votre code fonctionne tant que SAS est valide, c'est-à-dire qu'il n'a pas expiré. Une fois que le SAS expire, parce que maintenant le jeton SAS n'est pas autorisé à effectuer l'opération, vous commencez à obtenir l'erreur 403 (Not Authorized).

Ma recommandation serait de créer un jeton SAS valide pour une durée plus longue. Je recommanderais un jeton SAS valide pour 15 days car il s'agit de la durée maximale pendant laquelle Azure Storage tente de copier votre blob d'un compte à un autre.

+0

MERCI - J'ai complètement manqué cela quand je suis revenu sur le code. Dang - se sentir assez stupide (encore)! – dwirth