【问题标题】:Strange behavior with uri and WebClient classes on SSIS packageSSIS 包上 uri 和 WebClient 类的奇怪行为
【发布时间】:2012-05-30 04:29:37
【问题描述】:

我的情况很奇怪。

我有这个非常简单的包:

  • 任务“获取列表”从具有一个的程序集中检索数据表 列和要运行到对象变量中的 URL 列表。
  • “foreach”循环遍历对象变量并加载 将 URL 转换为 url 字符串变量
  • “运行”,使用此代码调用 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 个。循环 lops 4 次,脚本被调用 4 次(我可以看看我是否调试它),行 myWebClient.OpenReadAsync(myURI) 执行 4 次,有 4 个不同的值,但只调用了 2 次 URL。

如果我再次运行该程序包,现在会调用其他 2 个 URL,这证明该 URL 没有任何问题,如果我在浏览器上手动调用 4 个 URL(例如在 4 个选项卡上)一个正确依次类推,都产生了预期的结果,证明解析URL的代码没有问题。

所以我留下了 VB 代码,这是我第一次使用 uri 和 WebClient,所以我想知道我是否做错了什么。我还尝试在通话之间添加 5 秒的睡眠时间,但没有成功。

任何帮助将不胜感激。 谢谢

【问题讨论】:

  • 如果切换到使用同步 OpenRead 方法会怎样?
  • 嗨,比林克!第二次运行后我超时。这很奇怪,因为我拥有的 4 个 url 应该在几秒钟内运行,事实上我可以看到(我有一个日志)第二个在第一个之后 5 秒运行。如果我第二次运行这个包,剩下的 2 个 url 运行良好,所以绝对是调用代码超过 2 次的事实
  • 每当我在 SSIS 中遇到“奇怪”的代码问题时,我都会将代码转储到 .NET 控制台应用程序中,看看是否可以在那里重现该行为。我假设您已经尝试过,但如果您还没有尝试过,那可能是一个转眼的地方,因为对您的赏金没有太多的爱。另外,您的完整代码是什么样的?是否有可能调用所有 4 个 URL,但由于它们是异步调用,所以您直到稍后才观察到效果?如果您在其中放置更长的 thread.sleep 以匹配预期的进程持续时间怎么办?击败异步的目的,我知道,但可能会有所启发
  • 嗨 bilinkc!问题是我的完整代码!我很肯定代码没有被调用,因为有一个数据库交互,所以我可以在数据库上看到。此外,我增加了更长的睡眠时间,但没有帮助。你能给我更多关于你如何做转储的细节吗?我只知道如何在命令行上使用 DTEXEC 转储错误。不要以为是这样。您可以添加为答案,以便我可以标记它,因为您是迄今为止对我帮助最大的人。谢谢

标签: sql sql-server-2005 ssis webclient ssis-2005


【解决方案1】:

所有浏览器都应将自己限制为每个主机 2 个请求,以避免主机过载。 .NET 遵循此规则,并且只允许与主机建立 2 个并发连接。您可以通过修改应用程序的配置文件或通过代码来更改此限制。

您添加到脚本的延迟不起作用,因为您没有在 WebClient 实例上调用 Dispose。 WebClient 类保持其连接打开,直到您将其处置以读取响应流。否则在垃圾收集器收集客户端之前,您将无法再次连接到同一主机。

此外,OpenReadAsync 会向客户端打开流并确保它保持打开状态,除非您关闭它或它被收集。您应该使用其中一个 DownloadXXXAsync 来避免无故打开流。

更好的解决方案是调用 DownloadStringAsync 并在 DownloadStringAsyncCompleted 事件中处理客户端。

更新:

ServicePointManager.DefaultConnectionLimit 存储在一个静态字段中,这意味着它的范围是整个 AppDomain。 SSIS 对每个包执行使用单个 AppDomain,因此该值将影响整个包。

如果您只想使用FindServicePoint修改单个主机的连接限制,您可以为主机地址创建一个ServicePoint,并仅为该地址设置限制:

var myTarget= ServicePointManager.FindServicePoint(new Uri("http://www.google.com"));
myTarget.ConnectionLimit = 10;

【讨论】:

  • 我在 中添加了 但我仍然得到相同的行为
  • 忽略我最后的评论。我将您的第二个链接中的代码添加到我的脚本任务中,限制为 5,它确实运行良好。我不明白的是:我没有对我的 WebClient 对象进行任何引用。它是如何“读取”这个设置的?是全局设置吗?非常感谢
  • 该值存储在一个静态字段中,这意味着它对于 AppDomain 是全局的。 SSIS 对每个包执行使用单个 appdomain,因此不存在更改影响其他执行的风险。使用代码更新了答案以仅更改单个地址的限制
  • 太棒了,再次感谢。另一个快速的问题。你知道如何调用 Uri 来通知凭据吗?我需要硬编码一个 AD 用户\密码,但到目前为止我很不走运
【解决方案2】:
  1. 尝试延长每个任务和子任务的超时时间。

  2. 我没有被问到,但我会硬编码这样的任务,而不是使用 SSIS。 SSIS 非常适合 ETL,但仅此而已!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多