Сравнения производительности между типами соединений не важны, поскольку они дают наборы результатов differnt. Даже если бы внутреннее объединение быстрее, Вы не использовали бы его при необходимости в результатах левого соединения (который включает даже записи, которые не соответствуют второй таблице в соединении).
Я полагаю , что проблема в том, что WebRequest
измеряет время только после того, как запрос действительно сделан. Если вы отправляете несколько запросов на один и тот же адрес, тогда ServicePointManager
будет ограничивать ваши запросы и фактически отправлять столько одновременных подключений, сколько значение соответствующего ServicePoint.ConnectionLimit
, которое по умолчанию получает значение из ServicePointManager.DefaultConnectionLimit
. Хост CLR приложения устанавливает это значение 2, хост ASP - 10. Таким образом, если у вас есть многопоточное приложение, которое отправляет несколько запросов на один и тот же хост, только два фактически помещаются в сеть, остальные помещаются в очередь.
Я не исследовал это убедительное доказательство того, действительно ли это происходит, но в аналогичном проекте у меня все было ужасно, пока я не снял ограничение ServicePoint
.
Еще один фактор, который следует учитывать, - это время поиска DNS. Опять же, моя вера не подкреплена вескими доказательствами, но я думаю, что WebRequest
не подсчитывает время поиска DNS по таймауту запроса. Время поиска DNS может отображаться как очень большой фактор времени в некоторых развертываниях.
И да, вы должны кодировать свое приложение вокруг WebRequest.BeginGetRequestStream
(для POST
с контентом) и WebRequest.BeginGetResponse
(для GET
s и POSTS
s). Синхронные вызовы не масштабируются (я не буду вдаваться в подробности почему, но у меня есть веские доказательства). Тем не мение, проблема ServicePoint
ортогональна этому: поведение очереди происходит и с асинхронными вызовами.
Позже я обнаружил, что помогло, это свойство .ReadWriteTimeout
. Это, в дополнение к свойству .Timeout
, казалось, окончательно сократило время, которое потоки тратят на загрузку с проблемного сервера. По умолчанию время для .ReadWriteTimeout
составляет 5 минут, что для моего приложения было слишком долгим.
Мне кажется:
.Timeout
= время, потраченное на попытки установить соединение (не включая время поиска)
.ReadWriteTimeout
= время, потраченное на попытки чтения или записи данных после установления соединения
Дополнительная информация: Свойство HttpWebRequest.ReadWriteTimeout
Изменить:
Комментарий Per @ KyleM, Свойство Timeout
предназначено для всей попытки подключения, и чтение его в MSDN показывает:
Timeout - это количество миллисекунд, в течение которого последующий синхронный запрос, сделанный с помощью метода GetResponse, ожидает ответа, а метод GetRequestStream ожидает для потока. Тайм-аут применяется ко всему запросу и ответу, а не по отдельности к вызовам методов GetRequestStream и GetResponse. Если ресурс не возвращается в течение периода ожидания, запрос генерирует WebException со свойством Status, установленным в WebExceptionStatus.Timeout.
(Акцент мой.)
Из документации свойства httpwebrequest.timeout:
Запрос системы доменных имен (DNS) может занять до 15 секунд, чтобы вернуться или время. Если ваш запрос содержит Имя хоста, которое требует разрешения и Вы устанавливаете Timeout на значение меньше, чем 15 секунд, это может занять 15 секунд или Более перед броском WebException Чтобы указать тайм-аут по вашему запросу.
Возможно ли, что ваш запрос DNS является причиной тайм-аута?