2011-07-27 10 views
6

Estoy extrayendo datos JSON de varios servidores remotos simultáneamente a través de HTTP, utilizando un servicio WCF en los puntos finales del cliente y del servidor. Me doy cuenta de que, por cada solicitud sucesiva que comienza de forma asíncrona, el tiempo que tarda la solicitud http generalmente aumenta, incluso si la cantidad de datos no aumenta necesariamente. En otras palabras, si comienzo a 12 hilos de rosca de la piscina (con la tecla FUNC <> .BeginInvoke), entonces cada solicitud, después de haber sido programada, está apareciendo en mis registros, tales como:Descarga simultánea de datos JSON desde servicio (s) remoto

:HttpRequest invoked. Elapsed: 325ms 
    :HttpRequest invoked. Elapsed: 27437ms 
    :HttpRequest invoked. Elapsed: 28642ms 
    :HttpRequest invoked. Elapsed: 28496ms 
    :HttpRequest invoked. Elapsed: 32544ms 
    :HttpRequest invoked. Elapsed: 38073ms 
    :HttpRequest invoked. Elapsed: 41231ms 
    :HttpRequest invoked. Elapsed: 47914ms 
    :HttpRequest invoked. Elapsed: 45570ms 
    :HttpRequest invoked. Elapsed: 61602ms 
    :HttpRequest invoked. Elapsed: 53567ms 
    :HttpRequest invoked. Elapsed: 79081ms 

El proceso es bastante simple. Simplemente estoy comenzando cada solicitud en un bucle y luego llamo a .WaitAll() en todas las operaciones antes de usar los datos consolidados.

Parece que las solicitudes Http están llevando más tiempo de lo que deberían, incluso con pequeñas cantidades de datos. De hecho, la diferencia entre pequeñas y grandes cantidades de datos parece mínima en general. ¿Este tipo de cuello de botella se debe a solicitudes simultáneas de http que tienen que compartir ancho de banda, o hay un problema de subprocesamiento/cambio de contexto posible aquí? Solo mirando para ser apuntado en la dirección correcta.

EDITAR - Sólo para mayor claridad, me encontré con el mismo proceso sincrónicamente y aquí están los resultados:

:HttpRequest invoked. Elapsed: 20627ms 
    :HttpRequest invoked. Elapsed: 16288ms 
    :HttpRequest invoked. Elapsed: 2273ms 
    :HttpRequest invoked. Elapsed: 4578ms 
    :HttpRequest invoked. Elapsed: 1920ms 
    :HttpRequest invoked. Elapsed: 564ms 
    :HttpRequest invoked. Elapsed: 1210ms 
    :HttpRequest invoked. Elapsed: 274ms 
    :HttpRequest invoked. Elapsed: 145ms 
    :HttpRequest invoked. Elapsed: 21447ms 
    :HttpRequest invoked. Elapsed: 27001ms 
    :HttpRequest invoked. Elapsed: 1957ms 

El tiempo total (debido a que su síncrono) subió, sin embargo se puede ver claramente que cada solicitud individual es generalmente más rápida. Lamentablemente, no conozco ninguna forma de aislar el problema, pero creo que es un problema de intercambio de ancho de banda entre los hilos.

Así que alguna pregunta más sencilla que tengo es:

1) Si utilizo un subproceso no subprocesos, sería esta mejora

2) ¿Debo agrupar las operaciones en sólo unos pocos hilos, en lugar que cada solicitud tiene la suya?

3) ¿Es este un problema estándar cuando se intenta descargar datos simultáneamente a través de Http?

+0

En realidad, también estoy lidiando con algo del mismo problema con múltiples httpRequests concurrentes. Si envío 50 solicitudes al mismo tiempo, la primera vuelve en 300 ms, y la última vuelve después de 2000 ms. Sus resultados parecen indicar que hay algo más que está sucediendo. En su prueba síncrona, la primera solicitud volvió después de los 20? Tal vez esto es más un problema en el lado del servidor, ¿qué tipo de servicio es esta llamada? –

+0

@Mike Richard, mira mi enlace en la respuesta que publiqué, debería ayudarte. –

Respuesta

0

La mejor respuesta a esta pregunta que en última instancia se acercó con vino de este enlace:

http://blogs.msdn.com/b/wenlong/archive/2010/02/11/why-are-wcf-responses-slow-and-setminthreads-does-not-work.aspx

que se aplica si está llamando el mismo método mas el servicio en varias ocasiones.

Al ajustar ThreadPool.SetMinThreads() en el cliente y el servidor pude obtener mejores resultados.

Sin embargo, todavía hay muchos problemas de lentitud con WCF y la transferencia a través de HTTP que realmente no he llegado al fondo de.

2

Según la pregunta this hay una configuración que controla cuántas solicitudes HTTP simultáneas se pueden realizar. Además, debe utilizar el método BeginGetResponse en HttpWebRequest para la descarga simultánea, ya que es menos costoso que la creación de subprocesos. Mire here para ver ejemplos.

+0

Gracias. ¿La configuración de solicitud HTTP simultánea es para el servidor o el cliente, o para ambos? Además, en realidad estoy usando ChannelFactory para llamar al servicio WCF, llamando el método por el nombre del contrato de servicio. –

+0

La configuración debe cambiarse en la aplicación que está realizando la descarga. – eulerfx

+0

¿Esa configuración solo se aplicaría si utilicé HttpWebRequest, o debería funcionar con una llamada a la fábrica de ChannelFactory de WCF? Debería investigar si existe una configuración equivalente para los clientes de Wcf. –

2

Puede estar relacionado con el modo de concurrencia de su servicio. Verifique http://msdn.microsoft.com/en-us/library/system.servicemodel.concurrencymode.aspx y asegúrese de que el servicio no tenga un solo hilo.

+0

Esto no parece ayudar. Creo que esto es un problema de enhebrado en el cliente, aunque no estoy seguro. –

+0

ThreadPool administrará el número de subprocesos por sí mismo; no hay mucha garantía de que tenga 12 subprocesos simultáneos a menos que modifique SetMaxThreads/SetMinThreads. En segundo lugar, vería qué está haciendo realmente el servicio (servidor) - tal vez haya algún tipo de contención de bloqueo (como accesos DB/acceso de escritura al mismo archivo, etc.) – bkdc

+0

Diría que este comportamiento es Sin embargo, se espera que, dado que en el cliente, un montón de descargas simultáneas tendrán que compartir ancho de banda. Es decir, si estoy alcanzando 900kb/s cuando realizo una única descarga, podría perder velocidad por cada descarga simultánea que agregue además de eso. Si ese es el caso, pensaría que hay poco que puedo hacer. –

Cuestiones relacionadas