2009-08-18 2 views
5

При создании HttpWebRequest в хранимой процедуре CLR (согласно приведенному ниже коду) первый вызов после того, как сервер Sql (повторно) запущен или после заданного (но неопределенного) периода время ожидания на вызов метода GetResponse() длится довольно долго.HttpWebRequest запускается медленно в первый раз в SQLCLR

Есть ли способ разрешить это, не связанное с «взломом», например, когда задание агента сервера Sql выполняется каждые несколько минут, чтобы убедиться, что первый «медленный» вызов выполняется Агентом, а не «реальный» производственный код?

function SqlString MakeWebRequest(string address, string parameters, int connectTO) 
{ 
    SqlString returnData; 
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(String.Concat(address.ToString(), "?", parameters.ToString())); 
    request.Timeout = (int)connectTO; 
    request.Method = "GET"; 
    using (WebResponse response = request.GetResponse()) 
    { 
    using (Stream responseStream = response.GetResponseStream()) 
    { 
     using (StreamReader reader = new StreamReader(responseStream)) 
     { 
     SqlString responseFromServer = reader.ReadToEnd(); 
     returnData = responseFromServer; 
     } 
    } 
    } 
    response.Close(); 

    return returnData; 
} 

(Обработка ошибок и другие некритические код имеет бен удалены для краткости)


Смотрите также this Sql Server forums thread.

+0

Как долго длится это первое время ожидания вызова по сравнению с вторым + временем разговора? Является ли этот вызов тем же самым URI? – BigBlondeViking

+0

Я верю (с моей головы) это 30 секунд, и вызов сделан по URL-адресу, который является IP-адресом, поэтому я не думаю, что DNS будет проблемой :( – Rob

+0

Вы считаете, HTTP-трафик с чем-то вроде WireShark? Или было исключено, что все на проводке было исключено. –

ответ

10

Это было проблемой для меня, используя HttpWebRequest сначала. Это связано с тем, что класс ищет прокси для использования. Если вы установите значение Proxy объекта в null/Nothing, оно будет застегиваться вправо.

+0

Это определенно, по-видимому, было причиной * большого количества * (большей) продолжительности первоначального вызова. Но есть еще (может быть) небольшая разница. Любые идеи о том, что еще может сделать начальные вызовы медленнее (при использовании 'HttpWebRequest')? –

0

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

+0

К сожалению, это не проблема здесь, или, как представляется, не существует, так как любая другая функция в нашей сборке CLR может быть вызвана и выполнена, но в первый раз это называется блокировкой на request.GetResponse() – Rob

0

HttpWebRequest является частью сборки System.Net, которая не является частью supported libraries. Я бы рекомендовал использовать библиотеку System.Web.Services вместо того, чтобы делать вызовы веб-сервисов из SQLCLR.

+0

Опять же, не проблема. Мы используем другие компоненты System.Net без каких-либо проблем. «Поддерживается» или иным образом не имеет значения в контексте этого вопроса. Кроме того, System.Web.Services предназначен для * создания * веб-сервисов, а не для загрузки веб-страниц/вызовов веб-сервисов. – Rob

1

Не уверен, но если задержка достаточно долго, чтобы начальный поиск DNS мог быть виновником? (как долго задержка куплета обычного вызова?)

и/или

Является ли этот URI внутреннего по отношению к сети/или другой внутренней сети?

Я видел некоторые странные задержки сети с использованием профилей балансировки нагрузки в сети, которая не настроен правильно, межсетевые экраны, нагрузка-балансиры, а также другие сетевые профили могут быть «борьба» начальные соединения ...

Я не большой сети парень, но вы можете видеть то, что SA должен сказать об этом на serverfault.com, а также ...

удачи

0

я испытал и мой первый холодный запуск (после перезагрузки службы SQL) был через 3 секунды (не 30 как ваш), все остальные - за 0 секунд.

Пример кода я использовал для создания DLL:

using System; 
using System.Data; 
using System.Net; 
using System.IO; 
using System.Data.SqlClient; 
using System.Data.SqlTypes; 
using Microsoft.SqlServer.Server; 

namespace MySQLCLR 
{ 
    public static class WebRequests 
    { 
     public static void MakeWebRequest(string address, string parameters, int connectTO) 
     { 
      string returnData; 
      HttpWebRequest request = (HttpWebRequest)WebRequest.Create(String.Concat(address.ToString(), "?", parameters.ToString())); 
      request.Timeout = (int)connectTO; 
      request.Method = "GET"; 
      using (WebResponse response = request.GetResponse()) 
      { 
       using (Stream responseStream = response.GetResponseStream()) 
       { 
        using (StreamReader reader = new StreamReader(responseStream)) 
        { 
         returnData = reader.ReadToEnd(); 
         reader.Close(); 
        } 
        responseStream.Close(); 
       } 
       response.Close(); 
      } 
      SqlDataRecord rec = new SqlDataRecord(new SqlMetaData[] { new SqlMetaData("response", SqlDbType.NVarChar, 10000000) }); 
      rec.SetValue(0, returnData); 
      SqlContext.Pipe.Send(rec); 
     } 
    } 
} 
+0

Я только что подтвердил с моим коллегой, что задержка составляет около 15 секунд, а не 30, что я думал, что это и это происходит после перезапуска сервера Sql или определенного периода бездействия, который мы еще не идентифицировали (т.е. в течение ночи) – Rob

+0

Таким образом, проблема лежит где-то в другом месте, у нас просто нет среды для ее воспроизведения. Вы считаете, что 3s для холодного старта неприемлемы? –

4

Выглядит как проверка подписи кода. MS-отправленные системные DLL-файлы подписаны, и SQL проверяет подписи во время загрузки. По-видимому, список аннулирования сертификата истек, а механизм проверки сертификатов истекает из-за получения нового списка. Я писал об этой проблеме до Fix slow application startup due to code sign validation, и проблема также описана в этой статье Technet: Certificate Revocation and Status Checking.

Решение довольно запутанный, а включает в себя редактирование реестра ключа: HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CertDllCreateCertificateChainEngine\Config:

  • ChainUrlRetrievalTimeoutMilliseconds Это каждый отдельный тайм-аут CRL проверки вызова. Если 0 или нет, используется значение по умолчанию 15 секунд. Измените этот тайм-аут на разумное значение, например, 200 миллисекунд.
  • ChainRevAccumulativeUrlRetrievalTimeoutMilliseconds Это общий тайм-аут получения CRL. Если установлено значение 0 или нет, используется значение по умолчанию 20 секунд. Измените этот тайм-аут на значение, равное 500 миллисекундам.

Существует также более конкретное решение для Microsoft signed assemblies (это из документации Biztalk, но относится к любой сборке нагрузки):

вручную загрузить Microsoft Certificate отозванных список

При запуске приложения .NET .NET Framework попытается выполнить команду загрузить Список отзыва сертификатов (CRL) для любых подписанных как sembly. Если ваша система не имеет прямого доступа в Интернет или не имеет доступа к домену Microsoft.com , это может задержать запуск BizTalk Server. Чтобы избежать этой задержки при запуске приложения, вы, , можете выполнить следующие шаги до вручную загрузить и установить код , подписывая Списки аннулирования сертификатов в вашей системе.

  1. Скачать последние обновления CRL из http://crl.microsoft.com/pki/crl/products/CodeSignPCA.crl и http://crl.microsoft.com/pki/crl/products/CodeSignPCA2.crl.
  2. Переместить файлы CodeSignPCA.crl и CodeSignPCA2.crl в изолированную систему .
  3. В командной строке введите следующую команду, чтобы использовать CertUtil утилита для обновления локального хранилища сертификата с CRL загруженный на шаге 1: CertUtil -addstore CA C: \ CodeSignPCA.crl

Файлы CRL обновляются регулярно, , поэтому вам следует рассмотреть возможность задания повторно загружаемой задачи загрузки и , устанавливающих обновления CRL. Чтобы просмотреть следующее время обновления, дважды щелкните файл .crl и просмотрите значение поля Next Update.

+0

Конечно, немного необычно, что сервер, делающий вызовы веб-сервисов, не может подключить сервер CRL, чтобы я мог отвлечься, но симптомы очень похожи на проверку CRL. –

+0

Это очень полезно знать. Я попал в проблему тайм-аута CRL в другой форме (загрузка кода .NET C#, загружающая изображения TIFF, делает запрос CRL тайм-аутом, потому что ПК не подключен к Интернету, что приводит к загрузке изображения за 30 секунд). Ручка реестра немного изворотлива, но загрузка CRL вручную кажется разумным решением. – Conceptdev

+0

@Craig: Да, в принципе любое создание приложения может поразить это, и почти невозможно диагностировать, если вы не знаете об этом. Сначала нажмите на веб-сайт ASP, сначала вызовите DLL, приложение замерзает в течение 30 секунд при загрузке, все симптомы одной и той же проблемы. –

Смежные вопросы