5

CLR ストアド プロシージャ内で HttpWebRequest を作成する場合 (以下のコードに従って)、SQL Server が (再) 起動された後、または特定の (ただし不確定な) 期間が経過した後の最初の呼び出しは、サーバー上でかなりの時間待機します。 GetResponse() メソッド呼び出し。

Sql Server Agent ジョブを数分ごとに実行して、最初の「遅い」呼び出しが「実際の」本番ではなくエージェントによって行われることを確認するなど、「ハック」を伴わないこれを解決する方法はありますか?コード?

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;
}

(簡潔にするために、エラー処理とその他の重要でないコードは削除されています)


この Sql Server フォーラム スレッドも参照してください。

4

6 に答える 6

10

これは私HttpWebRequestが最初に使用したときの問題でした。これは、クラスが使用するプロキシを探しているためです。オブジェクトのProxy値をnull/Nothingに設定すると、すぐに圧縮されます。

于 2009-09-01T04:48:31.803 に答える
4

コード署名検証のように見えます。MS 出荷のシステム dll はすべて署名されており、SQL はロード時に署名を検証します。どうやら、証明書失効リストの有効期限が切れており、証明書検証エンジンが新しいリストの取得中にタイムアウトしました。コード署名の検証が原因でアプリケーションの起動が遅くなる問題を修正する前に、この問題についてブログに書きました。この問題については、Technet の記事「証明書の失効とステータスの確認」でも説明しています。

解決策はかなり難解で、キーのレジストリ編集が必要です: HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CertDllCreateCertificateChainEngine\Config:

  • ChainUrlRetrievalTimeoutMillisecondsこれは、個々の CRL チェック呼び出しのタイムアウトです。が 0 または存在しない場合、デフォルト値の 15 秒が使用されます。このタイムアウトを 200 ミリ秒などの適切な値に変更します。
  • ChainRevAccumulativeUrlRetrievalTimeoutMillisecondsこれは、集計 CRL 取得タイムアウトです。0 に設定するか、存在しない場合、デフォルト値の 20 秒が使用されます。このタイムアウトを 500 ミリ秒などの値に変更します。

Microsoft 署名済みアセンブリ用のより具体的なソリューションもあります(これは Biztalk ドキュメントからのものですが、アセンブリの読み込みに適用されます)。

Microsoft 証明書失効リストを手動でロードする

.NET アプリケーションを起動すると、.NET Framework は、署名されたアセンブリの証明書失効リスト (CRL) をダウンロードしようとします。システムがインターネットに直接アクセスできない場合、または 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 ユーティリティを使用して、手順 1 でダウンロードした CRL でローカル証明書ストアを更新します。 certutil –addstore CA c:\CodeSignPCA.crl

CRL ファイルは定期的に更新されるため、CRL 更新のダウンロードとインストールの繰り返しタスクを設定することを検討する必要があります。次回の更新時刻を表示するには、.crl ファイルをダブルクリックし、[次の更新] フィールドの値を表示します。

于 2009-09-01T05:19:58.290 に答える
1

確かではありませんが、最初の DNS ルックアップが原因である可能性があるのに十分な長さの遅延がある場合は? (通常の通話と比較して遅延時間はどのくらいですか?)

および/または

この URI はネットワークの内部にあるのか、または別の内部ネットワークにあるのか?

正しく設定されていないネットワーク内でロード バランス プロファイルを使用すると、奇妙なネットワーク遅延が発生するのを見てきました。

私は優れたネットワーク担当者ではありませんが、serverfault.com で SA がこれについて何と言っているかを確認したい場合もあります...

幸運を

于 2009-08-25T15:47:36.960 に答える
0

HttpWebRequest は、サポートされているライブラリの一部ではない System.Net アセンブリの一部です。SQLCLR 内から Web サービスを呼び出す代わりに、ライブラリ System.Web.Services を使用することをお勧めします。

于 2009-08-25T15:25:25.883 に答える
0

SQLCLR が必要なアセンブリを初めて読み込むときは、常に遅延が発生します。これは、関数 MakeWebRequest だけでなく、SQLCLR のすべての .NET 関数にも当てはまります。

于 2009-08-20T19:26:42.667 に答える
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);
        }
    }
}
于 2009-08-26T09:33:10.060 に答える