2010-10-11 15 views
6

Tengo una aplicación que araña sitios web para obtener información. Parece que después de 20-45 minutos de crear HttpWebRequests, un grupo de ellos devuelve los tiempos de espera. Una cosa que hacemos es adjuntar una función anónima de BindIPDelegate para darle a la solicitud una dirección IP específica, ya que hacemos robin a través de aproximadamente 150 direcciones IP.Después de hacer HttpWebRequests por un tiempo, el resultado comienza el tiempo de espera

Soy la creación del objeto HttpWebRequest con los siguientes valores ..

  • Configuración User-Agent
  • Configuración Keep-Alive en false para que no se vuelve a utilizar el IP
  • Ajuste de tiempo de espera a 60000 (60 segundos)
  • Marco ReadWriteTimeout a 60.000 (60 segundos)
  • ajuste de proxy a null
  • Setti ng Aceptar para /
  • Configuración CookieContainer de nuevo CookieContainer
  • Configuración Piplined a cierto
  • Ajuste automático de descompresión para desinflar & GZIP

La aplicación está utilizando .NET 4.0 y se ejecuta en Windows Server 2008 R2.

Esto definitivamente parece algo relacionado con la aplicación/TCP/.NET porque si reinicio la aplicación, corre bien de nuevo. También parece más o menos como que los tiempos de espera se colapsan esperando en un puerto local o algo así.

¿Alguna idea?

+0

¿Estás haciendo una llamada de llamada asincrónica o esperando una llamada? – WeNeedAnswers

+0

Llamadas de bloqueo síncronas. –

+0

prueba las llamadas de regreso asincrónicas. Puede que no resuelva su problema pero solucionan el dolor de cabeza de los hilos al usar httpWebRequest. Diría que tiene algo que ver con el grupo de temas, pero sin mirar tu código no podría decirlo con certeza. Nunca duele hacer llamadas de retorno asincrónicas en lugar de disparar hilos. ¿Estás usando el grupo de temas? – WeNeedAnswers

Respuesta

6

Usted no dice mucho sobre el código que realmente se utilicen para realizar las peticiones, pero, de todos modos, aquí están mis conjeturas:

  1. está usando el BeginGetResponse()/EndGetResponse() con una devolución de llamada y la devolución de llamada tarda demasiado tiempo en completo (o bloques!). Esto podría provocar un punto muerto en el grupo de temas si está emitiendo muchas solicitudes en un corto período de tiempo.

  2. Dado que no está reutilizando las conexiones y, de nuevo, si las solicitudes suceden muy rápido y sin parar, es posible que se quede sin enchufes (la última vez que lo intenté, ~ 3k por interfaz en Windows). Si configurar KeepAlive en true soluciona su problema, esto es todo.

  3. No está llamando al Dispose()/Close() en HttpWebRequest o HttpWebResponse o Stream que obtiene de la respuesta. Esto podría funcionar un poco hasta que llegue al límite de 2 (de los documentos de MSDN) o 6 (valor predeterminado del archivo de configuración) en la configuración de la aplicación para el sistema ().net/connectionManagement/add [dirección = "*", maxconnection = "6"]). Una manera simple de probar si este es el problema es establecer el límite en 1 y ver si el problema ocurre antes que antes.

Por cierto, el establecimiento de KeepAlive false y En tubería a cierto no tiene sentido.

+0

La manera fácil de diagnosticar el agotamiento del puerto sería con 'netstat'. –

+0

@Steven: sí, en Linux haría algo así como "netstat -nt". Si hay una gran cantidad de CLOSE_WAIT, sería el caso 3 anterior. Si hay un montón de TIME_WAIT, sería el caso 2 anterior. Aumentar 'ulimit -n' ayudaría al caso 2, pero el caso 3 es un problema de aplicación. – Gonzalo

+0

Windows tiene una versión portada de esa herramienta de línea de comandos de Unix integrada. Sin embargo, si bien hay un par de entradas de registro que se pueden usar para ajustar los límites del puerto, la respuesta correcta es arreglar el código para que reutilice los puertos. –

0

¿Podría ser un IDS en el extremo remoto pensando que eres un atacante y te está bloqueando?

+0

¿No me seguiría bloqueando? Parece que sucede durante un breve intervalo y luego desaparece. –

+0

Depende de la configuración: puede configurar cuánto tiempo desea bloquear un ataque percibido – arootbeer

+0

¿Puede ejecutar diagnósticos en su servidor, por ejemplo, TCPView, ver qué está interrumpiendo la conexión, etc.? –

1

Supongo que se debe a problemas relacionados con ThreadPool.

0

Supongo que quizás no todos los objetos se desechan correctamente y algunos puertos TCP se mantienen abiertos. Intenta ver qué objetos implementan IDisposable. Al menos el resultado de GetResponse y GetResponseStream son identificables y deben eliminarse correctamente.

+0

Todo lo que es IDisposable está envuelto en una declaración using. –

0

más fácil de mostrar un ejemplo de lo que quise decir en los comentarios, no es mi propio trabajo, pero los chicos de microsoft hacen un trabajo tan agradable que les paso el enlace.

http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.begingetrequeststream.aspx

Si su hacer de entrada y salida a través de http pesada, siempre sugeriría en el estudio de los mecanismos de devolución de llamada.

También cerciórese de cerrar esos malditos objetos httpWebRequest. Envuelva todo en plástico de plástico con burbujas utilizando las declaraciones de "uso" generosamente.

operaciones de subprocesos múltiples: hay una configuración predeterminada de 2 conexiones por conexión de host.
Esa configuración se puede cambiar. Si se usa la cantidad máxima de conexiones, entonces las operaciones HttpWebRequest (solicitud/respuesta) se pondrán en cola hasta que esté disponible una ranura de conexión.

un artículo me encontré con los pasajes concernientes a servicios web también podría afectar a su problema, ya que las causas son muy similares, aquí hay un enlace:

http://support.microsoft.com/kb/821268

0

Trate de añadir lo siguiente a su app.config, por debajo de la etiqueta de configuración. Creo que esto resuelve un problema similar que tenía cuando se hace una gran cantidad de conexiones HTTP en repetidas ocasiones:

<system.net> 
    <defaultProxy enabled="false"> 
    </defaultProxy> 
    <connectionManagement> 
     <remove address="*"/> 
     <add address="*" maxconnection="1000" /> 
    </connectionManagement> 
    </system.net> 

Editar: Creo que el defaultProxy -tag era la etiqueta muy, muy importante.

Cuestiones relacionadas