2017-07-31 1 views
0

J'ai écrit un système de journalisation qui écrit des entrées au format json dans un fichier dans Azure Data Lake. Plusieurs threads écrivent dans ce fichier, donc j'utilise la méthode ConcurrentAppendAsync.TaskCanceledException lors de l'ajout de contenu simultané à l'aide de ConcurrentAppendAsync à l'aide de CancellationToken.None

J'initialize l'accès comme ceci:

var clientCredential = new ClientCredential(ClientId, ClientSecret); 
var creds = ApplicationTokenProvider.LoginSilentAsync(Domain, clientCredential).GetAwaiter().GetResult(); 
fileSystemClient = new DataLakeStoreFileSystemManagementClient(creds); 
fileSystem = fileSystemClient.FileSystem; 

et j'écrire le contenu comme ceci:

private async Task WriteToDataLakeAsync(IGrouping<string, LogEvent> logEvents) 
    { 
     var logEvent = logEvents.FirstOrDefault(); 
     if (logEvent == null) 
      return; 

     var filename = string.Format(@"Logs\{0:yyyy}\{0:MM}\{0:dd}\{1}\{2}.json", logEvent.Session.Timestamp, logEvent.Session.Origin, logEvent.Session.SessionId); 

     var jsonBuilder = new StringBuilder(); 

     foreach (var @event in logEvents) 
     { 
      jsonBuilder.AppendLine(JsonConvert.SerializeObject(@event.SimplifyForBlob(), Formatting.None)); 
     } 

     try 
     { 
      await fileSystem.ConcurrentAppendAsync(Account, filename, new MemoryStream(Encoding.UTF8.GetBytes(jsonBuilder.ToString())), AppendModeType.Autocreate, cancellationToken: CancellationToken.None); 
     } 
     catch (Exception ex) 
     { 
      telemetryClient.TrackException(new ExceptionTelemetry(new Exception($"{nameof(DataLake)}: Failed to write {filename}", ex))); 
     } 
    } 

Le problème est, bien que je passe CancellationToken.None-fileSystem.ConcurrentAppendAsync(...) je reçois un TaskCanceledException encore dans mon bloc catch:

System.Exception: System.Threading.Tasks.TaskCanceledException: à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (mscorlib, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089) à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (mscorlib , Version = 4.0.0.0, Culture = Neutre, PublicKeyToken = b77a5c561934e089) à Microsoft.Rest.RetryDelegatingHandler + <> c__DisplayClass11_0 + b__1> d.MoveNext (Microsoft.Rest.ClientRuntime, Version = 2.0.0.0, Culture = neutre, PublicKeyToken = 31bf3856ad364e35) à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (mscorlib, version = 4.0.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089) à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (mscorlib, Versi sur = 4.0.0.0, Culture = neutre, PublicKeyToken = b77a5c561934e089) à Microsoft.Rest.RetryDelegatingHandler + d__11.MoveNext (Microsoft.Rest.ClientRuntime, Version = 2.0.0.0, Culture = neutre, PublicKeyToken = 31bf3856ad364e35) au système. Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (mscorlib, Version = 4.0.0.0, Culture = neutre, PublicKeyToken = b77a5c561934e089) à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (mscorlib, Version = 4.0.0.0, Culture = neutre, PublicKeyToken = b77a5c561934e089) à System.Net.Http.HttpClient + d__58.MoveNext (System.Net.Http, version = 4.1.1.1, Culture = neutre, PublicKeyToken = b03f5f7f11d50a3a) à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (mscorlib, Version = 4.0.0.0, Culture = neutre, PublicKeyToken = b77a5c561934e089) à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (mscorlib, Version = 4.0.0.0, Culture = neutre, PublicKeyToken = b77a5c561934e089) à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (mscorlib, Version = 4.0.0.0, Culture = neutre, PublicKeyToken = b77a5c561934e089) à Microsoft.Azure.Management.DataLake.Store.FileSystemOperations + d__10.MoveNext (Microsoft.Azure.Management.DataLake.Store, Version = 2.0.0.0, Culture = neutre, PublicKeyToken = 31bf3856ad364e35) au système. Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (mscorlib, Version = 4.0.0.0, Culture = neutre, PublicKeyToken = b77a5c561934e089) à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (mscorlib, Version = 4.0.0.0, Culture = neutre, PublicKeyToken = b77a5c561934e089) à Microsoft.Azure.Management.DataL ake.Store.FileSystemOperationsExtensions + d__3.MoveNext (Microsoft.Azure.Management.DataLake.Store, Version = 2.0.0.0, Culture = neutre, PublicKeyToken = 31bf3856ad364e35) à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (mscorlib, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089) à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (mscorlib, version = 4.0.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089) à DHS.PlanCare.CentralLogging.EventHub.Processors.StreamProcessors.DataLake + d__15.MoveNext (DHS.PlanCare.CentralLogging.EventHub.Processors, Version = 1.0.0.0, Culture = neutre, PublicKeyToken = null: D: \ Sources \ DHS.PlanCare.ManagementPortal \ DHS.PlanCare .ManagementPortal.EventHub.Processors \ StreamProcessors \ DataLake.cs: 95)

(ligne 95 est l'appel à ConcurrentAppendAsync)

Qu'est-ce qui pourrait se passer ici? Cela n'aide pas que the docs ne dise rien à propos de cette exception. Il y a même une erreur dans la documentation puisqu'elle indique que lorsqu'un message CancellationToken n'est pas passé, la valeur sera null, ce qui est impossible puisque CancellationToken est un type de valeur et par conséquent ne peut pas être null. Par conséquent, je sais pertinemment que je n'initialise aucun type d'annulation. La question est, puis-je ignorer cette exception ou les données ne seront-elles pas écrites du tout? En raison de la grande quantité de données ingérées et le fait qu'il arrive à l'occasion, il est difficile de vérifier si les données sont réellement écrites ou non.

+0

Je ne sais pas pourquoi cela a voté pour fermer pour des raisons de «pourquoi est-ce code ne fonctionne pas. Je ne peux vraiment plus penser à ce que je pourrais ajouter à ce post. J'ai un problème et une erreur spécifiques, mais je me rends compte qu'il ne peut pas être reproduit facilement, mais c'est pourquoi j'espérais trouver des gens qui ont travaillé avec cette technologie et qui l'ont déjà fait. –

+0

Il est possible que le client SDK ait atteint sa limite de délai d'attente en attendant une réponse du serveur pour l'appel ConcurrentAppend. Vous pouvez configurer ce délai d'expiration [lors de la création du DataLakeStoreFileSystemManagementClient] (https://docs.microsoft.com/en-us/dotnet/api/microsoft.azure.management.datalake.store.datalakestorefilesystemmanagementclient-ctor?view=azuremgmtdatalakestore-2.2 .0 # Microsoft_Azure_Management_DataLake_Store_DataLakeStoreFileSystemManagementClient__ctor_Microsoft_Rest_ServiceClientCredentials_System_String_System_String_System_Int32_System_Net_Http_DelegatingHandler ___). –

+0

Combien de données transférez-vous dans un seul appel ConcurrentAppend, au maximum? –

Répondre

0

HttpClient, qui est utilisé en interne, déclenche un OperationCanceledException au délai d'expiration. Ces délais peuvent survenir lors d'une connexion active ou lors de l'établissement d'une connexion. DataLakeStoreFileSystemManagementClient a un constructeur qui prend un paramètre facultatif clientTimeoutInMinutes, qui est utilisé pour définir HttpClient.Timeout.

Dans ce cas, c'est en fait le Microsoft.Rest.RetryDelegatingHandler qui répond à l'annulation que HttpClient a défini et qui lève l'exception.

Il provient aussi couramment d'un CancellationTokenSource.CancelAfter interne, qui peut également être utilisé pour un timeout.

Comme il est utile de faire la différence entre les délais d'attente et les demandes réelles d'annulation, je conclurai habituellement quelque chose comme ceci:

try 
{ 
    ... 
} 
catch (OperationCanceledException ex) when (!cancellationToken.IsCancellationRequested) 
{ 
    throw new TimeoutException("The operation timed out.", ex); 
}