76 votes

HttpWebRequest est extrêmement lent!

Je suis en utilisant une bibliothèque open source pour se connecter à mon serveur. Je craignais que le serveur allait extrêmement lent et puis j'ai essayé de faire un simple test en Ruby et j'ai eu ces résultats

Ruby programme: 2.11 secondes pour 10 HTTP Obtient

Ruby programme: 18.13 secondes pour 100 HTTP Obtient

C# bibliothèque: 20.81 secondes pour 10 HTTP Obtient

C# bibliothèque: 36847.46 secondes pour 100 HTTP Obtient

J'ai profilé et a trouvé le problème à cette fonction:

private HttpWebResponse GetRawResponse(HttpWebRequest request) {
  HttpWebResponse raw = null;
  try {
    raw = (HttpWebResponse)request.GetResponse(); //This line!
  }
  catch (WebException ex) {
    if (ex.Response is HttpWebResponse) {
      raw = ex.Response as HttpWebResponse;
    }
  }
  return raw;
}

La ligne est prend plus de 1 seconde à s'exécuter par elle-même tandis que le rubis programme 1 demande prend de 3 secondes. Je suis également de faire tous ces tests sur 127.0.0.1, de sorte que la bande passante du réseau n'est pas un problème.

Ce qui pourrait être la cause de cette énorme ralentir?

Mise à JOUR

Découvrez la changé résultats de référence. J'ai effectivement testé avec 10 se et pas 100, j'ai mis à jour les résultats.

177voto

James Roland Points 2582

Ce que j’ai trouvé être le principal responsable des demandes Web lentes est la propriété de proxy. Si vous définissez cette propriété sur null avant d'appeler la méthode GetResponse, la requête ignorera l'étape de détection automatique du proxy:

 request.Proxy = null;
using (var response = (HttpWebResponse)request.GetResponse())
{
}
 

La détection automatique du proxy demandait jusqu'à 7 secondes avant de renvoyer la réponse. Il est un peu gênant que cette propriété soit définie par défaut pour l'objet HttpWebRequest.

23voto

Manu Points 10901

Cela peut avoir à voir avec le fait que vous ouvrez plusieurs connexions à la fois. Par défaut, le nombre maximal de connexions HTTP ouvertes est défini sur deux. Essayez d'ajouter ceci à votre fichier .config et voyez si cela aide:

 <system.net>
  .......
  <connectionManagement>
    <add address="*" maxconnection="20"/>
  </connectionManagement>
</system.net>
 

11voto

jamieb Points 31

J'ai eu un problème similaire avec un VB.Net projet MVC.
En local sur mon pc (Windows 7), il prenait moins de 1 seconde à frapper les demandes de page, mais sur le serveur (Windows Server 2008 R2), c'était de prendre+ de 20 secondes pour chaque demande de page.

J'ai essayé une combinaison de réglage de la procuration à null

  System.Net.WebRequest.DefaultWebProxy = Nothing
  request.Proxy = System.Net.WebRequest.DefaultWebProxy

Et en modifiant le fichier de configuration en ajoutant

 <system.net>
   .......
   <connectionManagement>
     <add address="*" maxconnection="20"/>
   </connectionManagement>
 </system.net>

Ce n'est toujours pas réduire la lenteur de la page de demande de temps sur le serveur. En fin de compte la solution a été de décocher la case "détecter Automatiquement les paramètres" option dans l'IE options sur le serveur lui-même. (Sous Outils -> Options Internet, sélectionnez l'onglet Connexions. Appuyez sur le bouton Paramètres LAN)

Immédiatement après j'ai décoché cette option du navigateur sur le serveur, la page de demande de fois a chuté de plus de 20 secondes à moins de 1 seconde.

10voto

tonycoupland Points 1614

J'ai commencé à observer un ralentissement similaire à l'OP dans ce domaine, ce qui était un peu mieux lors de l'augmentation de la MaxConnections.

ServicePointManager.DefaultConnectionLimit = 4;

Mais après la construction de ce nombre de WebRequests les retards revint.

Le problème, dans mon cas, c'est que j'étais en appelant un POST et pas dérangé au sujet de la réponse, afin de ne pas prendre ou de faire quelque chose avec elle. Malheureusement, cette gauche de la WebRequest flottant autour jusqu'à ce qu'ils expiré.

La solution était de ramasser la Réponse et juste la fermer.

WebRequest webRequest = WebRequest.Create(sURL);
webRequest.Method = "POST";
webRequest.ContentLength = byteDataGZ.Length;
webRequest.Proxy = null;
using (var requestStream = webRequest.GetRequestStream())
{
    requestStream.WriteTimeout = 500;
    requestStream.Write(byteDataGZ, 0, byteDataGZ.Length);
    requestStream.Close();
}
// Get the response so that we don't leave this request hanging around
WebResponse response = webRequest.GetResponse();
response.Close();

3voto

kervin Points 7620

Utilisez un ordinateur autre que localhost , puis utilisez WireShark pour voir ce qui se passe réellement sur le réseau.

Comme d'autres l'ont dit, cela peut être un certain nombre de choses. Regarder les choses au niveau TCP devrait donner une image claire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X