從 Active Server Pages (asp) 代碼調(diào)用組件 設(shè)計(jì)將從 ASP 代碼調(diào)用的組件 希望利用 ASP 代碼中的組件 目錄 簡(jiǎn)介 為什么使用組件? 狀態(tài)管理 范圍 分割服務(wù) 線程模型 安全性 Server.CreateObject 與 CreateObject 傳遞參數(shù) 事件 OnStartPage/OnEndPage 與 ObjectContext 錯(cuò)誤處理 全局變量 分布組件 結(jié)論
簡(jiǎn)介 組件。有人喜歡它們,有人則害怕。害怕組件的人通常都能給您講一個(gè)駭人的經(jīng)歷。讓我們面對(duì)它:當(dāng)開(kāi)始在 ASP 下使用組件時(shí),并不知道什么能傷害您。如果您摔倒了,那么站起來(lái),自己拍干凈,然后接著來(lái)。在這篇文章中,我將提供從實(shí)踐中獲得的一般指南,幫助您建立更好的基于組件的 ASP 解決方案。
為什么使用組件? 在我開(kāi)始討論組件指南之前,值得考慮將組件添加到 ASP 應(yīng)用程序的價(jià)值。許多對(duì)組件不熟悉的開(kāi)發(fā)人員總覺(jué)得一切都那么新鮮。組件可以為 ASP 應(yīng)用程序帶來(lái)以下種種益處:
封裝功能和隱藏實(shí)現(xiàn)細(xì)節(jié) 可重用性(包括被不同客戶機(jī)應(yīng)用程序重復(fù)使用) 知識(shí)產(chǎn)權(quán)保護(hù) 可伸縮性(體現(xiàn)在允許將應(yīng)用程序分布到多臺(tái)計(jì)算機(jī)上) 配置和部署靈活性 性能(尤其在早期綁定是重要因素時(shí)) 訪問(wèn)系統(tǒng),例如 Win32 API 調(diào)用或編程語(yǔ)言的任何其他底層功能 鍵入功能較強(qiáng)(“Visual Basic® 腳本編輯器 [VBScript]”的鍵入功能較弱,而且 JScript® 也不太好) 業(yè)務(wù)邏輯與用戶界面分離,或者 Web 設(shè)計(jì)人員與 Web 開(kāi)發(fā)人員分離 利益與付出同在。就增加開(kāi)發(fā)過(guò)程的復(fù)雜性而論,創(chuàng)建組件解決方案可能更加昂貴。部署和疑難解答也可能變得更困難并成為現(xiàn)實(shí)因素。但是,不要讓眼前的困難阻礙了長(zhǎng)期的利益。如何知道付出的成本是否值得呢?請(qǐng)考慮下列方面:
現(xiàn)在,對(duì)組件可能帶來(lái)的益處有了一定的理解,讓我們繼續(xù)討論。下面的指南將幫助您獲得最大的益處。這些指南可能成為指引您順利建立更穩(wěn)定的、可升級(jí)的、性能更優(yōu)的 ASP 組件應(yīng)用程序的向?qū)А?br> 狀態(tài)管理 建議 一般來(lái)說(shuō),在可能的場(chǎng)合盡量使用無(wú)狀態(tài)的組件和無(wú)狀態(tài)的 ASP 頁(yè)面。組件不應(yīng)需要狀態(tài)從一個(gè)方法調(diào)用到下一個(gè)狀態(tài)。將復(fù)雜的狀態(tài)存儲(chǔ)在數(shù)據(jù)庫(kù)中。對(duì)于簡(jiǎn)單的數(shù)據(jù)、沿用 cookies、QueryString 或在頁(yè)面之間傳遞數(shù)據(jù)的隱藏的表單字段。
詳細(xì)信息 避免使用“ASP 會(huì)話”將提高服務(wù)器的性能,因?yàn)樗?jiǎn)化了代碼路徑并減少了服務(wù)器資源的消耗。如果不使用“ASP 會(huì)話”,請(qǐng)通過(guò)“Internet 服務(wù)管理器” (請(qǐng)參閱“Internet 信息服務(wù) [IIS]”文檔)禁用“會(huì)話”狀態(tài)。也可以在不需要“會(huì)話”的 ASP 頁(yè)面中使用下面的標(biāo)記禁用基于頁(yè)的“會(huì)話”:
<%@ENABLEsessionSTATE=False %> 部署靈活性是另一個(gè)重要方面,尤其在 Web 區(qū)域中運(yùn)行應(yīng)用程序時(shí)。如果依賴“ASP 會(huì)話”, 則給定用戶的請(qǐng)求綁定在指定的 Web 服務(wù)器上,因?yàn)椤皶?huì)話”狀態(tài)是服務(wù)器專用的。在中間層和 Web 服務(wù)器中避免狀態(tài),并使用數(shù)據(jù)庫(kù),將使 ASP 請(qǐng)求可由區(qū)域中任何有效的 Web 服務(wù)器處理。因此, 您將減少競(jìng)爭(zhēng),提供更好的冗余,并允許更多的分布選項(xiàng)。
Q175167 HOWTO: Persisting Values Without Sessions(英文) Q157906 HOWTO: Maintain State Across Pages with VBScript(英文) Don Box 在 ActiveX® Q&A(英文) 一文中 還提出有關(guān) MTS 狀態(tài)管理的更多見(jiàn)解。
Q243543 INFO: Do Not Store STA Objects in Session or application(英文) Q243548 INFO: Design Guidelines for VB Components Under ASP(英文) 分割服務(wù) 建議 將表達(dá)、業(yè)務(wù)和數(shù)據(jù)服務(wù)分離。業(yè)務(wù)組件應(yīng)該實(shí)施業(yè)務(wù)規(guī)則。業(yè)務(wù)組件不應(yīng)包含數(shù)據(jù)訪問(wèn)技術(shù)。那是數(shù)據(jù)層組件的任務(wù)。業(yè)務(wù)組件不應(yīng)包含對(duì) ASP 對(duì)象的引用。
ASP 提供表達(dá)服務(wù)。引用 ASP 的對(duì)象應(yīng)該呈現(xiàn)為 HTML。這些對(duì)象能夠依次調(diào)用對(duì) MTS/COM+ 注冊(cè)的業(yè)務(wù)對(duì)象。
為什么 將應(yīng)用程序分割為單獨(dú)的和截然不同的服務(wù),有以下好處:
更便于組件的重用 支持 Windows DNA model(英文) 更好地孤立疑難問(wèn)題 更靈活的部署選項(xiàng)(去掉服務(wù)的耦合允許在多臺(tái)計(jì)算機(jī)上分布應(yīng)用程序) 常見(jiàn)的陷阱 有一種我們稱為“瑞士軍刀”組件的常見(jiàn)問(wèn)題。 該“瑞士軍”組件將所有服務(wù)合成一體 (就像有螺絲錐、牙簽等 17 種工具的小瑞士軍刀)。 把不相關(guān)的服務(wù)組合到一個(gè)組件中, 使該組件很難使用、理解和維護(hù)。
容易掉入的另一個(gè)陷阱是從業(yè)務(wù)組件中引用 ASP。使 ASP 和業(yè)務(wù)邏輯耦合(通過(guò)使用 請(qǐng)求或響應(yīng)對(duì)象,或在其內(nèi)部構(gòu)建 HTML),不僅限制不同的客戶機(jī)重用您的組件,而且限制了橫向的可伸縮性。引用 ASP 內(nèi)置對(duì)象的對(duì)象應(yīng)該與 Web 服務(wù)器在同一框圍中。理想情況下,由于橫向可伸縮性,業(yè)務(wù)組件可以分布在不同的框圍中??梢灾苯釉?ASP 腳本中提供表達(dá)服務(wù),也可以建立呈現(xiàn)引用 ASP 內(nèi)置對(duì)象的組件的 HTML,并將這些組件保持在 IIS 框圍中。
常見(jiàn)的陷阱 也許最常見(jiàn)的陷阱就是使用了沒(méi)有被設(shè)計(jì)為在 ASP 下運(yùn)行的組件,如“單線程”組件。大多數(shù)開(kāi)發(fā)人員陷入其中,是因?yàn)閷⒆烂鎽?yīng)用程序移向 ASP,或者使用了第三方的控件時(shí)。如果您不能確定組件的線程模型,可以檢查組件的注冊(cè)表項(xiàng)(但不能總依賴它)。
詳細(xì)信息 有關(guān)線程模型及其對(duì) ASP 的影響,請(qǐng)參閱下面的文章:
Don Box's Active Server Pages and COM Apartments(英文) Agility in Server Components 另外,下面的 KB 文章提供了有關(guān)線程問(wèn)題的詳細(xì)內(nèi)容:
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(英文) 安全性 建議 組件不應(yīng)對(duì)它運(yùn)行的用戶環(huán)境做任何假設(shè)。不要訪問(wèn)用戶專用信息,如 HKEY_CURRENT_USER,或桌面計(jì)算機(jī)的專用資源,因?yàn)檫@些對(duì)組件來(lái)講是不可用的。應(yīng)用程序也不要使用 SendKeys 或調(diào)用依賴用戶界面的組件,執(zhí)行通常需要桌面交互的操作,如打開(kāi)對(duì)話框。
Q248348 PRB: SaveSetting and GetSetting Not Available in Visual Basic 6.0 Webclass (IIS Application)(英文) 當(dāng)從 ASP 而不是從桌面客戶機(jī)調(diào)用組件時(shí),打印機(jī)、MAPI 信息和網(wǎng)絡(luò)共享通常“失效”。
有關(guān)詳細(xì)內(nèi)容,請(qǐng)參閱下面的 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(英文) 詳細(xì)信息 有關(guān)安全性的幾點(diǎn)考慮:
啟用哪種 IIS 身份驗(yàn)證方法? 您的 Web 應(yīng)用程序是進(jìn)程內(nèi)的還是進(jìn)程外的? 如果組件以 MTS 或 COM+ 注冊(cè),它是在“服務(wù)器”上還是在庫(kù)軟件包中? 您正在調(diào)用本地 DLL、遠(yuǎn)程 DLL、本地 EXE、遠(yuǎn)程 EXE 嗎? 有關(guān)安全性的詳細(xì)說(shuō)明超出了本文的范圍。但是,由于這個(gè)主題的復(fù)雜性,下面的文章對(duì)從 ASP 組件角度理解問(wèn)題有很大幫助:
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+ 庫(kù)軟件包,請(qǐng)使用 Server.CreateObject 來(lái)避免線程阻塞。
ASP 不能識(shí)別該對(duì)象。 OnStartPage/OnEndPage 頁(yè)面方法沒(méi)有調(diào)用。 ASP 不知道對(duì)象的線程模型。 Server.CreateObject 相當(dāng)于 GetObjectContext.CreateInstance。這表示 ASP 清楚該對(duì)象并知道它的線程模型。另外,如果 ASP 頁(yè)面是事務(wù)性的,則通過(guò)調(diào)用 Server.CreateObject 可使組件與 ASP 頁(yè)面在同一事務(wù)中。(請(qǐng)注意,事務(wù)性的頁(yè)面可能意味著可避免的業(yè)務(wù)規(guī)則與表達(dá)層的耦合。)
常見(jiàn)的陷阱 如果對(duì)象處于防火墻后面,可能需要調(diào)用 CreateObject。請(qǐng)參閱 Q193230 PRB: Server.CreateObject Fails when Object is Behind Firewall(英文) 以獲得詳細(xì)信息。
為什么 腳本客戶機(jī)使用 Variant。 COM 服務(wù)器可使用指定的數(shù)據(jù)類型。當(dāng)您將指定的數(shù)據(jù)類型按值傳遞給 COM 服務(wù)器時(shí), COM 服務(wù)器可以毫無(wú)問(wèn)題地接收。但除 Variant 外,其他按引用參數(shù)無(wú)法“回送”給 ASP 腳本。
常見(jiàn)的陷阱 最常見(jiàn)的錯(cuò)誤之一是“類型不匹配”。這通常是因?yàn)榘匆?傳遞到 COM 對(duì)象的變量不是 Variant。通常的解決方法是按值傳遞參數(shù)或者將參數(shù)變?yōu)?Variant。
Q197956 PRB: Passing Parameters By Reference to a VB COM Object(英文) Q197957 PRB: Passing Parameters By Reference to a VC COM Object(英文) 事件 建議 避免調(diào)用等待其他組件返回事件的組件。
組件方法應(yīng)盡快返回對(duì) ASP 的執(zhí)行。請(qǐng)考慮使用“MSMQ”或“COM+ 排隊(duì)組件” 來(lái)提供異步調(diào)用 — 或當(dāng)要做的工作正長(zhǎng)時(shí)間運(yùn)行并且不必聯(lián)機(jī)運(yùn)行時(shí)。
請(qǐng)異步地分派工作項(xiàng)目,而不要讓 ASP 等待長(zhǎng)時(shí)間運(yùn)行的進(jìn)程結(jié)束。然后您將從 ASP 給客戶機(jī)返回一個(gè)響應(yīng)。一旦工作項(xiàng)目完成,您可以用電子郵件或其他方法通知客戶機(jī)(請(qǐng)參閱下面內(nèi)容)。
為什么 ASP 并不是為處理事件設(shè)計(jì)的。為了優(yōu)化服務(wù)器性能,請(qǐng)盡快返回對(duì) HTTP 請(qǐng)求的響應(yīng)。
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 訪問(wèn) ASP 內(nèi)置對(duì)象(如響應(yīng)、請(qǐng)求、服務(wù)器等等)。無(wú)論何時(shí)請(qǐng)盡量避免使用 ScriptingContext 對(duì)象、 OnStartPage 和 OnEndPage。
常見(jiàn)的陷阱 還記得 ASP 0115 錯(cuò)誤嗎? 但愿您不用和它苦苦斗爭(zhēng)了。 如果還在為其苦惱, 建議您參閱 Troubleshooting with the IIS Exception Monitor(英文)。
ASP 0115 錯(cuò)誤不是總出現(xiàn)在開(kāi)發(fā)人員的控制下 — 但多數(shù)時(shí)候是這樣,錯(cuò)誤處理可能已經(jīng)避免了很多這種情況的發(fā)生,還可能在其發(fā)生時(shí)幫助解決了它們。
總之,最大的問(wèn)題為跳過(guò)錯(cuò)誤處理或沒(méi)有包含有用的診斷信息。
在 COM 中,罕有跨越組件的界限傳播異常的情況。捕獲異常 — 但返回 HResults,以向調(diào)用者傳送失敗信息。
詳細(xì)信息 下面的文章提供了有關(guān)有效錯(cuò)誤處理的應(yīng)用示例:
Fitch & Mather Stocks: Web Application Design(英文) 全局變量 建議 避免在組件中使用全局變量。在 Visual Basic 術(shù)語(yǔ)中,這表示在標(biāo)準(zhǔn)的 .BAS 模塊中沒(méi)有 Public 或 Global 變量。
為什么 Global 變量并不是真正意義上的全局。每個(gè)線程都有自己的副本。如果幾種方法恰好在同一線程中執(zhí)行,它們將看到相同的變量;否則它們?cè)L問(wèn)的是這些變量的不同副本。這意味著您可能給一個(gè)全局變量賦了值(在線程 A 中),但其另一個(gè)用戶(在線程 B 中執(zhí)行)看不到新值。
其原因是 Visual Basic 內(nèi)部使用“線程本地存儲(chǔ) (TLS)”來(lái)引用全局變量。這意味著每個(gè)線程都有自己的 Public 變量的副本,并且因?yàn)樗嬖诙鄠€(gè)副本,全局?jǐn)?shù)據(jù)并不是真正“全局的”。也就是說(shuō),恰好在同一線程中運(yùn)行的用戶才會(huì)訪問(wèn)到同一個(gè)變量,不論他們是否期望如此。
常見(jiàn)的陷阱 如果在標(biāo)準(zhǔn) .BAS 模塊中使用 Public 變量,當(dāng)不同線程向還想使用同一個(gè)數(shù)據(jù)的不同用戶請(qǐng)求提供服務(wù)時(shí),這個(gè)數(shù)據(jù)可能已被破壞了。
Black Belt Programming - Create Worker Threads in DLLs COMponent Builder - Create Efficient Multithreaded Apps 另外,下面 Daniel Appleman 所著的文章 很好地概述了 Visual Basic 中多線程的工作原理: A Thread to Visual Basic(英文)
在 IIS 的同一框圍中運(yùn)行引用 ASP 內(nèi)置對(duì)象的組件。 在應(yīng)用程序服務(wù)器上運(yùn)行數(shù)據(jù)庫(kù)組件。 在哪一臺(tái)計(jì)算機(jī)上運(yùn)行業(yè)務(wù)組件很重要。倘若您去掉業(yè)務(wù)組件與任何 ASP 的耦合,您就可以根據(jù)您的應(yīng)用程序設(shè)計(jì)、計(jì)算機(jī)的可用性和測(cè)試,來(lái)自由選擇。 當(dāng)然還有例外。但這些是指南的好的開(kāi)始。
對(duì)象引用 ASP 內(nèi)置對(duì)象,會(huì)與您的 Web 服務(wù)器進(jìn)行大量通訊,并且由于它們是表達(dá)層的一部分,因此它們就在那里。
數(shù)據(jù)庫(kù)或?qū)?shù)據(jù)極為敏感的邏輯可能在數(shù)據(jù)庫(kù)的存儲(chǔ)過(guò)程中。將數(shù)據(jù)訪問(wèn)組件置于應(yīng)用程序服務(wù)器而非數(shù)據(jù)庫(kù)上,避免了組件之間的昂貴調(diào)用。相反,數(shù)據(jù)訪問(wèn)組件則利用 SQL Server 通信(如 TCP/IP)與數(shù)據(jù)庫(kù)更有效地通信。
常見(jiàn)的陷阱 您應(yīng)當(dāng)嘗試避免下列問(wèn)題:
當(dāng)橫向可伸縮性較為合適之后,繼續(xù)追求從您的計(jì)算機(jī)開(kāi)始的縱向可伸縮性。 忽視了防火墻的考慮(幫自己一個(gè)忙。如果計(jì)算機(jī)間的產(chǎn)品環(huán)境有防火墻,則在測(cè)試方案中添加防火墻。) 將引用 ASP 內(nèi)置對(duì)象的組件置于與 IIS 服務(wù)器分離的計(jì)算機(jī)上(回調(diào)和編組 ASP 內(nèi)置對(duì)象的成本很高。) 使用組件內(nèi)部的后期綁定(這產(chǎn)生對(duì) GetIdsOfNames 的額外調(diào)用,這在分布式應(yīng)用程序中可能很昂貴。盡量使用早期綁定。) 按引用傳遞參數(shù)(這產(chǎn)生更多的編組開(kāi)銷(xiāo)。盡可能“按值”傳遞參數(shù)。) 成功地從 IIS 調(diào)用遠(yuǎn)程 MTS 組件也可能很棘手。一個(gè)簡(jiǎn)單有效、既提高性能又簡(jiǎn)化安全性問(wèn)題的解決方案,是調(diào)用中間的 MTS/COM+ 軟件包/應(yīng)用程序。早期綁定可減少網(wǎng)絡(luò)路程段,提高性能。如果您使用“服務(wù)器”軟件包/應(yīng)用程序,則可以設(shè)置軟件包/應(yīng)用程序的運(yùn)行標(biāo)識(shí)。這個(gè)技術(shù)將在 KB 文章 159311 Instantiating Remote Components in Microsoft Transaction Server and Internet Information Server 中討論。
詳細(xì)信息 如果已經(jīng)解耦了服務(wù),特別是已使 ASP 在業(yè)務(wù)組件之外,則分布將相當(dāng)靈活。您就可以更多地考慮框圍,并根據(jù)需要分散組件以解決隨之而來(lái)的可伸縮性和性能問(wèn)題。如何知道?進(jìn)行測(cè)試。如何測(cè)試?請(qǐng)看下面的基本指南:
若要測(cè)試 Web 站點(diǎn)的可靠性,請(qǐng)剖析計(jì)算機(jī)并檢查錯(cuò)誤。 若要測(cè)試性能,請(qǐng)查看每秒可處理多少 ASP 請(qǐng)求。 若要測(cè)試可伸縮性,請(qǐng)?jiān)O(shè)置每秒需要處理多少 ASP 請(qǐng)求的閥值。用重要的工具考驗(yàn)應(yīng)用程序——添加用戶直到性能壞到不能接受為止。 加強(qiáng)對(duì)應(yīng)用程序的測(cè)試非常重要,因?yàn)樾枰┞哆\(yùn)轉(zhuǎn)條件和單瀏覽器測(cè)試中不會(huì)出現(xiàn)的其他問(wèn)題。 有關(guān)對(duì)應(yīng)用程序加強(qiáng)測(cè)試的詳細(xì)內(nèi)容, 請(qǐng)參閱 I Can't Stress It Enough -- Load Test Your ASP Application(英文)。
結(jié)論 正如所見(jiàn),有一些事情在整個(gè)開(kāi)發(fā)中需要時(shí)刻注意。在此,應(yīng)用程序指南所涉及的諸多因素已全部闡明,因?yàn)樗鼈冇兄趶氐妆苊鈬?yán)重失誤。在整個(gè)開(kāi)發(fā)周期中遵循本文中略述的幾個(gè)指南,不僅可以避免一些額外的工作,而且能夠提交可收縮的、可靠的、高性能的基于 ASP 組件的解決方案。