5

在 CLR 存储过程中发出 HttpWebRequest 时(根据下面的代码),Sql Server (重新)启动后或给定(但不确定)时间段后的第一次调用会在GetResponse() 方法调用。

有什么方法可以解决这个不涉及“黑客”的问题,例如每隔几分钟运行一次 Sql Server 代理作业以尝试确保代理发出第一个“慢”调用而不是“真实”生产代码?

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)。如果您的系统无法直接访问 Internet,或者被限制访问 Microsoft.com 域,这可能会延迟 BizTalk Server 的启动。为避免在应用程序启动时出现这种延迟,您可以使用以下步骤在您的系统上手动下载并安装代码签名证书吊销列表。

  1. 从http://crl.microsoft.com/pki/crl/products/CodeSignPCA.crlhttp://crl.microsoft.com/pki/crl/products/CodeSignPCA2.crl下载最新的 CRL 更新 。
  2. 将 CodeSignPCA.crl 和 CodeSignPCA2.crl 文件移动到隔离系统。
  3. 在命令提示符下,输入以下命令以使用 certutil 实用程序使用在步骤 1 中下载的 CRL 更新本地证书存储: certutil –addstore CA c:\CodeSignPCA.crl

CRL 文件会定期更新,因此您应该考虑设置下载和安装 CRL 更新的重复任务。要查看下次更新时间,请双击 .crl 文件并查看 Next Update 字段的值。

于 2009-09-01T05:19:58.290 回答
1

不确定,但如果延迟足够长以至于初始 DNS 查找可能是罪魁祸首?(与正常通话相比,延迟诗句要多长时间?)

和/或

这个 URI 是网络内部的还是不同的内部网络?

我已经看到一些奇怪的网络延迟,因为在设置不正确的网络中使用负载平衡配置文件,防火墙、负载平衡器和其他网络配置文件可能正在“对抗”初始连接......

我不是一个出色的网络人,但您可能还想在 serverfault.com 上查看 SA 对此有何评论……

祝你好运

于 2009-08-25T15:47:36.960 回答
0

SQLCLR 第一次加载必要的程序集时总是有延迟。这不仅适用于您的函数 MakeWebRequest,而且适用于 SQLCLR 中的任何 .NET 函数。

于 2009-08-20T19:26:42.667 回答
0

HttpWebRequest 是 System.Net 程序集的一部分,它不属于受支持的库。我建议使用库 System.Web.Services 而不是从 SQLCLR 内部进行 Web 服务调用。

于 2009-08-25T15:25:25.883 回答
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 回答