.NET 2服务组件(COM+)效率问题

本文关键字:COM+ 效率 问题 组件 服务 服务组 NET | 更新日期: 2023-09-27 17:58:56

这是我第一次创建。NET服务组件(COM+),在可伸缩性方面我遇到了一些问题。我已经对它进行了多达4000名用户的压力测试,但它仍然无法超过原始解决方案的性能。

它背后的基本思想是COM+在内存中保存一个包含字典的静态类,ASP页面调用该组件从字典中检索对象。字典里任何时候都有6000到12000个词条。

静态字典类如下所示:

public class Menus
{
    public static Dictionary<string, MenuPage> MenuPages { get; set; }
}

向COM+公开的ServicedComponent类如下所示:

public class MenuManager : ServicedComponent
{
    public MenuPage GetMenuPage(string PubCode, int Page)
    {
        MenuPage ReturnMenuPage;
        Menus.MenuPages.TryGetValue(String.Concat(PubCode, Page.ToString()), out ReturnMenuPage);
        return ReturnMenuPage;
    }
}

COM+组件是从ASP页面调用的,比如…

Dim MenuManager : Set MenuManager = Server.CreateObject("MenuManager.MenuManager")
Dim MenuPage : Set MenuPage = MenuManager.GetMenuPage(UCase(sBook), iPage)
If (Not MenuPage Is Nothing) Then
    //Retrieve values from class
Else
    Set MenuPage = Nothing
    Set MenuManager = Nothing
    Throw404()
End If
Set MenuPage = Nothing
Set MenuManager = Nothing

COM+作为本地服务运行,AssemblyInfo中设置了以下选项:

[assembly: ApplicationActivation(ActivationOption.Server)]
[assembly: ApplicationAccessControl(false, AccessChecksLevel = AccessChecksLevelOption.ApplicationComponent)]

在单个测试实例下,当前解决方案需要0.03秒才能解析,新组件需要0.0003秒才能解析。然而,在负载下,它的性能实际上比原来的差。

我真正需要知道的是,我到底做错了什么,以至于在缩放时性能没有像预期的那样提高!?!?!

如有任何帮助,我们将不胜感激。

.NET 2服务组件(COM+)效率问题

问题

我认为您看到的是使用服务器应用程序并返回的副产品。NET类。当您调用MenuManager时,您正在进行进程外调用以返回MenuPage对象。但是MenuPage是通过引用返回的——对象在服务器应用程序进程中的内存中。为了验证这是真的,在MenuPage getter方法之一中放置一些代码:

System.Diagnostics.Trace.TraceInformation(
  System.Diagnostics.Process.GetCurrentProcess().Id.ToString()
);

您将看到进程ID是服务器应用程序的进程ID。

对于另一个测试,在返回MenuPage之后放置睡眠,然后在睡眠之后检索MenuPage的属性。在睡眠结束之前,请手动关闭COM+资源管理器中的服务器应用程序。您将收到一条消息,说明远程服务器计算机不存在或不可用。

因此,对于每个页面,您都将进行一个远程进程外调用来检索MenuPage,再加上对您在MenuPage上调用的每个属性的另一个进程外调用。

改进

您是否出于安全目的使用服务器应用程序?如果没有,请尝试转到库应用程序,这样调用就不会脱离进程。这可能会有所帮助。

我还将更改我的组件,使其不返回MenuPage,而是返回可以按值(string、int等)封送的基元类型(如果可能的话)

最后,我将使用JIT在方法返回后立即停用对象。由于您在服务器进程中处于停用状态,因此不需要从ASP页面调用Dispose。

我不确定你的MenuPage类是什么样子的,但代码看起来像:

[JustInTimeActivation(true)]
public class MenuManager : ServicedComponent
{
    public void GetMenuPageInfo(string PubCode, 
         int Page, 
         out string menuPageUrl, 
         out int menuCode)
    {
        ContextUtil.DeactivateOnReturn = true;
        menuPageUrl = null;
        menuCode = 0;
        MenuPage ReturnMenuPage;
        if (Menus.MenuPages.TryGetValue(
                String.Concat(PubCode, Page.ToString()), out ReturnMenuPage))
        {
            menuPageUrl = ReturnMenuPage.MenuPageUrl;
            menuCode = ReturnMenuPage.Code;
        }
    }
}

希望这能提高可扩展性。

阅读

查看企业服务设计注意事项:

  • 只有在需要时才使用企业服务
  • 如果可能,请使用库应用程序
  • 考虑DLL和类的关系
  • 只有在需要时才使用分布式事务
  • 使用对象池来减少对象创建开销
  • 基于调用模式设计池对象
  • 使用显式接口
  • 设计不那么健谈的界面
  • 设计无状态组件

了解中的企业服务(COM+)。NET是一篇关于COM+的好文章。

尝试用以下属性标记您的COM+

[JustInTimeActivation]

[Transaction(TransactionOption.Disabled)]

我认为如果禁用COM+事务,对COM+的调用可以更快地工作。此外,我可以建议您将日志记录添加到服务器和客户端部分。之后,您可以分析COM+调用或Dictionary中性能较差的地方。TryGetValue

提高企业服务性能

根据我的经验,您应该将COM设置为"在与客户端相同的进程中"运行。它是组件服务控制台中的设置之一。速度至少快一千倍。