Gestion des délais d'expiration du service Web lors de l'exécution de tâches de base de données à exécution longue
L'architecture de l'un de nos produits est un exemple typique de niveau 3 solution:
- Client C#
- Service web WCF
- Base de données SQL Server
Le client demande des informations à partir du service web. Le service web hits de la base de données pour les informations et la renvoie au client.
Voici le problème. Certaines de ces requêtes peuvent prendre un long, long moment, et nous ne savons pas d'avance quels sont ceux qui seront lents. Nous savons que certains qui sont souvent plus lents que d'autres, mais même la plus simple des demandes peut être lent, compte tenu de suffisamment de données. Parfois utilise requête ou d'exécuter des rapports sur de grandes quantités de données. Les requêtes peuvent être optimisées que jusqu'à présent avant que le volume de données ralentit.
Si une requête dans la base de données atteint le maximum de délai d'expiration de requête dans SQL server, la base de données de la requête se termine, et le service web renvoie une erreur au client. C'est entendu. Nous pouvons nous occuper de ces erreurs.
Le client est en attente pour l'appel de service web pour compléter. Si la base de données prend beaucoup de temps, le client peut timeout sur son appel au service web. Le client donne, mais la demande de base de données continue le traitement. À ce stade, le client est hors de synchronisation avec la base de données. La base de données d'appel peut ou peut ne pas réussir. Il peut y avoir eu une erreur. Le client ne le saura jamais. Dans certains cas, nous ne voulons pas que nos utilisateurs de lancer une autre demande qui peut entraîner une défaillance de l'état compte tenu de l'achèvement de la précédente demande.
Je suis curieux de voir comment d'autres ont traité ce problème. Quelles stratégies avez-vous utilisées pour prévenir web service, délais d'expiration de toucher d'appels de base de données?
Les meilleures idées, je peux venir avec impliquent la réalisation d'une base de données de la couche quelque part, à l'intérieur du service web, joint à un message de la file d'attente-- quelque chose. Déchargement de chaque requête unique à un autre processus semble excessif. (Là encore, on ne sait pas toujours si une demande va être rapide ou lent.)
Ce serait génial si on pouvait séparer l'acte de faire une requête HTTP à partir de la loi de l'élaboration et de l'exécution d'un processus de base de données. J'ai vu ce fait avec un serveur personnalisé lors d'une précédente entreprise, mais c'était à l'aide de droites communication par socket, et je préfère éviter de remplacer le web service avec certaines applications personnalisées.
Noter que compte tenu de la quantité de données que nous traitons, nous sommes tous sur l'optimisation de la requête. L'optimisation de la requête, index, etc., vous prend seulement jusqu'ici lorsque le volume de données est élevé. Parfois, les choses prennent du temps.
source d'informationauteur Paul Williams | 2009-02-06
Vous devez vous connecter pour publier un commentaire.
J'ai rencontré des problèmes similaires dans le passé, et utilisé l'une des 3 méthodes suivantes pour résoudre:
Dans mon cas, ils étaient tous de complexes rapports qui où puis envoyé au client, ou qui ont été stockées dans des permanents "temporaire" des tables, pour la consultation par les clients après leur avaient été notifiés.
Cela a bien fonctionné quand nous ne voulions pas faire le chargement de la page synchroniser avec ce que le service web est en train de faire.
Cependant, il ne signifie pas que cette fonctionnalité n'était pas disponible jusqu'à ce que le long processus en cours d'exécution a été complète.
Nous avons sauté une autre fenêtre qui affiche une barre de progression, qui a également interrogé le serveur régulièrement.
Il utilise une variable de session afin de déterminer dans quelle mesure le long d'afficher la barre de progression.
Après la barre de progression a été lancé, un nouveau fil de discussion a été mis en route et mise à jour de la même session variable périodiquement.
Une fois que la variable de session de la valeur a été fixée à 100, la fenêtre est fermée.
Les clients aimé cette méthode.
J'espère en tout cas l'un de ceux qui est de l'aide pour vous.
Le service web peut exécuter les requêtes dans un pool de threads et si le thread n'a pas fini dans les 5 secondes (voir Fil.Join()), l'appel de service web renvoie au client un JobID au lieu de l'ensemble de résultats qui le client peut ensuite utiliser pour interroger le serveur toutes les quelques secondes pour voir si sa requête fini. Lorsqu'un thread termine les résultats peuvent être stockés dans une table de hachage jusqu'à ce que le client interroge à nouveau.
L'une des solutions que nous avons utilisés ces derniers temps est de briser l'immense base de données des processus de séparer les opérations en parallèle. Chaque opération est beaucoup plus petite et conçu pour être aussi efficace que possible. Les clients de lancer les opérations, frayer un, quelques fils, et de faire tout ce qu'ils peuvent en parallèle.
Par exemple, nous avons brisé en dehors des grands processes en une série d'étapes comme le Début, le Processus 1 Morceau de Travail, de Finition, et de Recueillir des Données de Rapport. Le Processus d'étapes de Travail peuvent s'exécuter en parallèle, mais ils ne peuvent pas commencer avant le Début de l'étape est terminée. L'Arrivée de l'étape a besoin d'attendre que tous les Processus de Travail des étapes à franchir.
Depuis le client est de contrôler le processus, le client peut rendre compte des progrès exactement à quelle étape il se trouve.
Rompre le problème de petits morceaux est certainement une bonne idée.
De plus et ce que d'autres ont dit (et seulement si vous avez la main sur le service web de mise en œuvre) et j'ai été d'utiliser le callback url réussi à le webservice. Le WS a appeler avec des erreurs ou des résultats dans la chaîne de requête ou de données post.
Les url contiennent généralement un jeton qui sert à permettre le rappel de re-saisir le client, et qui correspond à toutes les informations pertinentes nécessaires pour effectuer des actions après le rappel est reçu (stockées dans une base de données ou dans la mémoire).
C'est un peu lourd poids (surtout si vous n'êtes pas en cours d'exécution dans le serveur web est déjà fait) mais garantit le succès des aller-retour dans le cas où le client expire mais le webservice bien reçu l'instruction et qui est tout simplement lent dans le traitement.
Une fois cette configuration, votre webservice est en réalité un peu plus près pour être prêt à exécuter de manière asynchrone et de répondre rapidement au client : généralement, faire toutes les vérifications de répondre si c'est correct ou pas, et de frayer la lenteur de l'opération sur une autre boucle, avec l'url de callback afin qu'il puisse faire rapport au client.
Je ne suis pas sûr de la façon orthodoxe, c'est, d'ailleurs, mais il n'a résoudre des problèmes réels.