J'ai une application client-serveur. Mon scénario:
Parfois, les connexions WCF passent à l'état défectueux. Habituellement, lorsque cela se produit, le serveur n'a aucun réseau en amont. J'ai écrit un vidage de la mémoire et j'ai pu voir que beaucoup de threads WCF attendaient des WaitQueue
. La pile d'appels est:
Server stack trace: at System.ServiceModel.Channels.TransmissionStrategy.WaitQueueAdder.Wait(TimeSpan timeout) at System.ServiceModel.Channels.TransmissionStrategy.InternalAdd(Message message, Boolean isLast, TimeSpan timeout, Object state, MessageAttemptInfo& attemptInfo) at System.ServiceModel.Channels.ReliableOutputConnection.InternalAddMessage(Message message, TimeSpan timeout, Object state, Boolean isLast) at System.ServiceModel.Channels.ReliableDuplexSessionChannel.OnSend(Message message, TimeSpan timeout) at System.ServiceModel.Channels.DuplexChannel.Send(Message message, TimeSpan timeout) at System.ServiceModel.Dispatcher.DuplexChannelBinder.Send(Message message, TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation) at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
J'ai modifié les paramètres et il semble que la situation s'est améliorée - Maintenant, il y a moins de clients en défaut. Mes paramètres:
Je suis coincé. Pourquoi tous les appels essaient-ils d'attendre quelques WaitQueue
dans la TransmissionStrategy
? Je ne me soucie pas des messages envoyés dans le désordre (je m'en occupe moi-même). Je pensais déjà à désactiver la messagerie fiable mais l'application est utilisée dans un réseau d'entreprise dans le monde entier. J'ai besoin de savoir que mes messages ont été livrés.
Des idées comment apprendre à WCF à simplement envoyer les messages sans se soucier de rien d'autre?
MODIFIER strong >
Les valeurs de limitation de service sont définies sur Int32.MaxValue
.
J'ai également essayé de définir MaxConnections
et ListenBackLog (sur NetTcpBinding
) à leurs valeurs maximales. Cela n'a rien changé - pour autant que je sache.
EDIT 2
Vérification des traces WCF qu'il me dit (message allemand, donc un translation) qu'il n'y a pas d'espace disponible dans la fenêtre de transfert de messagerie fiable - et alors tout ce que je reçois, ce sont des délais d'attente car plus aucun message n'est envoyé.
Que se passe-t-il là-bas? Est-il possible que les messages fiables se confondent?
3 Réponses :
La file d'attente peut être liée au comportement de limitation intégré de wcf https://docs.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/wcf/servicethrottling Le meilleur moyen de dépanner est d'activer le traçage WCF https://docs.microsoft. com / fr-fr / dotnet / framework / configure-apps / file-schema / wcf / servicethrottling Et sachez exactement quelle en est la cause
Nan. Je les ai tous définis sur Int.MaxValue
Le traçage me dit simplement que la fenêtre de transfert fiable est pleine (voir ma question mise à jour). D'autres idées?
Utilisez-vous connectionManagement pour définir maxconnection de votre client? (Si votre session est en duplex) https: //docs.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/network/connectionmanagement-element-network-settings
Votre MaxPendingChannels est défini sur 16384, ce qui rendra trop de clients attendent dans la file d'attente, si le serveur ne peut pas traiter les clients à temps, le canal peut passer à l'état d'erreur.
FlowControlEnabled signifie s'il faut continuer d'envoyer un message au serveur lorsque le serveur a pas d'espace libre pour enregistrer le message. Vous feriez mieux de le définir sur true.
InactivityTimeout signifie s'il faut fermer la session lorsqu'il n'y a pas d'échange de messages dans un certain laps de temps. Vous feriez mieux de le définir sur une valeur appropriée.
De plus, avez-vous défini le délai d'expiration de votre liaison?
<netTcpBinding> <binding closeTimeout="" openTimeout="" receiveTimeout="" sendTimeout="" ></binding> </netTcpBinding>
J'utilise des valeurs par défaut, sauf pour le délai de réception.
En bref:
Il s'avère que mes paramètres WCF sont très bien.
Le ThreadPool est le facteur limitant. Dans les situations de trafic élevé (et donc de forte charge), je génère trop de messages qui doivent être envoyés aux clients. Ceux-ci sont mis en file d'attente car il n'y a pas assez de threads de travail pour envoyer les messages. À un moment donné, la file d'attente est pleine - et vous y êtes.
Pour plus de détails, consultez cette question et réponse a> de Russ Bishop.
Détail intéressant: cela a même réduit la charge du processeur dans les situations de trafic élevé. De la pointe folle entre 30 et 80% à une valeur (n) (presque) stable d'environ 30%. Je ne peux que supposer que c'est à cause de la génération et du nettoyage des threads de threadpool.
MODIFIER
J'ai fait ce qui suit:
ThreadPool.SetMinThreads(1000, 500)
Ces valeurs pourraient être comme utiliser une masse pour casser une noix - mais cela fonctionne.
Merci pour la mise à jour ! Mais qu'avez-vous fait pour résoudre le problème?
De plus, si le serveur appelle les clients uniquement en guise de notification, cela ne devrait pas prendre longtemps à gérer et ne drainera donc pas les ressources du serveur. il me semble que les appels à distance doivent être aussi courts que possible
@Menahem Pour clarifier davantage: lorsqu'un dataobject est modifié une notification de mise à jour est envoyée aux clients qui chargent alors la nouvelle version de l'objet. S'il y avait de nombreuses mises à jour, il semble que les threads de travail n'aient pas été en mesure de suivre le rythme ...
L'activation de la trace doit indiquer quand un canal est défaillant et pourquoi. Je pense qu'il vaut mieux donner une chance à la trace avant de bricoler une application de production
@Menahem veuillez vérifier Modifier 2
Cela ressemble à un problème plus profond, si la fenêtre de transfert 4096 est suffisante. Ses apparences ne sont pas reconnues. Le client et le serveur sont-ils sur le même réseau? Si c'est le cas, des sessions fiables ne sont pas nécessaires. Sinon peut-être que les accusés sont tombés
@Menahem dans mon environnement de test, la plupart d'entre eux sont sur le même commutateur - mais en production, il s'agit d'un réseau d'entreprise mondial
Et le problème est sur le net de test?
@Menahem J'ai mis en place cet environnement de test car j'ai ce comportement en production
Et ce problème se reproduit dans le test env?
continuons cette discussion dans le chat .