2017-02-15 1 views
2

Le 17 janvier 09:32, un de nos services a soudainement lancé 500 erreurs. C'est un service d'adaptateur à un service tiers et nous utilisons un HttpClient pour faire un POST (Nous faisons un GET à notre service avec des paramètres de chaîne de requête et nous transférons cela à l'application tierce en utilisant un POST et des paramètres dans le corps). Quand je poste manuellement au service de tiers en utilisant un postier ou une boucle, il a bien répondu. Donc c'était un problème avec notre service. C'est le service .NET qui utilise le middleware OWIN, semblable à la façon dont je travaille. Le problème était qu'il y a quelque temps, le framework .NET a été mis à niveau de 4.5.2 à 4.6 et quand il le fait en VS, il ajoute un élément <httpRuntime targetFramework="4.5.2"/> au web.config. Il s'agit de faire un effort pour préserver le comportement existant de l'application au cas où il y aurait des changements de rupture entre les versions du framework. La personne qui a mis à jour n'a pas réalisé et laissé dans l'élément dans le web.config. Il a bien fonctionné pendant des siècles, puis soudainement dans tous les environnements en même temps (y compris localement) s'est brisé. Je pensais que ça devait être quelque chose de temporel dans le framework .NET mais rouler l'horloge de mon système ne le résout pas! Que puis-je rechercher, des idées sur ce mystère? Il suffit de faire passer le web.config à 4.6 pour le corriger, mais j'ai été chargé de l'étudier.Le service lance soudainement SocketException sans modifications apparentes

Voici l'erreur sous-jacente:

System.Net.Sockets.SocketException (0x80004005): An existing connection was forcibly closed by the remote host 
    at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult) 
    at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult) 

et c'est le code, il jette à _client.PostAsync avec ce qui précède que le InnerException. _client est un System.Net.Http.HttpClient

public async Task<CalculateResponse> Calculate(CalculateRequest request) 
{ 
    var env = new RequestEnvelope { Body = { RblsCalculate = request } }; 
    request.LoginId = _username; 
    request.Password = _password; 

    var body = XmlConvert.SerializeObject(env); 

    var content = new StringContent(body, Encoding.UTF8, "application/soap+xml"); 
    var httpResponse = await _client.PostAsync(_endpointPath, content); 

    var response = XmlConvert.ToObject<ResponseEnvelope>(await httpResponse.Content.ReadAsStreamAsync()); 

    return response?.Body?.RblsCalculateResponse; 
} 

Le tiers n'a pas fait de changements, des mises à jour de Windows n'a pas couru (cela effectué simultanément 5 environnements différents). Nous n'avons fait aucun changement. Lorsque nous déployons, nous déployons à une nouvelle instance à chaque fois, le web.config n'a pas changé sur les serveurs et le déploiement précédent était des semaines auparavant.

J'ai passé en revue certaines des modifications à 4.6 et il y a quelques changements potentiellement cassants autour de HttpClient si n'utilisant pas TLSv1.0 + comme protocole, j'ai vérifié using Wireshark sur un des serveurs et nous employons TLSv1.2 . Mais cela n'explique pas pourquoi il s'est soudainement arrêté.

Mise à jour - Sortie de trace.log pour le traçage SSL/TLS selon la suggestion @Trumpi

System.Net.Sockets Verbose: 0 : [16292] Data from Socket#52088480::PostCompletion 
System.Net.Sockets Verbose: 0 : [16292] 00000000 : 16 03 01 00 88 01 00 00-84 03 01 58 A4 49 35 01 : ...........X.I5. 

Mise à jour 2 - Suppression des journaux inutiles ^^

+0

_ « Quand je poste au service tiers manuellement à l'aide ou postier boucle, il a répondu très bien. Il avait un problème avec notre service [...] Le tiers n'a apporté aucune modification » _ - La chose qui diffère est le moment où la demande a été exécutée. Peut-être que le service de tiers était surchargé en ce moment, dans un processus de mise à niveau ou autre. Si l'exécution de .NET 4.5.2 donne systématiquement cette erreur et pas de .NET 4.6, alors allez inspecter les différences entre les en-têtes HTTP entre les deux. – CodeCaster

+0

"fermé de force par l'hôte distant" est le débogage du problème de la mauvaise extrémité de la socket. Ne laisse pas deviner pourquoi l'autre extrémité a décidé d'abandonner. Suivez le fil. –

+0

@HansPassant l'autre extrémité de la socket est une application tierce dont je n'ai pas accès. J'ai contacté leur équipe de support et ils m'ont dit qu'ils ne voyaient aucune demande arriver. – Rodders

Répondre

1

Fait intéressant, j'ai rencontré un problème très similaire la semaine dernière (même si ce n'était pas avec .NET Core). J'avais appelé un point de terminaison API pendant des mois via un travail quotidien et tout à coup, je recevais la même erreur. Il m'a fallu plusieurs jours pour trouver un correctif, mais pour moi, l'ajout de la ligne de code suivante a corrigé le problème. Vous pourriez probablement l'ajouter à la première ligne de votre méthode.

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; 
+0

Très bien! Cela résout le problème même avec mon httpRuntime toujours réglé sur 4.5.2. C'est vraiment utile, merci. Cela n'explique pas pourquoi il s'est arrêté soudainement mais c'est un réel progrès. Peut-être que nous utilisions Tls1.2 et que quelque chose le faisait revenir à 1.0 – Rodders

+0

Ou en y réfléchissant, il est plus probable que je pense que nous utilisions toujours 1.0 et que la 3ème partie a fait des changements qui ont fait chuter le support. – Rodders

+0

J'ai ressenti la même chose. J'ai passé tellement de temps à essayer de comprendre pourquoi c'est arrivé, mais après un moment, j'ai décidé d'être heureux que j'ai trouvé une solution. Si vous comprenez ce qui a causé le problème, s'il vous plaît faites le moi savoir. – MDiesel

1

Mon premier instinct est que C'est un problème avec l'établissement de liaison TLS et le fait que le service tiers abandonne la connexion parce qu'il n'a pas réussi à établir une liaison. La version de TLS pourrait être un problème, comme vous l'avez noté. Ne pas être capable de trouver un chiffrement compatible pourrait être un autre problème.

Je suis tombé sur this blog post qui décrit comment écrire les informations de prise de contact sur le fichier de trace. Voici la section qu'il ajoute au fichier web.config:

<system.diagnostics> <trace autoflush="true"/> <sources> <source name="System.Net" maxdatasize="1024"> <listeners> <add name="TraceFile"/> </listeners> </source> <source name="System.Net.Sockets" maxdatasize="1024"> <listeners> <add name="TraceFile"/> </listeners> </source> </sources> <sharedListeners> <add name="TraceFile" type="System.Diagnostics.TextWriterTraceListener" initializeData="trace.log"/> </sharedListeners> <switches> <add name="System.Net" value="Verbose" /> <add name="System.Net.Sockets" value="Verbose" /> </switches> </system.diagnostics>

C'est le meilleur que je peux faire avec les informations contenues dans la question et j'espère que cela aide.

EDIT: Après la publication des résultats, il semble que l'appel tente de négocier une connexion TLS 1.0, que le serveur ne prend plus en charge. J'ai mis les détails dans un commentaire ci-dessous.

+1

Belle trouvaille, je mettrai à jour mon post avec la sortie. Merci – Rodders

+0

Dans le bloc d'octets après 'Data from Socket # 52088480 :: PostCompletion', le premier octet est le type de contenu (' 0x16') qui est la poignée de main. Les deux octets suivants sont la version ('0x03' et' 0x01'), qui est TLS 1.0. TLS 1.2 envoie '0x03' et' 0x03'. Source [RFC 5246 - TLS 1.2] (https://tools.ietf.org/html/rfc5246) et [RFC 2246 - TLS 1.0] (https://www.ietf.org/rfc/rfc2246.txt) – Trumpi

+0

I voir. Nous utilisons donc TLS1.0. En outre, si je corrige ce problème en mettant à niveau le targetFramework à 4.6, la demande fonctionne mais je n'obtiens aucun journal dans ce fichier de trace. Est-il possible que nous utilisions TLS1.2 et que quelque chose l'ait fait revenir à 1.0? – Rodders