Странное поведение с классами uri и WebClient в пакете служб SSIS

У меня довольно странная ситуация.

У меня есть очень простой пакет:

  • Задача "получить список" извлекает таблицу данных из сборки с одним столбцом и списком URL-адресов, которые нужно запустить в переменную объекта.
  • Цикл foreach проходит через переменную объекта и загружает URL в строковую переменную URL
  • "Run" вызывает URL с этим кодом (его 2005, так что я застрял с VB):

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

вызываемый URL является внутренним и просто читает параметры и выполняет ряд операций, которые занимают некоторое время, поэтому я использовал "OpenReadAsync"

Моя проблема: если у меня есть 4 URL для запуска, пакет запускает только 2 из них. Цикл повторяется 4 раза, скрипт вызывается 4 раза (я вижу, отлаживаю ли я его), строка myWebClient.OpenReadAsync(myURI) выполняется 4 раза с 4 различными значениями, но выполняется только 2 обращения к URL.

Если я запустил пакет еще раз, теперь будут вызваны другие 2 URL-адреса, что доказывает, что с URL-адресом нет ничего плохого, и если я вызываю 4-х URL-адреса вручную в браузере (например, на 4-х вкладках), один за другим, все они приводят к ожидаемому результату, который доказывает, что в коде, который анализирует URL, нет ничего плохого.

Так что я остался с кодом VB, я впервые использую uri и WebClient, поэтому мне интересно, что я делаю что-то не так. Я также пытался добавить 5 секунд сна между вызовами, но не повезло.

Любая помощь будет оценена. Спасибо

2 ответа

Решение

Ожидается, что все браузеры ограничат себя 2 запросами на хост, чтобы избежать перегрузки хоста. .NET следует этому правилу и разрешает только 2 одновременных подключения к хосту. Вы можете изменить это ограничение либо изменив конфигурационный файл приложения, либо с помощью кода.

Задержка, которую вы добавили в скрипт, не сработала, потому что вы не вызвали Dispose для экземпляра WebClient. Класс WebClient сохраняет свое соединение открытым, пока вы не утилизируете его для чтения потока ответов. В противном случае вы не сможете снова подключиться к тому же хосту, пока сборщик мусора не соберет клиента.

Кроме того, OpenReadAsync открывает поток для клиента и гарантирует, что он остается открытым, пока вы не закроете его или он не будет собран. Вы должны использовать один из DownloadXXXAsync, чтобы избежать открытия потока без причины.

Лучшим решением было бы вызвать DownloadStringAsync и избавиться от клиента в событии DownloadStringAsyncCompleted.

ОБНОВИТЬ:

ServicePointManager.DefaultConnectionLimit хранится в статическом поле, что означает, что его областью действия является весь домен приложения. Служба SSIS использует один домен приложений для каждого выполнения пакета, поэтому значение влияет на весь пакет.

Если вы хотите изменить ограничение соединения только для одного хоста, использующего FindServicePoint, вы можете создать ServicePoint для адреса хоста и установить ограничение только для этого адреса:

var myTarget= ServicePointManager.FindServicePoint(new Uri("http://www.google.com"));
myTarget.ConnectionLimit = 10;
  1. Попробуйте увеличить время ожидания для каждой задачи и подзадачи.

  2. Меня не спрашивали, но я бы жестко запрограммировал такую ​​задачу вместо использования SSIS. SSIS идеально подходит для ETL, но не намного!

Другие вопросы по тегам