详细信息 避免使用“ASP 会话”将提高服务器的性能,因为它简化了代码路径并减少了服务器资源的消耗。如果不使用“ASP 会话”,请通过“Internet 服务管理器” (请参阅“Internet 信息服务 [IIS]”文档)禁用“会话”状态。也可以在不需要“会话”的 ASP 页面中使用下面的标记禁用基于页的“会话”:
<%@ENABLESESSIONSTATE=False %> 部署灵活性是另一个重要方面,尤其在 Web 区域中运行应用程序时。如果依赖“ASP 会话”, 则给定用户的请求绑定在指定的 Web 服务器上,因为“会话”状态是服务器专用的。在中间层和 Web 服务器中避免状态,并使用数据库,将使 ASP 请求可由区域中任何有效的 Web 服务器处理。因此, 您将减少竞争,提供更好的冗余,并允许更多的分布选项。
不使用“ASP 会话”而在页间传递数据的其他方法,请参阅下面的“知识库 (KB)”文章:
Q175167 HOWTO: Persisting Values Without Sessions(英文) Q157906 HOWTO: Maintain State Across Pages with VBScript(英文) Don Box 在 ActiveX® Q&A(英文) 一文中 还提出有关 MTS 状态管理的更多见解。
Q243543 INFO: Do Not Store STA Objects in Session or Application(英文) Q243548 INFO: Design Guidelines for VB Components Under ASP(英文) 分割服务 建议 将表达、业务和数据服务分离。业务组件应该实施业务规则。业务组件不应包含数据访问技术。那是数据层组件的任务。业务组件不应包含对 ASP 对象的引用。
ASP 提供表达服务。引用 ASP 的对象应该呈现为 HTML。这些对象能够依次调用对 MTS/COM+ 注册的业务对象。
为什么 将应用程序分割为单独的和截然不同的服务,有以下好处:
更便于组件的重用 支持 Windows DNA model(英文) 更好地孤立疑难问题 更灵活的部署选项(去掉服务的耦合允许在多台计算机上分布应用程序) 常见的陷阱 有一种我们称为“瑞士军刀”组件的常见问题。 该“瑞士军”组件将所有服务合成一体 (就像有螺丝锥、牙签等 17 种工具的小瑞士军刀)。 把不相关的服务组合到一个组件中, 使该组件很难使用、理解和维护。
容易掉入的另一个陷阱是从业务组件中引用 ASP。使 ASP 和业务逻辑耦合(通过使用 请求或响应对象,或在其内部构建 HTML),不仅限制不同的客户机重用您的组件,而且限制了横向的可伸缩性。引用 ASP 内置对象的对象应该与 Web 服务器在同一框围中。理想情况下,由于横向可伸缩性,业务组件可以分布在不同的框围中。可以直接在 ASP 脚本中提供表达服务,也可以建立呈现引用 ASP 内置对象的组件的 HTML,并将这些组件保持在 IIS 框围中。
常见的陷阱 也许最常见的陷阱就是使用了没有被设计为在 ASP 下运行的组件,如“单线程”组件。大多数开发人员陷入其中,是因为将桌面应用程序移向 ASP,或者使用了第三方的控件时。如果您不能确定组件的线程模型,可以检查组件的注册表项(但不能总依赖它)。
详细信息 有关线程模型及其对 ASP 的影响,请参阅下面的文章:
Don Box's Active Server Pages and COM Apartments(英文) Agility in Server Components 另外,下面的 KB 文章提供了有关线程问题的详细内容:
Q243543 Single-Threaded Apartment Objects in Session or Application(英文) Q243544 INFO: Component Threading Model Summary Under Active Server Page(英文) Q150777 INFO: Descriptions and Workings of OLE Threading Models(英文) 安全性 建议 组件不应对它运行的用户环境做任何假设。不要访问用户专用信息,如 HKEY_CURRENT_USER,或桌面计算机的专用资源,因为这些对组件来讲是不可用的。应用程序也不要使用 SendKeys 或调用依赖用户界面的组件,执行通常需要桌面交互的操作,如打开对话框。
Q248348 PRB: SaveSetting and GetSetting Not Available in Visual Basic 6.0 Webclass (IIS Application)(英文) 当从 ASP 而不是从桌面客户机调用组件时,打印机、MAPI 信息和网络共享通常“失效”。
有关详细内容,请参阅下面的 KB 文章:
Q184291 PRB: COM Objects Fail to Print When Called From ASP(英文) Q217144 INFO: Difficulties Using Net APIs in ISAPI and ASP COM Objects(英文) Q207671 HOWTO: Accessing Network Files from IIS Applications(英文) 详细信息 有关安全性的几点考虑:
启用哪种 IIS 身份验证方法? 您的 Web 应用程序是进程内的还是进程外的? 如果组件以 MTS 或 COM+ 注册,它是在“服务器”上还是在库软件包中? 您正在调用本地 DLL、远程 DLL、本地 EXE、远程 EXE 吗? 有关安全性的详细说明超出了本文的范围。但是,由于这个主题的复杂性,下面的文章对从 ASP 组件角度理解问题有很大帮助:
Securing a Web-based Microsoft Transaction Server Application(英文) Q172925 INFO: Security Issues with Objects in ASP and ISAPI Extensions(英文) Q217202 PRB: CGI Applications and IIS OOP Applications May Fail(英文) 下文很好地概述了 IIS 如何处理安全性:
Authentication and Security for Internet Developers(英文) Server.CreateObject 与 CreateObject 建议 使用 Server.CreateObject。如果正在使用 MTS/COM+ 库软件包,请使用 Server.CreateObject 来避免线程阻塞。
ASP 不能识别该对象。 OnStartPage/OnEndPage 页面方法没有调用。 ASP 不知道对象的线程模型。 Server.CreateObject 相当于 GetObjectContext.CreateInstance。这表示 ASP 清楚该对象并知道它的线程模型。另外,如果 ASP 页面是事务性的,则通过调用 Server.CreateObject 可使组件与 ASP 页面在同一事务中。(请注意,事务性的页面可能意味着可避免的业务规则与表达层的耦合。)
常见的陷阱 如果对象处于防火墙后面,可能需要调用 CreateObject。请参阅 Q193230 PRB: Server.CreateObject Fails when Object is Behind Firewall(英文) 以获得详细信息。
Q197956 PRB: Passing Parameters By Reference to a VB COM Object(英文) Q197957 PRB: Passing Parameters By Reference to a VC COM Object(英文) 事件 建议 避免调用等待其他组件返回事件的组件。
组件方法应尽快返回对 ASP 的执行。请考虑使用“MSMQ”或“COM+ 排队组件” 来提供异步调用 — 或当要做的工作正长时间运行并且不必联机运行时。
请异步地分派工作项目,而不要让 ASP 等待长时间运行的进程结束。然后您将从 ASP 给客户机返回一个响应。一旦工作项目完成,您可以用电子邮件或其他方法通知客户机(请参阅下面内容)。
Q243547 PRB: ASP Does Not Provide Progress Notifications to Client Browsers(英文) Q243546 PRB: ASP Does Not Support Events(英文) OnStartPage/OnEndPage 与 ObjectContext 建议 在 IIS 4.0 及更高版本中使用 ObjectContext 访问 ASP 内置对象(如响应、请求、服务器等等)。无论何时请尽量避免使用 ScriptingContext 对象、 OnStartPage 和 OnEndPage。
错误处理 建议 错误处理器将期待着意外情况。捕获应用程序每一部分中的错误,并尽可能完整地记录下来。好的日志对于跟踪、隔离和疑难解答有重大意义。这些日志可以实现为文本文件或写入 NT 事件日志。在多数情况下,边添加信息边“冒出”错误,是通知调用者已经出错的有效途径。冒出错误使调用者可自由地与处理具体问题的具体方法交互。
Black Belt Programming - Create Worker Threads in DLLs COMponent Builder - Create Efficient Multithreaded Apps 另外,下面 Daniel Appleman 所著的文章 很好地概述了 Visual Basic 中多线程的工作原理: A Thread to Visual Basic(英文)
对象引用 ASP 内置对象,会与您的 Web 服务器进行大量通讯,并且由于它们是表达层的一部分,因此它们就在那里。
数据库或对数据极为敏感的逻辑可能在数据库的存储过程中。将数据访问组件置于应用程序服务器而非数据库上,避免了组件之间的昂贵调用。相反,数据访问组件则利用 SQL Server 通信(如 TCP/IP)与数据库更有效地通信。
常见的陷阱 您应当尝试避免下列问题:
当横向可伸缩性较为合适之后,继续追求从您的计算机开始的纵向可伸缩性。 忽视了防火墙的考虑(帮自己一个忙。如果计算机间的产品环境有防火墙,则在测试方案中添加防火墙。) 将引用 ASP 内置对象的组件置于与 IIS 服务器分离的计算机上(回调和编组 ASP 内置对象的成本很高。) 使用组件内部的后期绑定(这产生对 GetIdsOfNames 的额外调用,这在分布式应用程序中可能很昂贵。尽量使用早期绑定。) 按引用传递参数(这产生更多的编组开销。尽可能“按值”传递参数。) 成功地从 IIS 调用远程 MTS 组件也可能很棘手。一个简单有效、既提高性能又简化安全性问题的解决方案,是调用中间的 MTS/COM+ 软件包/应用程序。早期绑定可减少网络路程段,提高性能。如果您使用“服务器”软件包/应用程序,则可以设置软件包/应用程序的运行标识。这个技术将在 KB 文章 159311 Instantiating Remote Components in Microsoft Transaction Server and Internet Information Server 中讨论。
详细信息 如果已经解耦了服务,特别是已使 ASP 在业务组件之外,则分布将相当灵活。您就可以更多地考虑框围,并根据需要分散组件以解决随之而来的可伸缩性和性能问题。如何知道?进行测试。如何测试?请看下面的基本指南:
若要测试 Web 站点的可靠性,请剖析计算机并检查错误。 若要测试性能,请查看每秒可处理多少 ASP 请求。 若要测试可伸缩性,请设置每秒需要处理多少 ASP 请求的阀值。用重要的工具考验应用程序——添加用户直到性能坏到不能接受为止。 加强对应用程序的测试非常重要,因为需要暴露运转条件和单浏览器测试中不会出现的其他问题。 有关对应用程序加强测试的详细内容, 请参阅 I Can't Stress It Enough -- Load Test Your ASP Application(英文)。
结论 正如所见,有一些事情在整个开发中需要时刻注意。在此,应用程序指南所涉及的诸多因素已全部阐明,因为它们有助于彻底避免严重失误。在整个开发周期中遵循本文中略述的几个指南,不仅可以避免一些额外的工作,而且能够提交可收缩的、可靠的、高性能的基于 ASP 组件的解决方案。