2012-05-23 7 views
5

Tengo una situación bastante extraña.Comportamiento extraño con uri y clases WebClient en el paquete SSIS

tengo este paquete muy simple:

enter image description here

  • tarea "obtener la lista" recupera una tabla de datos de un conjunto con uno columna y una lista de URL que se corrió en una variable de objeto .
  • El "foreach" bucle de bucle a través de la variable de objeto y carga el URL en una cadena URL variable de
  • La "marcha", llama a la URL con el código (el 2005 así que estoy atascado con VB):

    Dim myURI As New Uri("http://" + Dts.Variables("URL").Value.ToString()) 
    Dim myWebClient As New System.Net.WebClient 
    myWebClient.OpenReadAsync(myURI) 
    

la URL que se llama es interno y simplemente lee los parámetros y realiza una serie de operación que llevará algún tiempo, es por eso que he usado "OpenReadAsync"

Mi problema es: si tengo 4 URL para ejecutar, el paquete solo ejecuta 2 de ellas. El ciclo 4 veces, el script se llama 4 veces (puedo ver si lo depuro), la línea myWebClient.OpenReadAsync(myURI) se ejecuta 4 veces con 4 valores diferentes, pero solo se hacen 2 llamadas a la URL.

Si ejecuto el paquete de nuevo, ahora se llaman las otras 2 URL, lo que demuestra que no hay nada mal con la URL y si llamo las 4 urls manualmente en el navegador (en 4 pestañas, por ejemplo) enseguida, todos producen el resultado esperado, lo que prueba que no hay nada de malo en el código que analiza la URL.

Así que me quedé con el código VB, es la primera vez que estoy usando uri y WebClient, así que me pregunto si estoy haciendo algo mal. También traté de agregar un sueño de 5 segundos entre las llamadas, pero no tuve suerte.

Cualquier ayuda sería apreciada. Gracias

+0

Lo que si se cambia a usando el método sincrónico OpenRead? – billinkc

+0

¡Hola billinkc! Obtengo un tiempo de espera luego de la segunda ejecución. Es extraño porque las 4 URL que tengo deben ejecutarse en unos pocos segundos, de hecho puedo ver (tengo un registro) que el segundo ejecutó 5 segundos después del primero. Y si ejecuto el paquete la segunda vez, las 2 URL restantes funcionan bien, así que definitivamente es algo así como llamar al código más de 2 veces – Diego

+0

Cada vez que me encuentro con problemas de código "extraños" en SSIS, vuelco el código a una aplicación de consola .NET y ver si puedo reproducir el comportamiento allí. Supongo que ya lo has intentado, pero en caso de que no lo hayas hecho, ese podría ser un lugar para volverte ya que no ha habido mucho amor por tu generosidad. Además, ¿cómo se ve tu código completo? ¿Hay alguna posibilidad de que se llamen las 4 URL, pero como son llamadas asincrónicas, simplemente no observas los efectos hasta más adelante? ¿Qué pasa si pone un hilo más largo. Duerma allí, algo que coincida con la duración esperada del proceso? Derrota el propósito de la asincrónica, lo sé, pero puede arrojar algo de luz – billinkc

Respuesta

4

Se espera que todos los navegadores se limiten a 2 solicitudes por host, para evitar sobrecargar el host. .NET sigue esta regla y permite solo 2 conexiones concurrentes a un host. Puede cambiar este límite modificando el archivo de configuración de una aplicación o mediante un código.

El retraso que agregó al script no funcionó porque no llamó a Dispose en la instancia de WebClient. La clase WebClient mantiene su conexión abierta hasta que la deseche para leer la secuencia de respuesta.De lo contrario, no podrá volver a conectarse al mismo host hasta que el recolector de basura recolecte el cliente.

Además, OpenReadAsync abre la transmisión al cliente y garantiza que permanezca abierta a menos que la cierre o se recopile. Debería usar uno de DownloadXXXAsync para evitar abrir la transmisión sin una razón.

Una mejor solución sería llamar a DownloadStringAsync y deshacerse del cliente en el evento DownloadStringAsyncCompleted.

UPDATE:

ServicePointManager.DefaultConnectionLimit se almacena en un campo estático que significa que su ámbito de aplicación es la totalidad del dominio de aplicación. SSIS utiliza un único dominio de aplicación para cada ejecución del paquete, por lo que el valor afectará a todo el paquete.

Si desea modificar el límite de conexión sólo para un único host usando FindServicePoint, se puede crear un ServicePoint para la dirección de host y establecer el límite sólo para esta dirección:

var myTarget= ServicePointManager.FindServicePoint(new Uri("http://www.google.com")); 
myTarget.ConnectionLimit = 10; 
+0

He añadido inside pero sigo teniendo el mismo comportamiento – Diego

+0

Ignore mi último comentario. Agregué el código de su segundo enlace a mi tarea de script con un límite de 5 y funcionó perfectamente. Lo que no entiendo es que no hice ninguna referencia a mi objeto WebClient. ¿Cómo "leyó" esta configuración? ¿Es un escenario global? Muchas gracias – Diego

+0

El valor se almacena en un campo estático, lo que significa que es global para el Dominio de la aplicación. SSIS usa un solo dominio de aplicación para cada ejecución del paquete, por lo que no hay riesgo de que el cambio afecte a otras ejecuciones. Actualicé la respuesta con el código para cambiar el límite de una única dirección, solo –

1
  1. tratar de extender el tiempo de espera para cada tarea y subtarea.

  2. No me lo pidieron, pero codificaría una tarea como esta en lugar de usar SSIS. ¡SSIS es perfecto para ETL pero no mucho más!

Cuestiones relacionadas