Quel délai de 130 secondes met fin à mon appel de service de streaming WCF?
Tout récemment, j'ai commencé à enquêter sur un problème délicat avec WCF en streaming dans laquelle un CommunicationException est produit si le client attend plus de 130 secondes entre les envoie au serveur.
Ici, c'est la pleine exception:
System.ServiceModel.CommunicationException was unhandled by user code
HResult=-2146233087
Message=The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '23:59:59.9110000'.
Source=mscorlib
StackTrace:
Server stack trace:
at System.ServiceModel.Channels.HttpOutput.WebRequestHttpOutput.WebRequestOutputStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at System.IO.BufferedStream.Write(Byte[] array, Int32 offset, Int32 count)
at System.Xml.XmlStreamNodeWriter.FlushBuffer()
at System.Xml.XmlStreamNodeWriter.GetBuffer(Int32 count, Int32& offset)
at System.Xml.XmlUTF8NodeWriter.InternalWriteBase64Text(Byte[] buffer, Int32 offset, Int32 count)
at System.Xml.XmlBaseWriter.WriteBase64(Byte[] buffer, Int32 offset, Int32 count)
at System.Xml.XmlDictionaryWriter.WriteValue(IStreamProvider value)
at System.ServiceModel.Dispatcher.StreamFormatter.Serialize(XmlDictionaryWriter writer, Object[] parameters, Object returnValue)
at System.ServiceModel.Dispatcher.OperationFormatter.OperationFormatterMessage.OperationFormatterBodyWriter.OnWriteBodyContents(XmlDictionaryWriter writer)
at System.ServiceModel.Channels.Message.OnWriteMessage(XmlDictionaryWriter writer)
at System.ServiceModel.Channels.TextMessageEncoderFactory.TextMessageEncoder.WriteMessage(Message message, Stream stream)
at System.ServiceModel.Channels.HttpOutput.WriteStreamedMessage(TimeSpan timeout)
at System.ServiceModel.Channels.HttpOutput.Send(TimeSpan timeout)
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.SendRequest(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.RequestChannel.Request(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)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at WcfService.IStreamingService.SendStream(MyStreamUpRequest request)
at Client.Program.<Main>b__0() in c:\Users\jpierson\Documents\Visual Studio 2012\Projects\WcfStreamingTest\Client\Program.cs:line 44
at System.Threading.Tasks.Task.Execute()
InnerException: System.IO.IOException
HResult=-2146232800
Message=Unable to write data to the transport connection: An existing connection was forcibly closed by the remote host.
Source=System
StackTrace:
at System.Net.Sockets.NetworkStream.MultipleWrite(BufferOffsetSize[] buffers)
at System.Net.ConnectStream.InternalWrite(Boolean async, Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
at System.Net.ConnectStream.Write(Byte[] buffer, Int32 offset, Int32 size)
at System.ServiceModel.Channels.BytesReadPositionStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at System.ServiceModel.Channels.HttpOutput.WebRequestHttpOutput.WebRequestOutputStream.Write(Byte[] buffer, Int32 offset, Int32 count)
InnerException: System.Net.Sockets.SocketException
HResult=-2147467259
Message=An existing connection was forcibly closed by the remote host
Source=System
ErrorCode=10054
NativeErrorCode=10054
StackTrace:
at System.Net.Sockets.Socket.MultipleSend(BufferOffsetSize[] buffers, SocketFlags socketFlags)
at System.Net.Sockets.NetworkStream.MultipleWrite(BufferOffsetSize[] buffers)
InnerException:
Il semble que le serveur a fermé la connexion prématurément en raison de l'inactivité de la connexion. Si j'ai la place donner une impulsion sur le serveur, même un octet à la fois, alors je n'obtiens jamais de cette exception et je peux continuer à transférer des données indéfiniment. J'ai construit un exemple très simple de l'application de démontrer ce qui utilise basicHttpBinding avec Streaming transferMode et j'ai insérer un délai artificiel à partir de l'intérieur d'un flux personnalisé de mise en œuvre sur le client que les délais pour 130 secondes. Cela simule quelque chose de semblable à un dépassement de mémoire tampon condition dans laquelle le flux fourni dans mon appel de service du client n'est pas de nourrir les données de la FMC de l'infrastructure assez rapide pour satisfaire une sorte de non identifiables valeur de délai d'expiration qui semble être d'environ 130 deuxième marque.
En utilisant le service WCF des outils de suivi, je suis en mesure de trouver un HttpException avec un message qui dit "Le client est déconnecté en raison de la demande sous-jacente a été achevé. Il n'est plus une HttpContext disponible."
De l'IIS Express fichier journal de suivi, je vois une entrée qui dit que "L'opération d'e/S a été annulée en raison d'une sortie de thread ou à la demande d'une application. (0x800703e3)"
J'ai configuré à la fois serveur et client délais d'attente pour utiliser une valeur de plus de 130 deuxième marque juste à la règle. J'ai essayé idleTimeout dans IIS Express et une foule de ASP.NET liés valeurs de délai d'attente trop afin de découvrir d'où ce problème vient de mais jusqu'à présent aucune chance. La meilleure information que je peux trouver à ce jour est une commentaire dans FireFox bug tracker par un développeur qui décrit un problème similaire de travailler à l'extérieur de la FMC de l'architecture. Pour cette raison, je suppose que le problème est peut-être plus spécifiquement lié à IIS7 ou, éventuellement, de Windows Server.
Liaison personnalisée sur le serveur Web.config
<binding name="myHttpBindingConfiguration"
closeTimeout="02:00:00"
openTimeout="02:00:00"
receiveTimeout="02:00:00"
sendTimeout="02:00:00">
<textMessageEncoding messageVersion="Soap11" />
<httpTransport maxBufferSize="65536"
maxReceivedMessageSize="2147483647"
maxBufferPoolSize="2147483647"
transferMode="Streamed" />
</binding>
Côté Client configuration dans le code:
var binding = new BasicHttpBinding();
binding.MaxReceivedMessageSize = _maxReceivedMessageSize;
binding.MaxBufferSize = 65536;
binding.ReaderQuotas.MaxStringContentLength = int.MaxValue;
binding.ReaderQuotas.MaxArrayLength = int.MaxValue;
binding.TransferMode = TransferMode.Streamed;
binding.ReceiveTimeout = TimeSpan.FromDays(1);
binding.OpenTimeout = TimeSpan.FromDays(1);
binding.SendTimeout = TimeSpan.FromDays(1);
binding.CloseTimeout = TimeSpan.FromDays(1);
En réponse à wals idée d'essayer de voir si j'obtiens des résultats différents par l'auto-hébergement de mon service, j'ai envie d'ajouter que je l'ai fait et constaté que j'obtiens les mêmes résultats que lors de l'hébergement dans IIS. Qu'est-ce que cela signifie? Je suppose que cela signifie que le problème est soit dans WCF ou dans le sous-jacent de l'infrastructure de réseau dans Windows. Je suis sous Windows 7 64 bits, et nous avons découvert ce problème en exécutant divers clients et l'exécution de la partie sur un Serveur Windows 2008.
Mise à jour 2013-01-15
J'ai trouvé quelques nouveaux indices grâce à DarkWanderer une fois que j'ai réalisé que WCF utilise HTTP.sys en dessous de l'auto-hébergement scénarios sur Windows 7. Cela m'a regarder dans ce que j'ai pu configurer pour HTTP.sys et aussi quel type de problèmes que les gens sont des rapports que pour HTTP.sys que son semblable à ce que je suis en train de vivre. Cela me conduirait à un fichier journal situé à C:\Windows\System32\LogFiles\HTTPERR\httperr1.log qui apparaît à certains types de HTTP sur les problèmes de HTTP.sys. Dans ce journal, je vois le type d'entrée de journal chaque fois que je lance mon test.
2013-01-15 17:17:12 127.0.0.1 59111 127.0.0.1 52733 HTTP/1.1 POST
/StreamingService.svc - - Timer_EntityBody -
Donc, c'est vers le bas pour trouver quelles conditions pourrait causer un Timer_EntityBody erreur et quels sont les paramètres dans IIS7 ou ailleurs peuvent avoir une incidence sur le moment et si cette erreur se produit.
De la officiel site web IIS:
La connexion a expiré avant que la demande de l'entité arrivée du corps. Quand il
est clair qu'une demande a un corps d'entité, l'API HTTP de tours sur le
Timer_EntityBody de la minuterie. D'abord, la limite de ce que la minuterie est réglée à
la valeur connectionTimeout. Chaque fois qu'un autre indication de données
reçu sur cette demande, l'API HTTP réinitialise la minuterie pour donner l'
connexion de plusieurs minutes, comme spécifié dans le connectionTimeout
attribut.
Essayer de modifier le connectionTimeout attribut comme la référence ci-dessus suggère pour en applicationhost.config pour IIS Express ne semblent pas faire la différence. Peut-être IIS Express ignore cette configuration et utilise une valeur codée en dur interne? Essayer quelque chose sur mon propre j'ai découvert qu'il y a de nouvelles commandes netsh http ajouté pour afficher et ajouter des valeurs de délai d'attente, si généreux que je vais je suis venu avec la commande suivante, mais malheureusement, le faire ne semble pas avoir d'effet sur cette erreur.
netsh http ajoutez délai timeouttype=IdleConnectionTimeout valeur=300
source d'informationauteur jpierson
Vous devez vous connecter pour publier un commentaire.
Il s'avère que ce problème a été causé par le Délai D'Attente De Connexion valeur utilisée par HTTP.sys et qui peuvent être spécifiées par le Gestionnaire des services internet à travers les Paramètres Avancés de chaque site. Cette valeur est configurée par défaut en attente d'une connexion lorsque l'en-tête et le corps n'ont pas été reçus dans un délai de 120 secondes. Si une impulsion de données de l'organisme est reçu, le serveur redémarre un timer (Timer_EntityBody) au sein de la valeur de délai d'expiration, puis la minuterie est remise à zéro à attendre pour des données supplémentaires.
C'est juste que la documentation concernant Timer_EntityBody et connectionTimeout précise toutefois qu'il était difficile à cerner, car il semble que IIS Express ignore le connectionTimeout valeur spécifiée dans les limites de l'élément dans applicationhost.config indépendamment de ce que dit la documentation. Pour le déterminer, j'ai dû installer la version complète de IIS sur ma machine de développement et de modifier le paramètre ci-dessus après l'hébergement de mon site.
Puisque nous sommes hébergeant le service réel sous IIS sur Windows 2008, la solution ci-dessus va travailler pour moi, cependant, la question demeure sur la manière de modifier le Délai de Connexion dans le cas où vous êtes Auto-Hébergement.
À en juger par l'erreur:
Il semble que ce soit un simple timeout TCP.
Vous pouvez le vérifier en exécution de l'application en auto-hébergé, puis en exécutant cette commande dans la console:
où xxxxx est le PID de votre processus de serveur. Cette commande va vous montrer les connexions à votre serveur a mis en place et actualiser à chaque seconde.
Essayez de vous connecter avec le client et de voir ce qui se passe. Très probablement, vous allez voir "CLOSE_WAIT" ou "TIME_WAIT" sur votre connexion après environ 100 à 120 secondes - ce qui signifie qu'il a été abandonné en raison de délai d'attente.
Ce doit être résolu en ajoutant les lignes suivantes à votre configuration:
Le paramètre est expliqué ici
Probablement long shot, mais... Vérifier votre pool d'applications IIS si il a Ping activé. C'est dans les paramètres avancés, Modèle de Processus de regroupement.
Essayer ça, pour moi ça a résolu le problème. Le problème est que le noyau sous-jacent http.sys dispose d'un délai d'attente et il va rompre la connexion.
Avez-vous pensé à http://support.microsoft.com/kb/946086 ?
J'ai observé ce genre de streaming interruptions dans mon ISAPI-Extensions. Après l'arrêt de
mise en mémoire tampon dans IIS 7 selon ce soutien la note, tout a fonctionné à une amende.