改進(jìn)性能與樣式的 25+ ASP 技巧(2)
發(fā)表時(shí)間:2023-08-08 來源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]技巧 6:妙用 Session 對(duì)象 在肯定了在 Applications 和 Sessions 中緩存的優(yōu)點(diǎn)之后,我們建議您避免使用 Session 對(duì)象。下面將會(huì)談到,當(dāng)用于忙碌站點(diǎn)時(shí),Sess...
技巧 6:妙用 Session 對(duì)象
在肯定了在 Applications 和 Sessions 中緩存的優(yōu)點(diǎn)之后,我們建議您避免使用 Session 對(duì)象。下面將會(huì)談到,當(dāng)用于忙碌站點(diǎn)時(shí),Sessions 有幾個(gè)缺點(diǎn)。所謂忙碌,通常是指站點(diǎn)每秒請(qǐng)求數(shù)百頁或同時(shí)有數(shù)千個(gè)用戶。該技巧對(duì)于必須進(jìn)行水平擴(kuò)展的站點(diǎn),即那些利用多個(gè)服務(wù)器來適應(yīng)負(fù)載或執(zhí)行容錯(cuò)功能的站點(diǎn)來說,更加重要。對(duì)于較小的站點(diǎn),如 intranet 站點(diǎn),Sessions 的便利,與開銷相比也是值得的。
為了翻新,ASP 自動(dòng)為每個(gè)訪問 Web 服務(wù)器的用戶創(chuàng)建一個(gè) Session。每個(gè) Session 有大約 10 KB 內(nèi)存開銷(在存儲(chǔ)在 Session 中的任何數(shù)據(jù)中是最高的),并使所有的請(qǐng)求都慢了一點(diǎn)。Session 一直保持活動(dòng)狀態(tài),直到達(dá)到可配置的超時(shí)(通常 20 分鐘)為止。
Session 最大的問題不是性能而是可伸縮性。Session 不能跨越 Web 服務(wù)器;一旦在一個(gè)服務(wù)器上創(chuàng)建了 Session,它的數(shù)據(jù)就保持在那里。這意味著,如果您在 Web 領(lǐng)域中使用 Sessions,您將不得不為每個(gè)用戶的請(qǐng)求設(shè)計(jì)一種策略,以便始終將這些請(qǐng)求引向用戶的 Session 所在的服務(wù)器。這被稱為將用戶“粘”到 Web 服務(wù)器上。術(shù)語“粘性會(huì)話”即來源于此。由于 Session 沒有保持到磁盤上,所以,當(dāng) Web 服務(wù)器崩潰時(shí),被“粘住”的用戶將丟失他們的 Sessions 狀態(tài)。
用于實(shí)施粘性會(huì)話的策略包括硬件和軟件解決方案。如 Windows 2000 Advanced Server 中的網(wǎng)絡(luò)負(fù)載平衡解決方案和 Cisco 公司的“本地指向器”解決方案可以實(shí)施粘性會(huì)話,但以犧牲一些可伸縮性為代價(jià)。這些解決方案并不完美。我們不主張您現(xiàn)在全盤推翻您的軟件解決方案(我們過去常用 ISAPI 篩選器和 URL 矯直對(duì)方案進(jìn)行檢查)。
Application 對(duì)象也不能跨越服務(wù)器;如果您需要在 Web 領(lǐng)域內(nèi)共享并更新 Application 數(shù)據(jù),則需要使用后端數(shù)據(jù)庫。但只讀的 Application 數(shù)據(jù)在 Web 領(lǐng)域中仍然有用。
如果只是為了增加正常運(yùn)行時(shí)間(用于處理故障轉(zhuǎn)移和服務(wù)器維護(hù)),大多數(shù)執(zhí)行重要任務(wù)的站點(diǎn)將需要部署至少兩臺(tái) Web 服務(wù)器。所以,在設(shè)計(jì)執(zhí)行重要任務(wù)的應(yīng)用程序時(shí),您將需要實(shí)施“粘性會(huì)話”,或者簡單地避開 Sessions 以及其他任何在單個(gè) Web 服務(wù)器上存儲(chǔ)用戶狀態(tài)的狀態(tài)管理技術(shù)。
如果當(dāng)前沒有使用 Sessions,請(qǐng)確保將它們關(guān)閉。可以通過“Internet 服務(wù)管理器”(請(qǐng)參閱 ISM 文檔)來為應(yīng)用程序執(zhí)行該操作。如果決定使用 Sessions,可以采取幾個(gè)方法來將對(duì)性能的影響降低到最小。
可以將不需要 Sessions 的內(nèi)容(如“幫助”屏幕、訪問者區(qū)域等)移動(dòng)到關(guān)閉了 Sessions 的、單獨(dú)的 ASP 應(yīng)用程序中?梢灾痦撎崾 ASP:在給定的頁中您不需要 Session 對(duì)象;使用位于 ASP 頁頂端的如下指令:
<% @EnableSessionState=False %>
使用該指令的一個(gè)很好的原因是,Session 給框架集帶來了有趣的問題。ASP 保證任何時(shí)候只執(zhí)行一個(gè)來自 Session 的請(qǐng)求。這樣可以確保如果瀏覽器為一個(gè)用戶請(qǐng)求了多個(gè)頁時(shí),在每一時(shí)刻只有一個(gè) ASP 請(qǐng)求將進(jìn)入 Session;這就避免了在訪問 Session 對(duì)象時(shí)出現(xiàn)多線程問題。遺憾的是,結(jié)果,框架集中的所有頁均被以串行化方式繪制,一個(gè)接一個(gè)地,而不是同時(shí)地。這樣,用戶可能不得不等待很長時(shí)間才能得到所有框架內(nèi)容。這意味著:如果某些框架頁不信任 Session,一定要使用 @EnableSessionState=False 指令告訴 ASP。
作為使用 Session 對(duì)象的替代方式,有很多方法可以用來管理 Session 狀態(tài)。對(duì)于狀態(tài)數(shù)量較小的情況(不到 4 KB),通常建議使用 Cookies、QueryString 變量和隱藏形式的變量。對(duì)于較大數(shù)量的數(shù)據(jù),如購物推車,則使用后端數(shù)據(jù)庫是最合適的選擇。關(guān)于在 Web 服務(wù)器領(lǐng)域中的狀態(tài)管理技術(shù)已經(jīng)有很多資料。詳細(xì)信息,請(qǐng)參閱 會(huì)話狀態(tài)(英文)。
技巧 7:在 COM 對(duì)象中封裝代碼
如果您有很多 VBScript 或 JScript,那么您可以通過把代碼移動(dòng)到已編譯的 COM 對(duì)象來經(jīng)常改進(jìn)它們的性能。已編譯的代碼通常比被解釋代碼運(yùn)行得更快。已編譯的 COM 對(duì)象可以通過“早期綁定”訪問其他 COM 對(duì)象,這種調(diào)用 COM 對(duì)象方法的手段,比腳本所使用的“后期綁定”更有效。
將代碼封裝在 COM 對(duì)象種有如下好處(超越性能):
COM 對(duì)象是將表達(dá)邏輯與業(yè)務(wù)邏輯分隔開來的好辦法。
COM 對(duì)象啟用了代碼重用。
很多開發(fā)商發(fā)現(xiàn),用 VB、C++ 或 Visual J++ 書寫的代碼,比 ASP 更容易調(diào)試。
COM 對(duì)象有一些缺點(diǎn),包括初始開發(fā)時(shí)間以及需要不同的編程技巧。需要警告您的是,封裝“少”量的 ASP 可能會(huì)導(dǎo)致性能降低,而不是提高。通常,在少量 ASP 代碼封裝到 COM 對(duì)象時(shí)出現(xiàn)這樣的情況。這時(shí)候,創(chuàng)建和調(diào)用 COM 對(duì)象的開銷,超過了已編譯代碼的好處。至于 ASP 腳本和 COM 對(duì)象代碼怎樣合并才能產(chǎn)生最佳性能還有待測試。注意,與 Windows NT(R) 4.0/IIS 4.0 相比,Microsoft 已經(jīng)在 Windows 2000/IIS 5.0 中極大地提高了腳本和 ADO 性能。這樣,已編譯代碼對(duì) ASP 代碼的性能優(yōu)勢已經(jīng)隨著 IIS 5.0 的引入而降低。
有關(guān)在 ASP 中使用 COM 對(duì)象的優(yōu)缺點(diǎn)的更多討論,請(qǐng)參閱 ASP 組件準(zhǔn)則和用 COM 和 Microsoft Visual Basic 6.0 對(duì)分布式應(yīng)用程序進(jìn)行編程(英文)。如果您的確部署了 COM 組件,要對(duì)它們進(jìn)行強(qiáng)度測試是非常重要的。實(shí)際上,所有 ASP 應(yīng)用程序都應(yīng)當(dāng)作為正式過程進(jìn)行強(qiáng)度測試。
技巧 8:晚點(diǎn)獲取資源,早點(diǎn)釋放資源
這是個(gè)小技巧。通常,最好晚點(diǎn)獲取資源而要早點(diǎn)釋放資源。這些資源包括 COM 對(duì)象、文件句柄和其他資源。
ADO 連接和記錄集是這種優(yōu)化的首要目標(biāo)。當(dāng)您使用完記錄集,就是說用它的數(shù)據(jù)打印完一個(gè)表格后,請(qǐng)立即將它釋放,而不是等到頁的末尾。將您的 VBScript 變量設(shè)置為 Nothing 是最好的做法。不要讓記錄集簡單地脫離作用域。同時(shí),應(yīng)當(dāng)釋放任何有關(guān)的 Command 或 Connection 對(duì)象。(不要忘了對(duì)記錄集或“連接”調(diào)用 Close(),在將它們?cè)O(shè)置為 = Nothing 之前。)這將縮短數(shù)據(jù)庫必須為您調(diào)整資源的時(shí)間跨度,并將數(shù)據(jù)庫連接盡可能快地釋放給連接池。
技巧 9:進(jìn)程外的執(zhí)行將犧牲可靠性
ASP 和 MTS/COM+ 都有允許您以可靠性換取性能的配置選項(xiàng)。當(dāng)建立和部署應(yīng)用程序時(shí),應(yīng)當(dāng)理解這種交換。
ASP 選項(xiàng)
ASP 應(yīng)用程序可以配置為以三種方式之一運(yùn)行。在 IIS 5.0 中引入了術(shù)語“隔離級(jí)”來描述這些選項(xiàng)。三個(gè)隔離級(jí)值分別是低、中和高:
低級(jí)隔離。該隔離級(jí)在所有版本的 IIS 中受到支持,并且是最快的。它在主 IIS 進(jìn)程 Inetinfo.exe 中執(zhí)行 ASP。如果 ASP 應(yīng)用程序崩潰,則 IIS 也將崩潰。(要在 IIS 4.0 下重新啟動(dòng) IIS,Web 站點(diǎn)管理員需要使用工具,如 InetMon,來監(jiān)視站點(diǎn),如果服務(wù)器失敗,將運(yùn)行批處理文件來重新啟動(dòng)服務(wù)器。而 IIS 5.0 則引入了可靠的重新啟動(dòng),它將自動(dòng)重新啟動(dòng)失敗的服務(wù)器。)
中級(jí)隔離。IIS 5.0 引入了這個(gè)新隔離級(jí),它稱為進(jìn)程外的,這是因?yàn)?ASP 運(yùn)行在 IIS 進(jìn)程之外。在中級(jí)隔離中,所有被配置按“中級(jí)”運(yùn)行的 ASP 應(yīng)用程序,將共享單個(gè)進(jìn)程空間。這將減少在一個(gè)服務(wù)器上運(yùn)行多個(gè)進(jìn)程外的 ASP 應(yīng)用程序所需的進(jìn)程數(shù)。中級(jí)是 IIS 5.0 中默認(rèn)的隔離級(jí)。
高級(jí)隔離。在 IIS 4.0 和 IIS 5.0 中受到支持,高級(jí)隔離也是進(jìn)程外的。如果 ASP 崩潰,則 Web 服務(wù)器并不崩潰。ASP 應(yīng)用程序?qū)⒃谙乱粋(gè) ASP 請(qǐng)求時(shí)自動(dòng)重新啟動(dòng)。使用高級(jí)隔離,每個(gè)被配置為按高級(jí)運(yùn)行的 ASP 應(yīng)用程序,將在其自己的進(jìn)程空間中運(yùn)行。這樣可以保護(hù) ASP 應(yīng)用程序彼此不受干擾。它的缺點(diǎn)是它需要為每個(gè) ASP 應(yīng)用程序建立獨(dú)立的進(jìn)程。當(dāng)需要在一個(gè)服務(wù)器上主持十多個(gè)應(yīng)用程序時(shí),會(huì)增加很多開銷。
那么,哪個(gè)選項(xiàng)是最好的呢?在 IIS 4.0 中,運(yùn)行進(jìn)程外的應(yīng)用程序會(huì)極大地影響性能。在 IIS 5.0 中,做了許多工作,使得進(jìn)程外運(yùn)行 ASP 應(yīng)用程序?qū)π阅墚a(chǎn)生的影響降到了最低。實(shí)際上,在大多數(shù)測試中,在 IIS 5.0 中的 ASP 進(jìn)程外應(yīng)用程序,要比 IIS 4.0 中的進(jìn)程內(nèi)應(yīng)用程序運(yùn)行得更快。無論如何,進(jìn)程內(nèi)(低隔離級(jí))在兩種平臺(tái)上仍然產(chǎn)生了最好的性能。但是,如果您的命中率相對(duì)較低或最大吞吐量較低,選擇低隔離級(jí)不會(huì)有太大的好處。所以,除非您需要每個(gè) Web 服務(wù)器每秒處理數(shù)百或數(shù)千個(gè)頁面,否則沒有必要選擇低隔離級(jí)。同樣,應(yīng)當(dāng)測試多種配置并判斷哪種情形最適合您。
注意: 當(dāng)您進(jìn)程外運(yùn)行 ASP 應(yīng)用程序(中級(jí)或高級(jí)隔離)時(shí),則在 NT4 上它們將運(yùn)行在 MTS 中,而在 Windows 2000 上它們將運(yùn)行在 COM+ 中。即,在 NT4 上它們運(yùn)行在 Mtx.exe 中,而在 Windows 2000 上它們運(yùn)行在 DllHost.exe 中。在“任務(wù)管理器”中,您可以看見這些正在運(yùn)行的進(jìn)程。還可以看見 IIS 如何為進(jìn)程外的 ASP 應(yīng)用程序配置 MTS 程序包或 COM+ 應(yīng)用程序。
COM 選項(xiàng)
COM 組件也有三個(gè)配置選項(xiàng),雖然與 ASP 選項(xiàng)不完全相似。COM 組件可以被:“不配置”、配置為“庫應(yīng)用程序”或配置為“服務(wù)器應(yīng)用程序”。“不配置”是指不向 COM+ 注冊(cè)組件。組件將運(yùn)行在調(diào)用者的進(jìn)程空間,就是說,它們是“進(jìn)程中”的!皫鞈(yīng)用程序”也是進(jìn)程中的,但受惠于 COM+ 的服務(wù),包括安全性、事務(wù)和環(huán)境支持!胺⻊(wù)器應(yīng)用程序”被配置為在其自己的進(jìn)程空間中運(yùn)行。
您可能看到,不配置的組件比庫應(yīng)用程序優(yōu)點(diǎn)稍微多些。您還可能看到“庫應(yīng)用程序”比“服務(wù)器應(yīng)用程序”有很大的性能優(yōu)點(diǎn)。這是因?yàn)椤皫鞈?yīng)用程序”與 ASP 運(yùn)行在同一個(gè)進(jìn)程中,而“服務(wù)器應(yīng)用程序”則運(yùn)行在自己的進(jìn)程中。內(nèi)部進(jìn)程調(diào)用的開銷要比進(jìn)程內(nèi)調(diào)用的開銷大得多。而且,當(dāng)在進(jìn)程之間傳遞數(shù)據(jù)(如記錄集)時(shí),必須在兩個(gè)進(jìn)程之間復(fù)制所有的數(shù)據(jù)。
缺點(diǎn)!當(dāng)使用“COM 服務(wù)器應(yīng)用程序”時(shí),如果要在 ASP 和 COM 之間傳遞對(duì)象,請(qǐng)確保對(duì)象實(shí)現(xiàn)“按值匯集”,即 MBV。實(shí)現(xiàn) MBV 的對(duì)象將其自身從一個(gè)進(jìn)程復(fù)制到另一個(gè)進(jìn)程。這比另一種方式好,在另一種方式中,對(duì)象留在創(chuàng)建它的進(jìn)程中,而其他進(jìn)程則重復(fù)調(diào)用創(chuàng)建使用該對(duì)象的進(jìn)程。被斷開連接的 ADO 記錄集將是按值匯集的,已連接的記錄集則不是。Scripting.Dictionary 并不實(shí)現(xiàn) MBV,不會(huì)在進(jìn)程之間傳遞。最后,要另外告訴 VB 程序員的是:MBV 不是通過傳遞參數(shù)ByVal 獲得的。MBV 是由原始組件創(chuàng)作者實(shí)現(xiàn)的。
怎么辦?
如果您想要以性能與可靠性的合理交換來完成您的配置,我們的推薦如下:
在 IIS 4.0 上,使用 ASP 的低隔離級(jí)別,并使用“MTS 服務(wù)器包”。
在 IIS 5.0 上,使用 ASP 的中隔離級(jí)別,并使用“COM+ 庫應(yīng)用程序”。
這些是很一般的準(zhǔn)則;通常讓公司以中或高隔離級(jí)別運(yùn)行 ASP,而單一目的的 Web 服務(wù)器可運(yùn)行于低隔離級(jí)別。請(qǐng)權(quán)衡折中并自行決定滿足需求的配置。
技巧 10:顯式使用選項(xiàng)
在 .asp 文件中顯式使用選項(xiàng) Explicit。置于 .asp 文件開頭的這一指令,強(qiáng)制開發(fā)人員聲明所有要使用的變量。許多開發(fā)人員認(rèn)為這有助于調(diào)試應(yīng)用程序,因?yàn)樗苊饬隋e(cuò)誤鍵入變量名稱而不經(jīng)意地新建變量(例如,MyXLMString=... 而非 MyXMLString=)。
也許更重要的是,聲明的變量比未聲明的變量快。實(shí)際上,腳本運(yùn)行時(shí),在每次使用未聲明變量時(shí)按照名稱引用。而聲明的變量,在編譯或運(yùn)行時(shí)分配了序號(hào)。這樣,聲明的變量按照該序號(hào)引用。由于選項(xiàng) Explicit 強(qiáng)制變量聲明,因此保證聲明了所有變量而實(shí)現(xiàn)快速訪問。
技巧 11:在子例程和函數(shù)中使用局部變量
局部變量是在子例程和函數(shù)中聲明的變量。在子例程和函數(shù)中,局部變量訪問要快于全局變量訪問。使用局部變量還可以使代碼更加清晰,因此盡可能使用局部變量。
技巧 12:將常用數(shù)據(jù)復(fù)制到腳本變量
在 ASP 中訪問 COM 時(shí),應(yīng)該將常用的對(duì)象數(shù)據(jù)復(fù)制到腳本變量中。這將削減 COM 方法的調(diào)用,COM 方法的調(diào)用與訪問腳本變量相比,要相對(duì)昂貴些。在訪問 Collection 和 Dictionary 對(duì)象時(shí),這一技術(shù)也可以削減了昂貴的查找。
通常,如果打算多次訪問對(duì)象數(shù)據(jù),請(qǐng)將數(shù)據(jù)放入腳本變量。該優(yōu)化的主要目標(biāo)是 Request 變量(Form 和 QueryString 變量)。例如,您的站點(diǎn)可能傳遞一個(gè)名為 UserID 的 QueryString。假定該 UserID 變量要在特定頁中引用 12 次。請(qǐng)不要調(diào)用 Request("UserID") 12 次,而在 ASP 頁的開頭將 UserID 賦予某個(gè)變量。然后就在頁中使用該變量。這將節(jié)省 11 次 COM 方法調(diào)用。
在實(shí)際中,訪問 COM 屬性或方法暗藏著繁復(fù)的過程和大量的開銷。下面是一個(gè)示例,它只是些相當(dāng)普通的代碼(從語法上講):
Foo.bar.blah.baz = Foo.bar.blah.qaz(1)
If Foo.bar.blah.zaq = Foo.bar.blah.abc Then ' ...
在運(yùn)行這段代碼時(shí),將發(fā)生下列事件:
變量 Foo 被解析為全局變量。
變量 bar 被解析為 Foo.的成員。這將產(chǎn)生 COM 方法調(diào)用。
變量 blah 被解析為 Foo.bar 的成員。這也將產(chǎn)生 COM 方法調(diào)用。
變量 qaz 被解析為 foo.bar.blah 的成員。是的,這也將產(chǎn)生 COM 方法調(diào)用。
調(diào)用 Foo.bar.blah.quaz(1)。又一次產(chǎn)生 COM 方法調(diào)用。理解這幅圖了嗎?
執(zhí)行步驟 1 到 3 將再次解析 baz。系統(tǒng)不知道調(diào)用 qaz 是否更改對(duì)象模型,因此步驟 1 到 3 必須再次執(zhí)行解析 baz。
將 baz 解析為 Foo.bar.blah 的成員。進(jìn)行屬性置入。
再次執(zhí)行步驟 1 到 3 并解析 zaq。
再次執(zhí)行步驟 1 到 3 并解析 abc。
正如所見,這是非常可怕的低效率(而且非常慢)。用 VBScript 編寫該代碼實(shí)現(xiàn)的快速方法為:
Set myobj = Foo.bar.blah ' 對(duì) blah 做一次解析
Myobj.baz = myobj.qaz(1)
If Myobj.zaq = Myobj.abc Then '...
如果您使用的是 VBScript 5.0 或更高版本,則可用 With 語句來寫這段代碼:
With Foo.bar.blah
.baz = .qaz(1)
If .zaq = .abc Then '...
...
End With
請(qǐng)注意該技巧對(duì) VB 編程同樣有效。