Sont des problèmes de concurrence possible lors de l'utilisation du Service WCF Comportement de l'attribut ConcurrencyMode.Multiples et InstanceContextMode.PerCall?
Nous avons un service WCF qui fait une bonne partie de transactionnelles NHibernate appels. Occasionnellement, nous avons été voir les SQL délais d'attente, même si les appels ont mis à jour les différentes lignes et les tableaux ont été mis à verrouillage de niveau ligne.
Après avoir creusé dans les journaux, il ressemble à différents threads ont été saisie de la même point dans le code (notre transaction à l'aide de bloc), et une mise à jour a été suspendu à s'engager. Il n'avait pas de sens, bien que, parce que nous avons cru que le service suivant attribut de classe a forcé un unique thread d'exécution par un appel de service:
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.PerCall)]
Nous avons récemment changé la simultanéité mode de ConcurrencyMode.Single
et n'avez pas de problèmes, mais le bug a été très difficile à reproduire (si quelqu'un a des idées sur la vidange d'un bug comme ça, laissez-moi savoir!).
De toute façon, que tous m'amène à ma question: ne devrait-il pas un InstanceContextMode de PerCall appliquer fil-sécurité au sein du service, même si le ConcurrencyMode est définie à plusieurs? Comment serait-il possible pour les deux appels à être desservis par la même instance de service?
Merci!
Vous devez vous connecter pour publier un commentaire.
La seule façon d'avoir deux différents WCF clients, c'est à dire, les procurations, font référence à la même instance de votre service WCF est d'utiliser
InstanceContextMode=InstanceContextMode.Single
. C'est un mauvais choix si la mise à l'échelle est un problème, si vous voulez utiliserPerCall
si vous le pouvez.Lorsque vous utilisez
PerCall
, chaque APPEL du service WCF obtient son propre service WCF instance. Il n'y a pas de partage de l'instance de service, mais cela ne signifie pas qu'ils ne partagent pas le même back-end de stockage (p. ex., base de données, de la mémoire, fichier, etc.). Rappelez-vous juste,PerCall
permet à chaque appel pour accéder à votre service WCF simultanément.La
ConcurrencyMode
paramètre contrôle le modèle de thread du service lui-même. Un réglage deSingle
limite tous de la WCF service des instances en cours d'exécution sur le même thread. Donc, si vous avez plusieurs clients qui se connectent en même temps, ils ne seront exécutées l'une après l'autre sur le service WCF côté. Dans ce cas, vous tirer parti de roulement pour assurer la synchronisation. Ça marchera très bien, comme vous l'avez vu, mais pensez à avoir de ce fait uniquement au niveau macro-contrôle de la synchronisation - chaque appel de service WCF va exécuter dans son intégralité avant le prochain appel peut exécuter.Réglage
ConcurrencyMode
àMultiple
, cependant, permettra à l'ensemble de la WCF instances de service d'exécuter simultanément. Dans ce cas, vous êtes responsable de fournir la synchronisation nécessaire. Pensez à avoir de ce fait des micro-niveau de contrôle de synchronisation puisque vous pouvez synchroniser uniquement les parties de chaque appel, qui doivent être synchronisés.J'espère que j'ai expliqué assez bien, mais voici un extrait de la documentation MSDN pour
ConcurrencyMode
juste au cas où:MODIFIER
Vous avez demandé
Ce sera probablement dépendant d'un service.
Avec
InstanceContextMode.PerCall
, une nouvelle instance est créée pour chaque et tous les appels via le serveur proxy, vous avez donc la surcharge de création de l'instance à traiter. En supposant que votre service constructeur ne fait pas beaucoup, ce ne sera pas un problème.Avec
InstanceContextMode.Single
, une seule instance de service existe pour la durée de vie de l'application, il n'y a pratiquement pas de frais généraux associés à la création de l'instance. Cependant, ce mode permet à une seule instance de service pour traiter chaque appel qui ne sera jamais fait. Donc, si vous avez plusieurs appels simultanément, chaque appel à attendre pour les autres appels à terminer avant de pouvoir être exécuté.Pour ce que ça vaut, voici comment je l'ai fait. Utiliser le
PerCall
instance de contexte avecMultiple
la simultanéité. À l'intérieur de votre service WCF classe, de créer des membres statiques de gérer la banque de données, puis de synchroniser l'accès à ces membres statiques nécessaires, à l'aide de lalock
déclaration,volatile
champs, etc. Cela permet à votre service à l'échelle agréablement tout en préservant la sécurité des threads.ConcurrencyMode.Multiple
, indépendamment de InstanceContextMode, signifie que vous êtes en utilisantlock
états autour de sections critiques et d'effectuer d'autres thread-safety/synchronisation des contrôles. Est-il une augmentation de la performance, puis, à l'aide dePerCall
vsSingle
lors de l'utilisation deConcurrencyMode.Single
? Ou est l'inverse est vrai?ConcurrencyMode
àSingle
limite chaque instance du service pour un seul thread, pas toutes les instances d'un service à un seul thread. Les demandes ne sont exécutés un à un moment si leInstanceContextMode
est également mis àSingle
. Donc, siInstanceContextMode
estPerCall
etConcurrencyMode
estSingle
, le service WCF prennent en charge plusieurs clients en même temps.Je crois que la réponse est le fait qu'il y a plusieurs threads (côté client) en utilisant le même proxy instance, et donc, potentiellement, en permettant plusieurs appels dans la même instance. Cette post a une explication plus détaillée.
PerCall
instance de contexte etMultiple
simultanéité mode. Dans ce cas, vous doit fournir thread-safety-vous si vous créez le proxy à chaque fois ou de réutiliser le même.PerCall
instance accède. Dans ce cas,PerCall
fournit pas de fil de sécurité à l'arrière-plan des ressources. Qui doivent être gérés manuellement.InstanceContextMode.PerCall
etConcurrencyMode.Single
devrait être bon si vous n'êtes pas à l'aide de deux manière de rappels sur le serveur. Dans ce cas, vous aurez besoin d'utiliserConcurrencyMode.Reentrant
ou de rappel ne sera pas en mesure d'obtenir l'accès à l'verrouillé instance de service et un blocage se produit.Depuis sa par appel en instance de service de la création, il est impossible pour les autres threads ou des appels pour y avoir accès. Comme indiqué dans l'article mentionné dans d'autres réponses l'article une telle combinaison peut encore être un problème si la session est creatd sur une liaison de niveau ET que vous utilisez le même objet proxy de service.
Donc, si vous n'utilisez pas le même objet proxy ou qui n'ont pas un sessionful de liaison et de ne pas utiliser deux façon de rappels au client ( le plus probable est qu'ils doivent être Univoques de toute façon)
InstanceContextMode.PerCall
etConcurrencyMode.Single
devrait être bon.Je pense que tout dépend de l'exigence.
Si nous allons appeler le même service, de sorte que beaucoup de fois mieux que nous pouvons utiliser
InstanceContextMode est Unique et concurrencymode est multiple.