Mon rôle Azure récupère des données à traiter à partir d'une database – il contient une instance de System.Data.SqlClient.SqlConnection
et crée périodiquement une instance de SqlCommand
et exécute une requête SQL.
Maintenant, une fois de time en time (généralement une fois tous les jours), l'exécution d'une requête triggersra une exception SqlException
Le service a rencontré une erreur lors du traitement de votre request. Veuillez réessayer. Code d'erreur 40143. Une erreur grave s'est produite sur la command en cours. Les résultats, le cas échéant, doivent être ignorés.
Ce que j'ai déjà vu plusieurs fois et maintenant mon code l'attrape, appelle Dispose()
sur l'instance de SqlConnection
, puis rouvre la connection et réessaie la requête. Ce dernier entraîne généralement une autre exception SqlException
Le timeout d'attente a expiré. Le timeout d'expiration s'est écoulé avant la fin de l'opération ou le server ne répond pas.
Ce qui ressemble beaucoup au fait que le server SQL Azure ne répond pas ou n'est pas disponible pour une raison quelconque.
Actuellement mon code n'attrape pas la dernière exception, il est propagé en dehors de RoleEntryPoint.Run()
et le rôle est redémarré. Redémarrer prend généralement environ dix minutes et une fois qu'il est terminé, le problème est parti pour un jour ou deux.
Je n'aime pas que mon rôle redémarre – il faut du time et ma fonctionnalité de service est entravée. J'aimerais faire quelque chose de plus intelligent.
Quelle serait une stratégie pour résoudre ce problème? Devrais-je réessayer la requête plusieurs fois et combien de fois et avec quel intervalle? Devrais-je faire autre chose? Quand dois-je abandonner et laisser le rôle redémarrer?
Je vous recommand fortement de jeter un coup d'œil sur le cadre de gestion des erreurs transitoires pour SQL Azure
Cela vous aidera à gérer la logique de tentative à la fois pour les tentatives de connection et de requête, je l'utilise en production et cela fonctionne très bien. Il y a aussi un bon article sur Technet qui pourrait être utile.
[EDIT: 17 octobre 2013]
Il semble que cela a été pris en count par l'équipe des templates et des pratiques du bloc d'application de traitement des fautes transitoires
Nous utilisons TransientFaultHandling et il ne gère pas toutes les exceptions étranges.
Par exemple, celui-ci a surgi hier:
Le service a rencontré une erreur lors du traitement de votre request. Veuillez réessayer. Code d'erreur 40143. Une erreur grave s'est produite sur la command en cours. Les résultats, le cas échéant, doivent être ignorés. , stacktrace à System.Data.SqlClient.SqlConnection.OnError (Exception SqlException, Boolean breakConnection) à System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning () à System.Data.SqlClient.TdsParser.Run (RunBehavior runBehavior, SqlCommand cmdHandler,. .
L'approche raisonnable qui fonctionnera même avec ceci:
Exemple d'un workflow typique:
Envelopper B à C set dans un try-catch. Si quelque chose se produit lors d'un appel SQL Azure «inoffensif», il suffit de sortir du message sans supprimer le message, il apparaîtra simplement à nouveau après l'expiration du timeout de visibilité.
En fait, il s'agit d'une approche très courante: s'organiser en blocs de type transaction, bloquer le bloc en try-catch, revenir en arrière sur l'exception. Et jamais, ne supposez jamais que certains appels n'échouent pas. Tous les appels échouent de time en time.