我们有一些使用大家最喜欢的语言(?)VB6编写的COM+代码。这个COM+组件调用了一个由第三方编写的标准COM组件,该组件执行对SQL Server数据库的调用。在COM+中我们什么也不做,除了(以下是示例,我们并不真正调用doStuff函数 :-) ):
作为一个可怕的快速压力测试,我们将调用包装在一个非常简单的VBScript中,它简单地创建对象,在循环中调用方法,将对象设置为无效,并重复几次。然后我们在命令提示符中并行运行四个这样的脚本。
我们的经验是,四个COM+窗口停止了,就好像它们在某种方式上相互阻塞一样。根据输出的行为,看起来不同的窗口在某个地方共享对象的实例:例如,输出在窗口之间出现的速度在窗口之间同步...所以两个窗口可以以很快的速度运行,而另外两个则每秒钟输出一行(当它们输出这一行时,它们同时进行)。
最终,所有四个窗口似乎都停止了——在组件服务中,我们看到调用时间开始上升(从每个调用的几毫秒,上升到30、40秒)。有时dllhost.exe会失败,我们会看到一个COM代理错误对话框(此时窗口会恢复,生成一个新的dllhost)。
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代理错误对话框(此时窗口会恢复,生成一个新的dllhost)。
数据库上没有任何活动,因此我们排除了数据库层面的问题。我们尝试通过将 COM+ 组件设置为“禁用事务”来获得更好的结果,但挂起问题并未消失。我们将尝试使用 CreateObject
创建 COM 对象而不是 new
,以查看它是否会有什么作用(如果有)。在 COM+ 和 VBScript 层面完成对象后都将其设为 Nothing
。
值得注意的是,如果直接从 VBScript 调用第三方库(绕过 COM+),则不会出现任何问题。因此,似乎与 COM+ 与 COM 对象交互的方式有关,但除了在组件服务下调整对象属性的不同设置外,不确定还发生了什么。
有什么建议可以解决这个问题吗?或者可以调整哪些设置?
额外信息
回答问题中的答案:
- 全局变量未被使用(根据 http://support.microsoft.com/kb/815053)
- 正确设置无人值守执行和保留在内存中(根据 http://support.microsoft.com/kb/264957)
- 由于对象是VB COM+对象,因此正在运行STA,因此无法配置对象池化