我们有一些COM +代码用每个人最喜欢的语言编写(?) - VB6。此COM +组件调用由第三方编写的标准COM组件,该组件执行对SQL Server数据库的调用。我们在COM +中没有做任何花哨的事 - 只不过(这只是一个例子;我们并没有真正调用我们的函数doStuff :-)):
Function doStuff
Dim o As Library.Object
Set o = New Library.Object
str = o.DoSomething()
Set o = Nothing
doStuff = str
End Function
作为一个可怕的快速压力测试,我们将调用包装在一个简单的简单VBScript中,简单地创建对象,在循环中调用方法,将对象设置为空,并重复几次。然后,我们在命令提示符下同时运行其中的四个。
我们经历的是四个COM +窗口停止死亡,好像它们以某种方式相互阻挡。根据输出的行为,看起来不同的窗口在沿途的某处共享对象的实例:例如,窗口之间的输出出现的速度在窗口之间同步...所以两个可以在速度上起泡,而另外两个吐出一条线(当他们吐出线时,他们同时这样做)。
然后最终,所有四个窗口似乎都停止了 - 在组件服务中,我们看到呼叫时间开始爬升(因此从每次呼叫的几毫秒,它爬升到30,40秒)。有时dllhost.exe失败,我们会出现一个COM Surrogate错误对话框(此时窗口会在生成新的dllhost时恢复)。
数据库上有 no 活动,因此我们排除了数据库层阻塞的问题。通过将COM +组件设置为“Transactions:disabled”,我们似乎已经取得了更好的效果,但是挂起并没有消失。而不是new
,我们将尝试使用CreateObject
创建COM对象,以查看它的作用(如果有的话)。在COM +和VBScript层完成后,对象都设置为Nothing。
值得注意的是,如果直接从VBScript调用第三方库(绕过COM +),则不会出现问题。因此,似乎它与COM +与COM对象交互的方式有关,但除了摆弄组件服务中对象属性下的不同设置之外,还不确定其他事情是什么。
有什么建议可以引起这种情况吗?还是要调整设置?
额外信息
回答答案中的问题:
进一步的工作...... 看起来它是COM +或COM深处的同步问题。在我们的测试脚本中,如果我们在每次迭代时添加10-50ms的随机延迟,问题就会消失。如果我们有固定的延迟,我们会锁定。一些谷歌搜索似乎表明,对于负载很重的COM +,它可能是一个问题,即documented here on an MS blog。回到Server 2000机箱或Server 2003 SP1机箱会很高兴:这可能是接下来要看的......
答案 0 :(得分:2)
听起来你可能会在公寓电话中遇到COM +和STA的问题。
微软曾经发过一篇由Michael McKeown发表的伟大文章,名为“从MTS移植到COM +时保持应用程序性能”,讨论了这个问题,但它看起来已被删除(有一个存档版本here)。
基本上,COM + STA线程池最多绑定5个活动到每个STA线程。当您进行公寓呼叫(第三方组件或SQL Server)时,COM +允许其他请求作为STA线程上的另一个活动进行服务。最多5个活动(每个线程)可能会发生这种情况。此外,一旦对另一个活动进行了控制,原始活动就无法重新获得控制,直到第二个活动完成。在负载很重和/或如果调用“长时间运行”,则第一个活动完成的时间是完成所有其他活动(在线程上)的时间总和。这可能会影响你的表现。
如果您能够切换整个COM +服务器的设置,则可以将COM +配置为使用旧的MTS 100 STA线程方法。有关详细信息,请参阅Registry key for tuning COM+ thread and activity。你可以看看这是否有助于你的表现。另一种方法是避免STA组件。
答案 1 :(得分:0)
或许COM+ Object Pooling Concepts以及Configuring a Component to Be Pooled等相关文章会有所帮助。
Poolable对象必须满足某些要求才能使多个客户端使用单个对象实例。例如,它们不能保持客户端状态或具有任何线程关联。
答案 2 :(得分:0)
我想到了两件事:
您是否尝试将o
变量设为本地而非模块级别?
功能doStuff
Dim o as Library.Object
设置o = New Library.Object
str = o.DoSomething()
设置o = Nothing
doStuff = str
结束职能
您是否认为Library.Object组件和.DoSomething方法不包含全局变量(或MessageBox语句)?
你能在每一行之后抛出日志语句,看看代码窒息的地方吗?
点击ProcMon查看它何时停止访问注册表。最后一次通话失败了吗?如果是这样,去哪里?