1. 程式人生 > >ASP.NET 2.0 快取和過期、連線池

ASP.NET 2.0 快取和過期、連線池

問:使用 .js 和級聯樣式表 (CSS) include 時是否有什麼技巧,以便對它們進行快取,而不必在每次發出請求時都進行提取?

答:為了實現這種型別的快取,您可以使用 IIS 管理單元中的 HTTP 標頭屬性表,通過選中“啟用內容過期”複選框來啟用內容過期。這樣會使用 Expires 標頭為該 HTTP 響應新增標記(請參閱啟用內容過期)。如果您在使用 ASP、ASP.NET、PHP 等,則還可以使用 Cache-Control 標頭來獲得相同的結果。

Microsoft® Internet Explorer 支援可用於相似用途的 META 標記,但是 HTTP 響應標頭仍然是首選的方式。使用此方式,無需更新任何 HTML 內容,該設定會基於 IIS 中的站點、虛擬根或檔案而進行全域性應用。

有關在物件快取方面執行效能極好的站點示例,請使用一個 HTTP 除錯代理,如 Fiddler(它會記錄客戶端和 Web 伺服器之間的所有 HTTP 通訊),然後訪問 office.microsoft.com。當您檢視 Fiddler 中的跟蹤時,EXPIRES 列中的大多數物件就都會設定一個 Expiration,並且不會再次請求。圖 1 顯示了 Fiddler 左側的列表檢視。您會注意到,Office Online 會在事務上傳送一個 HTTP/1.0 EXPIRES 日期(例如 Mon, 01 Nov 2004)或一個 HTTP/1.1 Cache-Control(例如 max-age=86400)標頭。

問:對於檢視狀態資料,是否存在一個推薦的大小限制,可幫助避免明顯的效能下降?

答:當您下載大量檢視狀態資料時,如果考慮使用者的體驗,則會認識到使用者的痛苦閾值是真正的限制因素,而在伺服器出現問題之前就已經超過了此閾值。請參閱 Chapter 6 — Improving ASP.NET Performance 上標題為“View State”的章節。

如果不考慮伺服器規格、網格體系結構和客戶端的話,就很難說檢視狀態有多大。Don't let the BinaryFormatter get at it! 上的 blog 張貼說明了如何將 LosFormatter 和 BinaryFormatter 用於檢視狀態,以及經過序列化的型別如何影響檢視狀態大小。

Whidbey will brings us a shorter viewstate, guaranteed! 上的跟貼說明了在 .NET Framework 2.0 中它發生了怎樣的變化。

有關經過批准的新“檢視狀態”的資訊,請參閱 2004 年 10 月 MSDN®Magazine 中的一篇文章,“Speed Up Your Site with the Improved View State in ASP.NET 2.0”,網址是 Speed Up Your Site with the Improved View State in ASP.NET 2.0。

問:最近我遇到了一個問題,一個層上的所有計算機(大約 18 個)差不多同時回收了 W3wp(輔助程序)。我想知道在所有這些不同的計算機上計時器是如何保持同步的呢。我正在使用應用程式中心 (Application Center),並且最近執行了推入內容的操作。

答:計時器是在應用程式池啟動時開始的。最常見的做法是在對應用程式進行重大更改之後(推入內容)回收應用程式池,這在群集中可能已經進行了自動化處理,因此所有池幾乎都在同時啟動。

問:在 ADO.NET 中,一個程序可以建立多少連線池?我知道,如果我有 n 個連線字串的話,將有 n 個池。但是這個 n 是否具有最大值呢?另外,MSDN 文章中指出,一旦建立了連線池,那麼這些連線池在活動程序結束之前就不會被破壞。非活動池或空池的維護涉及的系統開銷很小。非活動池是否會被剪除?

答:如果您問可以建立多少池的話,答案是每個應用程式域使用的每個連線字串一個池。對於整合的安全連線,會根據不同使用者的數量而建立子池。如果您在某個特定的應用程式域中使用 n 個連線字串,則將擁有 n 個池。連線池是以每個應用程式域為基礎建立的,而不是根據每個程序建立的。池是在有使用者連線請求的需要時建立的。還有一個邏輯用於剪除池,甚至在使用者沒有指定其他設定的情況下,可在一段非活動時間之後刪除這些池。

可以建立的池數量沒有上限。您提到的 MSDN 註釋對於 Microsoft .NET Framework 1.0 和 1.1 是正確的。如果您沒有指定最小池大小的話,這些池在非活動時間之後將一直保留,即使它們是空的也是如此。在 .NET Framework 2.0 中,一段非活動時間之後,Framework 將刪除該池。

問:我有一個關於 HTML 頁截止日期的問題(Windows? XP 和 Microsoft Internet Explorer 6.x)。在 Expire1.htm 中,我指定了頁立即過期:

<html>
<head>
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
<META HTTP-EQUIV="expires" CONTENT="-1">
</head><body>
<a href="HtmlPage1.htm">HtmlPage1.htm</a>
</body>
</html>
使用 Internet Explorer 時,如果我瀏覽到 Expire1.htm(使用 HTTP,不是 HTTPS),則當我單擊連結之後,會被帶入 HtmlPage1.htm。如果我更改 Expire1.htm 的內容,然後單擊“Back”按鈕,得到的是 Expire1.htm 的舊內容,而不是新內容。在 Internet Explorer 中,我選擇了在每次訪問該頁時都“檢查”儲存頁的更新版本的選項。

答:此行為是設計使然。通過使用 META 標頭,您可以依賴於 MSHTML 來判斷是否刪除快取中的內容,快取中內容的刪除只由 MSHTML 在這些內容通過安全套接字層 (SSL) 下載時執行。因為您使用“Forward”和“Back”按鈕,所以不是真正的導航;您只是在顯示前面下載的內容。如果連線不是一個 SSL 連線,MSHTML 則只是為儲存在快取中的內容設定 Expiration 標頭。

這些操作取決於 WININET 在下載時是否快取了檔案,您通過在整個網站上設定標頭已經發現了這個情況。如果您控制 IIS 伺服器或宿主這些 HTML 檔案的 Web 伺服器,則可以基於站點、目錄或檔案設定 Expires 標頭,因此可以一直向下到檔案級別,獲得合適的快取行為。

從 Expire1.htm 導航到 HtmlPage1.htm 之後,但在單擊“Forward”和“Back”按鈕之前,您需要檢視“Tools | Internet options | Settings button | View Files”按鈕。在此顯示中,找到 Expires1.htm,然後檢視“截止期”列。是否存在一個日期/時間反映您何時訪問了該檔案?如果是,圖 2 中顯示的規則會在使用“Forward”和“Back”按鈕時應用到這些經過快取的內容。您可能會看到,使用“Forward”和“Back”按鈕時,只有當前 Internet Explorer 會話期間尚未下載內容的情況下才會發生同步。

現在為了獲得您希望的行為,在載入了 HtmlPage1.htm 之後,請不要使用“Forward”和“Back”按鈕來訪問 Expire1.htm,而是單擊位址列,然後手動輸入 Expire1.htm 的完整路徑。這樣應該會導致顯示新內容,因為現在快取規則是基於超連結單擊或位址列導航的。這種情況下,內容的“截止期”將決定是否應該再次下載該內容。

問:如果某個應用程式同時建立了 50 個與 SQL Server™ 的連線,則連線池中將具有 50 個連線。何時從池中將它們刪除?如果它們的 ConnectionLifetime 為 0,文章中說明此設定表示使用最長的連線生命週期,那麼這個生命週期是多長?

答:刪除池中連線背後的邏輯沒有記錄,但是這並沒有阻止人們發現該邏輯的嘗試,以及有關此類文章的編寫。最好的一篇文章可能是 SqlClient Connection Pooling Exposed - Reflection allows .NET developers to peer into the internals of SqlClient。您還可以檢視下列 blog:ADO.NET The misunderstood "Connection Lifetime" managed pooler connection string keyword.

基本的理念是,在池中保持閒置狀態的連線將在大約 4 分鐘和 8 分鐘之間一個任意的時間內進行清除,具體取決於實施細節。正如前面提到的那篇文章所講述的那樣,如果不使用反射,您根本不可能更改該預設值。

設定了最小連線池大小的連線的真正行為與沒有此設定的連線相同。關閉該連線時,會檢查該連線生命週期,並且該連線將被處置。託管的池將注意到您已經小於最小池大小,因此會在後臺執行緒上開啟一個新連線。連線生命週期與連線池閒置時間無關。將其設定為 0 相當於設定為 int32.MaxValue 的最大值,2147483647 秒。

問:ADO.NET 是否會執行任何操作來保護傳遞到 SQLConnection 物件的連線字串引數的安全?我擔心的是公開連線字串的記憶體轉儲問題。對連線字串執行比較,以確定是否可以使用池中的連線時,是否會傳遞真正的字串?

答:首先,應該注意,有關公開連線字串的擔心並非 ADO.NET 所特有的;這對於所有資料庫訪問技術來說都是一個合理的擔心。實際上沒有什麼方法可用來保護密碼不會被對 ADO.NET 應用程式具有管理員許可權的使用者看到。他可以從 .exe 檔案、記憶體轉儲、通過從網路進行資料包探測,通過欺騙伺服器資訊等方式來獲取密碼。

一個很好的解決方案是使用整合安全。這就意味著,您的程式可以執行經過身份驗證的使用者在沒有您程式的情況下有許可權執行的任何操作。如果使用整合安全,在此過程中將不會顯示任何密碼。

作為在連線字串中使用密碼的眾多危險的一個示例,請採用此方案。首先,請使用包含密碼的連線字串呼叫 SqlConnection.Open。第二,SqlConnection 儘快對該密碼進行內部加密。但是,即使使用此設計,在垃圾收集發生之前的程序記憶體轉儲仍會向您顯示呼叫 SqlConnection.Open 時所使用的字串物件(連線字串)。因此,無論 SqlConnection 執行什麼操作,它都無法隱藏此連線字串的內容。SqlConnection 甚至無法擦除傳入連線字串中的資料,因為字串在 .NET 中是不可變的。有關在基於 .NET 的應用程式中保護字串安全的詳細資訊,請參閱本期 MSDN Magazine 中的 Security Briefs,尤其是有關 System.Security 和新 SecureString 類的部分。

第二個選擇是完全向使用者隱藏資料庫(如使用 Web 服務解決方案),以便該資料庫只能由 Web 伺服器訪問。

問:我想知道如何使得頁上的選單項不會出現在正在顯示的圖後面?該圖是一個包含在 <DIV> 標記中的 flash 物件。是否應該使用 Z-索引?當我在主選單上移動滑鼠時,應該顯示選單項,但是其中某些選單項總是會隱藏在該圖之後。

答:在 <DIV> 元素上設定 Z-索引屬性不會有所幫助,這是因為 Flash 控制元件是一個有視窗的元素,不允許其他 DHTML 內容置於它上面的層中。您可能能夠將您的選單更改為使用 createPopup,這樣就會位於另一個有視窗物件的上面了。但是,請注意,輔助功能應該仍然能夠使用這些選單項。有關如何完成上述任務的詳細資訊,請參閱 createPopup Method。