<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    weidagang2046的專欄

    物格而后知致
    隨筆 - 8, 文章 - 409, 評論 - 101, 引用 - 0
    數(shù)據(jù)加載中……

    編寫高性能Web應(yīng)用程序的10個入門技巧

    編寫高性能Web應(yīng)用程序的10個入門技巧

    ? 數(shù)據(jù)層性能
    ? 技巧 1 — 返回多個結(jié)果集
    ? 技巧 2 — 分頁的數(shù)據(jù)訪問
    ? 技巧 3 — 連接池
    ? 技巧 4 — ASP.NET 緩存 API
    ? 技巧 5 — 每請求緩存
    ? 技巧 6 — 后臺處理
    ? 技巧 7 — 頁輸出緩存和代理服務(wù)器
    ? 技巧 8 — 運行 IIS 6.0(只要用于內(nèi)核緩存)
    ? 技巧 9 — 使用 Gzip 壓縮
    ? 技巧 10 — 服務(wù)器控件視圖狀態(tài)
    ?

    使用 ASP.NET 編寫 Web 應(yīng)用程序的簡單程度令人不敢相信。正因為如此簡單,所以很多
    開發(fā)人員就不會花時間來設(shè)計其應(yīng)用程序的結(jié)構(gòu),以獲得更好的性能了。在本文中,我將
    講述 10 個用于編寫高性能 Web 應(yīng)用程序的技巧。但是我并不會將這些建議僅局限于
    ASP.NET 應(yīng)用程序,因為這些應(yīng)用程序只是 Web 應(yīng)用程序的一部分。本文不作為對 Web
    應(yīng)用程序進(jìn)行性能調(diào)整的權(quán)威性指南 — 一整本書恐怕都無法輕松講清楚這個問題。請將
    本文視作一個很好的起點。

    成為工作狂之前,我原來喜歡攀巖。在進(jìn)行任何大型攀巖活動之前,我都會首先仔細(xì)查看
    指南中的路線,閱讀以前游客提出的建議。但是,無論指南怎么好,您都需要真正的攀巖
    體驗,然后才能嘗試一個特別具有挑戰(zhàn)性的攀登。與之相似,當(dāng)您面臨修復(fù)性能問題或者
    運行一個高吞吐量站點的問題時,您只能學(xué)習(xí)如何編寫高性能 Web 應(yīng)用程序。

    我的個人體驗來自在 Microsoft 的 ASP.NET 部門作為基礎(chǔ)架構(gòu)程序經(jīng)理的經(jīng)驗,在此期
    間我運行和管理 www.ASP.NET,幫助設(shè)計社區(qū)服務(wù)器的結(jié)構(gòu),社區(qū)服務(wù)器是幾個著名
    ASP.NET 應(yīng)用程序(組合到一個平臺的 ASP.NET Forums、.Text 和 nGallery)。我確信
    有些曾經(jīng)幫助過我的技巧對您肯定也會有所幫助。

    您應(yīng)該考慮將應(yīng)用程序分為幾個邏輯層。您可能聽說過 3 層(或者 n 層)物理體系結(jié)構(gòu)
    一詞。這些通常都是規(guī)定好的體系結(jié)構(gòu)方式,將功能在進(jìn)程和/或硬件之間進(jìn)行了物理分離
    。當(dāng)系統(tǒng)需要擴(kuò)大時,可以很輕松地添加更多的硬件。但是會出現(xiàn)一個與進(jìn)程和機器跳躍
    相關(guān)的性能下降,因此應(yīng)該避免。所以,如果可能的話,請盡量在同一個應(yīng)用程序中一起
    運行 ASP.NET 頁及其相關(guān)組件。

    因為代碼分離以及層之間的邊界,所以使用 Web 服務(wù)或遠(yuǎn)程處理將會使得性能下降 20%
    甚至更多。

    數(shù)據(jù)層有點與眾不同,因為通常情況下,最好具有專用于數(shù)據(jù)庫的硬件。然而進(jìn)程跳躍到
    數(shù)據(jù)庫的成本依然很高,因此數(shù)據(jù)層的性能是您在優(yōu)化代碼時首先要考慮的問題。

    在深入應(yīng)用程序的性能修復(fù)問題之前,請首先確保對應(yīng)用程序進(jìn)行剖析,以便找出具體的
    問題所在。主要性能計數(shù)器(如表示執(zhí)行垃圾回收所需時間百分比的計數(shù)器)對于找出應(yīng)
    用程序在哪些位置花費了其主要時間也非常有用。然而花費時間的位置通常非常不直觀。

    本文講述了兩種類型的性能改善:大型優(yōu)化(如使用 ASP.NET 緩存),和進(jìn)行自身重復(fù)的
    小型優(yōu)化。這些小型優(yōu)化有時特別有意思。您對代碼進(jìn)行一點小小的更改,就會獲得很多
    很多時間。使用大型優(yōu)化,您可能會看到整體性能的較大飛躍。而使用小型優(yōu)化時,對于
    某個特定請求可能只會節(jié)省幾毫秒的時間,但是每天所有請求加起來,則可能會產(chǎn)生巨大
    的改善。

    數(shù)據(jù)層性能


    談到應(yīng)用程序的性能調(diào)整,有一個試紙性的測試可用來對工作進(jìn)行優(yōu)先級劃分:代碼是否
    訪問數(shù)據(jù)庫?如果是,頻率是怎樣的?請注意,這一相同測試也可應(yīng)用于使用 Web 服務(wù)或
    遠(yuǎn)程處理的代碼,但是本文對這些內(nèi)容未做講述。

    如果某個特定的代碼路徑中必需進(jìn)行數(shù)據(jù)庫請求,并且您認(rèn)為要首先優(yōu)化其他領(lǐng)域(如字
    符串操作),則請停止,然后執(zhí)行這個試紙性測試。如果您的性能問題不是非常嚴(yán)重的話
    ,最好花一些時間來優(yōu)化一下與數(shù)據(jù)庫、返回的數(shù)據(jù)量、進(jìn)出數(shù)據(jù)庫的往返頻率相關(guān)的花
    費時間。

    了解這些常規(guī)信息之后,我們來看一下可能會有助于提高應(yīng)用程序性能的十個技巧。首先
    ,我要講述可能會引起最大改觀的更改。


    技巧 1 — 返回多個結(jié)果集


    仔細(xì)查看您的數(shù)據(jù)庫代碼,看是否存在多次進(jìn)入數(shù)據(jù)庫的請求路徑。每個這樣的往返都會
    降低應(yīng)用程序可以提供的每秒請求數(shù)量。通過在一個數(shù)據(jù)庫請求中返回多個結(jié)果集,可以
    節(jié)省與數(shù)據(jù)庫進(jìn)行通信所需的總時間長度。同時因為減少了數(shù)據(jù)庫服務(wù)器管理請求的工作
    ,還會使得系統(tǒng)伸縮性更強。

    雖然可以使用動態(tài) SQL 返回多個結(jié)果集,但是我首選使用存儲過程。關(guān)于業(yè)務(wù)邏輯是否應(yīng)
    該駐留于存儲過程的問題還存在一些爭議,但是我認(rèn)為,如果存儲過程中的邏輯可以約束
    返回數(shù)據(jù)的話(縮小數(shù)據(jù)集的大小、縮短網(wǎng)絡(luò)上所花費時間,不必篩選邏輯層的數(shù)據(jù)),
    則應(yīng)贊成這樣做。

    使用 SqlCommand 實例及其 ExecuteReader 方法填充強類型的業(yè)務(wù)類時,可以通過調(diào)用
    NextResult 將結(jié)果集指針向前移動。圖 1 顯示了使用類型類填充幾個 ArrayList 的示例
    會話。只從數(shù)據(jù)庫返回您需要的數(shù)據(jù)將進(jìn)一步減少服務(wù)器上的內(nèi)存分配。

    Figure 1 Extracting Multiple Resultsets from a DataReader
    // read the first resultset
    reader = command.ExecuteReader();

    // read the data from that resultset
    while (reader.Read()) {
    ??? suppliers.Add(PopulateSupplierFromIDataReader( reader ));
    }

    // read the next resultset
    reader.NextResult();

    // read the data from that second resultset
    while (reader.Read()) {
    ??? products.Add(PopulateProductFromIDataReader( reader ));
    }


    技巧 2 — 分頁的數(shù)據(jù)訪問


    ASP.NET DataGrid 具有一個很好的功能:數(shù)據(jù)分頁支持。在 DataGrid 中啟用分頁時,一
    次會顯示固定數(shù)量的記錄。另外,在 DataGrid 的底部還會顯示分頁 UI,以便在記錄之間
    進(jìn)行導(dǎo)航。該分頁 UI 使您能夠在所顯示的數(shù)據(jù)之間向前和向后導(dǎo)航,并且一次顯示固定
    數(shù)量的記錄。

    還有一個小小的波折。使用 DataGrid 的分頁需要所有數(shù)據(jù)均與網(wǎng)格進(jìn)行綁定。例如,您
    的數(shù)據(jù)層需要返回所有數(shù)據(jù),那么 DataGrid 就會基于當(dāng)前頁篩選顯示的所有記錄。如果
    通過 DataGrid 進(jìn)行分頁時返回了 100,000 個記錄,那么針對每個請求會放棄 99,975 個
    記錄(假設(shè)每頁大小為 25 個記錄)。當(dāng)記錄的數(shù)量不斷增加時,應(yīng)用程序的性能就會受
    到影響,因為針對每個請求必須發(fā)送越來越多的數(shù)據(jù)。

    要編寫性能更好的分頁代碼,一個極佳的方式是使用存儲過程。圖 2 顯示了針對
    Northwind 數(shù)據(jù)庫中的 Orders 表進(jìn)行分頁的一個示例存儲過程。簡而言之,您此時要做
    的只是傳遞頁索引和頁大小。然后就會計算合適的結(jié)果集,并將其返回。

    Figure 2 Paging Through the Orders Table
    CREATE PROCEDURE northwind_OrdersPaged
    (
    ??? @PageIndex int,
    ??? @PageSize int
    )
    AS
    BEGIN
    DECLARE @PageLowerBound int
    DECLARE @PageUpperBound int
    DECLARE @RowsToReturn int

    -- First set the rowcount
    SET @RowsToReturn = @PageSize * (@PageIndex + 1)
    SET ROWCOUNT @RowsToReturn

    -- Set the page bounds
    SET @PageLowerBound = @PageSize * @PageIndex
    SET @PageUpperBound = @PageLowerBound + @PageSize + 1

    -- Create a temp table to store the select results
    CREATE TABLE #PageIndex
    (
    ??? IndexId int IDENTITY (1, 1) NOT NULL,
    ??? OrderID int
    )

    -- Insert into the temp table
    INSERT INTO #PageIndex (OrderID)
    SELECT
    ??? OrderID
    FROM
    ??? Orders
    ORDER BY
    ??? OrderID DESC

    -- Return total count
    SELECT COUNT(OrderID) FROM Orders

    -- Return paged results
    SELECT
    ??? O.*
    FROM
    ??? Orders O,
    ??? #PageIndex PageIndex
    WHERE
    ??? O.OrderID = PageIndex.OrderID AND
    ??? PageIndex.IndexID > @PageLowerBound AND
    ??? PageIndex.IndexID < @PageUpperBound
    ORDER BY
    ??? PageIndex.IndexID

    END



    在社區(qū)服務(wù)器中,我們編寫了一個分頁服務(wù)器控件,以完成所有的數(shù)據(jù)分頁。您將會看到
    ,我使用的就是技巧 1 中討論的理念,從一個存儲過程返回兩個結(jié)果集:記錄的總數(shù)和請
    求的數(shù)據(jù)。

    返回記錄的總數(shù)可能會根據(jù)所執(zhí)行查詢的不同而有所變化。例如,WHERE 子句可用來約束
    返回的數(shù)據(jù)。為了計算在分頁 UI 中顯示的總頁數(shù),必須了解要返回記錄的總數(shù)。例如,
    如果總共有 1,000,000 條記錄,并且要使用一個 WHERE 子句將其篩選為 1000 條記錄,
    那么分頁邏輯就需要了解記錄的總數(shù)才能正確呈現(xiàn)分頁 UI。


    技巧 3 — 連接池


    在 Web 應(yīng)用程序和 SQL Server? 之間設(shè)置 TCP 連接可能是一個非常消耗資源的操作。Mi
    crosoft 的開發(fā)人員到目前為止能夠使用連接池已經(jīng)有一段時間了,這使得他們能夠重用
    數(shù)據(jù)庫連接。他們不是針對每個請求都設(shè)置一個新的 TCP 連接,而是只在連接池中沒有任
    何連接時才設(shè)置新連接。當(dāng)連接關(guān)閉時,它會返回連接池,在其中它會保持與數(shù)據(jù)庫的連
    接,而不是完全破壞該 TCP 連接。

    當(dāng)然,您需要小心是否會出現(xiàn)泄漏連接。當(dāng)您完成使用連接時,請一定要關(guān)閉這些連接。
    再重復(fù)一遍:無論任何人對 Microsoft?.NET Framework 中的垃圾回收有什么評論,請一
    定要在完成使用連接時針對該連接顯式調(diào)用 Close 或 Dispose。不要相信公共語言運行庫
    (CLR) 會在預(yù)先確定的時間為您清除和關(guān)閉連接。盡管 CLR 最終會破壞該類,并強制連
    接關(guān)閉,但是當(dāng)針對對象的垃圾回收真正發(fā)生時,并不能保證。

    要以最優(yōu)化的方式使用連接池,需要遵守一些規(guī)則。首先打開連接,執(zhí)行操作,然后關(guān)閉
    該連接。如果您必須如此的話,可以針對每個請求多次打開和關(guān)閉連接(最好應(yīng)用技巧 1
    ),但是不要一直將連接保持打開狀態(tài)并使用各種不同的方法對其進(jìn)行進(jìn)出傳遞。第二,
    使用相同的連接字符串(如果使用集成身份驗證的話,還要使用相同的線程標(biāo)識)。如果
    不使用相同的連接字符串,例如根據(jù)登錄的用戶自定義連接字符串,那么您將無法得到連
    接池提供的同一個優(yōu)化值。如果您使用集成身份驗證,同時還要模擬大量用戶,連接池的
    效率也會大大下降。嘗試跟蹤與連接池相關(guān)的任何性能問題時,.NET CLR 數(shù)據(jù)性能計數(shù)器
    可能非常有用。

    每當(dāng)應(yīng)用程序連接資源時,如在另一個進(jìn)程中運行的數(shù)據(jù)庫,您都應(yīng)該重點考慮連接該資
    源所花時間、發(fā)送或檢索數(shù)據(jù)所花時間,以及往返的數(shù)量,從而進(jìn)行優(yōu)化。優(yōu)化應(yīng)用程序
    中任何種類的進(jìn)程跳躍都是獲得更佳性能的首要一點。

    應(yīng)用層包含了連接數(shù)據(jù)層、將數(shù)據(jù)轉(zhuǎn)換為有意義類實例和業(yè)務(wù)流程的邏輯。例如社區(qū)服務(wù)
    器,您要在其中填充Forums 或 Threads集合,應(yīng)用業(yè)務(wù)規(guī)則(如權(quán)限);最重要的是要在
    其中執(zhí)行緩存邏輯。


    技巧 4 — ASP.NET 緩存 API


    編寫應(yīng)用程序代碼行之前,一個首要完成的操作是設(shè)計應(yīng)用層的結(jié)構(gòu),以便最大化利用
    ASP.NET 緩存功能。

    如果您的組件要在 ASP.NET 應(yīng)用程序中運行,則只需在該應(yīng)用程序項目中包括一個
    System.Web.dll 引用。當(dāng)您需要訪問該緩存時,請使用 HttpRuntime.Cache 屬性(通過
    Page.Cache 和 HttpContext.Cache 也可訪問這個對象)。

    對于緩存數(shù)據(jù),有幾個規(guī)則。首先,如果數(shù)據(jù)可能會多次使用時,則這是使用緩存的一個
    很好的備選情況。第二,如果數(shù)據(jù)是通用的,而不特定于某個具體的請求或用戶時,則也
    是使用緩存的一個很好的備選情況。如果數(shù)據(jù)是特定于用戶或請求的,但是壽命較長的話
    ,仍然可以對其進(jìn)行緩存,但是這種情況可能并不經(jīng)常使用。第三,一個經(jīng)常被忽略的規(guī)
    則是,有時可能您緩存得太多。通常在一個 x86 計算機上,為了減少內(nèi)存不足錯誤出現(xiàn)的
    機會,您會想使用不高于 800MB 的專用字節(jié)運行進(jìn)程。因此緩存應(yīng)該有個限度。換句話說
    ,您可能能夠重用某個計算結(jié)果,但是如果該計算采用 10 個參數(shù)的話,您可能要嘗試緩
    存 10 個排列,這樣有可能給您帶來麻煩。一個要求 ASP.NET 的最常見支持是由于過度緩
    存引起的內(nèi)存不足錯誤,尤其是對于大型數(shù)據(jù)集。


    緩存有幾個極佳的功能,您需要對它們有所了解。首先,緩存會實現(xiàn)最近最少使用的算法
    ,使得 ASP.NET 能夠在內(nèi)存運行效率較低的情況下強制緩存清除 - 從緩存自動刪除未使
    用過的項目。第二,緩存支持可以強制失效的過期依賴項。這些依賴項包括時間、密鑰和
    文件。時間經(jīng)常會用到,但是對于 ASP.NET 2.0,引入了一個功能更強的新失效類型:數(shù)
    據(jù)庫緩存失效。它指的是當(dāng)數(shù)據(jù)庫中的數(shù)據(jù)發(fā)生變化時自動刪除緩存中的項。有關(guān)數(shù)據(jù)庫
    緩存失效的詳細(xì)信息,請參閱 MSDN?Magazine 2004 年 7 月的 Dino Esposito Cutting
    Edge 專欄。要了解緩存的體系結(jié)構(gòu),請參閱圖 3。

    技巧 5 — 每請求緩存

    在本文前面部分,我提到了經(jīng)常遍歷代碼路徑的一些小改善可能會導(dǎo)致較大的整體性能收
    益。對于這些小改善,其中有一個絕對是我的最愛,我將其稱之為"每請求緩存"。

    緩存 API 的設(shè)計目的是為了將數(shù)據(jù)緩存較長的一段時間,或者緩存至滿足某些條件時,但
    每請求緩存則意味著只將數(shù)據(jù)緩存為該請求的持續(xù)時間。對于每個請求,要經(jīng)常訪問某個
    特定的代碼路徑,但是數(shù)據(jù)卻只需提取、應(yīng)用、修改或更新一次。這聽起來有些理論化,
    那么我們來舉一個具體的示例。

    在社區(qū)服務(wù)器的論壇應(yīng)用程序中,頁面上使用的每個服務(wù)器控件都需要個性化的數(shù)據(jù)來確
    定使用什么外觀、使用什么樣式表,以及其他個性化數(shù)據(jù)。這些數(shù)據(jù)中有些可以長期緩存
    ,但是有些數(shù)據(jù)卻只針對每個請求提取一次,然后在執(zhí)行該請求期間對其重用多次,如要
    用于控件的外觀。

    為了達(dá)到每請求緩存,請使用 ASP.NET HttpContext。對于每個請求,都會創(chuàng)建一個
    HttpContext 實例,在該請求期間從 HttpContext.Current 屬性的任何位置都可訪問該實
    例。該 HttpContext 類具有一個特殊的 Items 集合屬性;添加到此 Items 集合的對象和
    數(shù)據(jù)只在該請求持續(xù)期間內(nèi)進(jìn)行緩存。正如您可以使用緩存來存儲經(jīng)常訪問的數(shù)據(jù)一樣,
    您也可以使用 HttpContext.Items 來存儲只基于每個請求使用的數(shù)據(jù)。它背后的邏輯非常
    簡單:數(shù)據(jù)在它不存在的時候添加到 HttpContext.Items 集合,在后來的查找中,只是返
    回 HttpContext.Items 中的數(shù)據(jù)。


    技巧 6 — 后臺處理


    通往代碼的路徑應(yīng)該盡可能快速,是嗎?可能有時您會覺得針對每個請求執(zhí)行的或者每
    n 個請求執(zhí)行一次的任務(wù)所需資源非常多。發(fā)送電子郵件或者分析和驗證傳入數(shù)據(jù)就是這
    樣的一些例子。

    剖析 ASP.NET Forums 1.0 并重新構(gòu)建組成社區(qū)服務(wù)器的內(nèi)容時,我們發(fā)現(xiàn)添加新張貼的
    代碼路徑非常慢。每次添加新張貼時,應(yīng)用程序首先需要確保沒有重復(fù)的張貼,然后必須
    使用"壞詞"篩選器分析該張貼,分析張貼的字符圖釋,對張貼添加標(biāo)記并進(jìn)行索引,請求
    時將張貼添加到合適的隊列,驗證附件,最終張貼之后,立即向所有訂閱者發(fā)出電子郵件
    通知。很清楚,這涉及很多操作。

    經(jīng)研究發(fā)現(xiàn),大多數(shù)時間都花在了索引邏輯和發(fā)送電子郵件上。對張貼進(jìn)行索引是一個非
    常耗時的操作,人們發(fā)現(xiàn)內(nèi)置的 System.Web.Mail 功能要連接 SMYP 服務(wù)器,然后連續(xù)發(fā)
    送電子郵件。當(dāng)某個特定張貼或主題領(lǐng)域的訂閱者數(shù)量增加時,執(zhí)行 AddPost 功能所需的
    時間也越來越長。

    并不需要針對每個請求都進(jìn)行電子郵件索引。理想情況下,我們想要將此操作進(jìn)行批處理
    ,一次索引 25 個張貼或者每五分鐘發(fā)送一次所有電子郵件。我們決定使用以前用于對數(shù)
    據(jù)緩存失效進(jìn)行原型設(shè)計的代碼,這個失效是用于最終進(jìn)入 Visual Studio? 2005 的內(nèi)容
    的。

    System.Threading 命名空間中的 Timer 類非常有用,但是在 .NET Framework 中不是很
    有名,至少對于 Web 開發(fā)人員來說是這樣。創(chuàng)建之后,這個 Timer 類將以一個可配置的
    間隔針對 ThreadPool 中的某個線程調(diào)用指定的回調(diào)。這就表示,您可以對代碼進(jìn)行設(shè)置
    ,使其能夠在沒有對 ASP.NET 應(yīng)用程序進(jìn)行傳入請求的情況下得以執(zhí)行,這是后臺處理的
    理想情況。您還可以在此后臺進(jìn)程中執(zhí)行如索引或發(fā)送電子郵件之類的操作。

    但是,這一技術(shù)有幾個問題。如果應(yīng)用程序域卸載,該計時器實例將停止觸發(fā)其事件。另
    外,因為 CLR 對于每個進(jìn)程的線程數(shù)量具有一個硬性標(biāo)準(zhǔn),所以可能會出現(xiàn)這樣的情形:
    服務(wù)器負(fù)載很重,其中計時器可能沒有可在其基礎(chǔ)上得以完成的線程,在某種程度上可能
    會造成延遲。ASP.NET 通過在進(jìn)程中保留一定數(shù)量的可用線程,并且僅使用總線程的一部
    分用于請求處理,試圖將上述情況發(fā)生的機會降到最低。但是,如果您具有很多異步操作
    時,這可能就是一個問題了。

    這里沒有足夠的空間來放置該代碼,但是您可以下載一個可以看懂的示例,網(wǎng)址是
    www.rob-howard.net。請了解一下 Blackbelt TechEd 2004 演示中的幻燈片和演示。


    技巧 7 — 頁輸出緩存和代理服務(wù)器


    ASP.NET 是您的表示層(或者說應(yīng)該是您的表示層);它由頁、用戶控件、服務(wù)器控件(H
    ttpHandlers 和 HttpModules)以及它們生成的內(nèi)容組成。如果您具有一個 ASP.NET 頁,
    它會生成輸出(HTML、XML、圖像或任何其他數(shù)據(jù)),并且您針對每個請求運行此代碼時,
    它都會生成相同的輸出,那么您就擁有一個可用于頁輸出緩存的絕佳備選內(nèi)容。

    將此行內(nèi)容添加頁的最上端

    <%@ Page OutputCache VaryByParams="none" Duration="60" %>

    就可以高效地為此頁生成一次輸出,然后對它進(jìn)行多次重用,時間最長為 60 秒,此時該
    頁將重新執(zhí)行,輸出也將再一次添加到 ASP.NET 緩存。通過使用一些低級程序化 API 也
    可以完成此行為。對于輸出緩存有幾個可配置的設(shè)置,如剛剛講到的 VaryByParams 屬性
    。VaryByParams 剛好被請求到,但還允許您指定 HTTP GET 或 HTTP POST 參數(shù)來更改緩
    存項。例如,只需設(shè)置 VaryByParam="Report" 即可對 default.aspx?Report=1 或
    default.aspx?Report=2 進(jìn)行輸出緩存。通過指定一個以分號分隔的列表,還可以指定其
    他參數(shù)。

    很多人都不知道何時使用輸出緩存,ASP.NET 頁還會生成一些位于緩存服務(wù)器下游的
    HTTP 標(biāo)頭,如 Microsoft Internet Security and Acceleration Server 或 Akamai 使
    用的標(biāo)頭。設(shè)置了 HTTP 緩存標(biāo)頭之后,可以在這些網(wǎng)絡(luò)資源上對文檔進(jìn)行緩存,客戶端
    請求也可在不必返回原始服務(wù)器的情況下得以滿足。

    因此,使用頁輸出緩存不會使得您的應(yīng)用程序效率更高,但是它可能會減少服務(wù)器上的負(fù)
    載,因為下游緩存技術(shù)會緩存文檔。當(dāng)然,這可能只是匿名內(nèi)容;一旦它成為下游之后,
    您就再也不會看到這些請求,并且再也無法執(zhí)行身份驗證以阻止對它的訪問了。


    技巧 8 — 運行 IIS 6.0(只要用于內(nèi)核緩存)


    如果您未運行 IIS 6.0 (Windows Server? 2003),那么您就錯過了 Microsoft Web 服務(wù)
    器中的一些很好的性能增強。在技巧 7 中,我討論了輸出緩存。在 IIS 5.0 中,請求是
    通過 IIS 然后進(jìn)入 ASP.NET 的。涉及到緩存時,ASP.NET 中的 HttpModule 會接收該請
    求,并返回緩存中的內(nèi)容。

    如果您正在使用 IIS 6.0,就會發(fā)現(xiàn)一個很好的小功能,稱為內(nèi)核緩存,它不需要對
    ASP.NET 進(jìn)行任何代碼更改。當(dāng)請求由 ASP.NET 進(jìn)行輸出緩存時,IIS 內(nèi)核緩存會接收緩
    存數(shù)據(jù)的一個副本。當(dāng)請求來自網(wǎng)絡(luò)驅(qū)動程序時,內(nèi)核級別的驅(qū)動程序(無上下文切換到
    用戶模式)就會接收該請求,如果經(jīng)過了緩存,則會將緩存的數(shù)據(jù)刷新到響應(yīng),然后完成
    執(zhí)行。這就表示,當(dāng)您將內(nèi)核模式緩存與 IIS 和 ASP.NET 輸出緩存一起使用時,就會看
    到令人不敢相信的性能結(jié)果。在 ASP.NET 的 Visual Studio 2005 開發(fā)過程中,我一度是
    負(fù)責(zé) ASP.NET 性能的程序經(jīng)理。開發(fā)人員完成具體工作,但是我要看到每天進(jìn)行的所有報
    告。內(nèi)核模式緩存結(jié)果總是最有意思的。最常見的特征是網(wǎng)絡(luò)充滿了請求/響應(yīng),而 IIS
    運行時的 CPU 使用率只有大約 5%。這太令人震驚了!當(dāng)然使用 IIS 6.0 還有一些其他原
    因,但是內(nèi)核模式緩存是其中最明顯的一個。


    技巧 9 — 使用 Gzip 壓縮


    雖然使用 gzip 并不一定是服務(wù)器性能技巧(因為您可能會看到 CPU 使用率的提高),但
    是使用 gzip 壓縮可以減少服務(wù)器發(fā)送的字節(jié)數(shù)量。這就使人們覺得頁速度加快了,并且
    還減少了帶寬的用量。根據(jù)所發(fā)送數(shù)據(jù)、可以壓縮的程度以及客戶端瀏覽器是否支持(IIS
    只會向支持 gzip 壓縮的客戶端發(fā)送經(jīng)過 gzip 壓縮的內(nèi)容,如 Internet Explorer
    6.0 和 Firefox),您的服務(wù)器每秒可以服務(wù)于更多的請求。實際上,幾乎每當(dāng)您減少所
    返回數(shù)據(jù)的數(shù)量時,都會增加每秒請求數(shù)。

    Gzip 壓縮已經(jīng)內(nèi)置到 IIS 6.0 中,并且其性能比 IIS 5.0 中使用的 gzip 壓縮要好的多
    ,這是好消息。但不幸的是,當(dāng)嘗試在 IIS 6.0 中打開 gzip 壓縮時,您可能無法在
    IIS 的屬性對話中找到該設(shè)置。IIS 小組在該服務(wù)器中置入了卓越的 gzip 功能,但是忘
    了包括一個用于啟用該功能的管理 UI。要啟用 gzip 壓縮,您必須深入到 IIS 6.0 的
    XML 配置設(shè)置內(nèi)部(這樣不會引起心臟虛弱)。順便提一句,這歸功于 OrcsWeb 的
    Scott Forsyth,他幫助我提出了在 OrcsWeb 上宿主的 www.asp.net 服務(wù)器的這個問題。


    本文就不講述步驟了,請閱讀 Brad Wilson 的文章,網(wǎng)址是 IIS6 Compression。還有一
    篇有關(guān)為 ASPX 啟用壓縮的知識庫文章,網(wǎng)址是 Enable ASPX Compression in IIS。但是
    您應(yīng)該注意,由于一些實施細(xì)節(jié),IIS 6.0 中不能同時存在動態(tài)壓縮和內(nèi)核緩存。


    技巧 10 — 服務(wù)器控件視圖狀態(tài)


    視圖狀態(tài)是一個有趣的名稱,用于表示在所生成頁的隱藏輸出字段中存儲一些狀態(tài)數(shù)據(jù)的
    ASP.NET。當(dāng)該頁張貼回服務(wù)器時,服務(wù)器可以分析、驗證、并將此視圖狀態(tài)數(shù)據(jù)應(yīng)用回該
    頁的控件樹。視圖狀態(tài)是一個非常強大的功能,因為它允許狀態(tài)與客戶端一起保持,并且
    它不需要 cookie 或服務(wù)器內(nèi)存即可保存此狀態(tài)。很多 ASP.NET 服務(wù)器控件都使用視圖狀
    態(tài)來保持在與頁元素進(jìn)行交互期間創(chuàng)建的設(shè)置,例如保存對數(shù)據(jù)進(jìn)行分頁時顯示的當(dāng)前頁


    然而使用視圖狀態(tài)也有一些缺點。首先,服務(wù)或請求頁時,它都會增加頁的總負(fù)載。對張
    貼回服務(wù)器的視圖狀態(tài)數(shù)據(jù)進(jìn)行序列化或取消序列化時,也會發(fā)生額外的開銷。最后,視
    圖狀態(tài)會增加服務(wù)器上的內(nèi)存分配。

    幾個服務(wù)器控件有著過度使用視圖狀態(tài)的趨勢,即使在并不需要的情況下也要使用它,其
    中最著名的是 DataGrid。ViewState 屬性的默認(rèn)行為是啟用,但是如果您不需要,則可以
    在控件或頁級別關(guān)閉。在控件內(nèi),只需將 EnableViewState 屬性設(shè)置為 false,或者在頁
    中使用下列設(shè)置即可對其進(jìn)行全局設(shè)置:

    <%@ Page EnableViewState="false" %>

    如果您不回發(fā)頁,或者總是針對每個請求重新生成頁上的控件,則應(yīng)該在頁級別禁用視圖
    狀態(tài)。


    我為您講述了一些我認(rèn)為在編寫高性能 ASP.NET 應(yīng)用程序時有所幫助的技巧。正如我在本
    文前面部分提到的那樣,這是一個初步指南,并不是 ASP.NET 性能的最后結(jié)果。(有關(guān)改
    善 ASP.NET 應(yīng)用程序性能的信息,請參閱 Improving ASP.NET Performance。)只有通過
    自己的親身體驗才能找出解決具體性能問題的最好方法。但是,在您的旅程中,這些技巧
    應(yīng)該會為您提供一些好的指南。在軟件開發(fā)中,幾乎沒有絕對的東西;每個應(yīng)用程序都是
    唯一的。

    from: http://www.chinahtml.com/programming/8/2006/11622676777784_2.shtml

    posted on 2006-12-06 23:57 weidagang2046 閱讀(572) 評論(0)  編輯  收藏 所屬分類: JavaDatabaseJavascript

    主站蜘蛛池模板: 91免费福利精品国产| 91精品成人免费国产| 久草视频免费在线| 亚洲av无码无在线观看红杏| a级大片免费观看| 亚洲国产精品无码久久久不卡 | 国产成+人+综合+亚洲专| 最近的中文字幕大全免费8| 亚洲伊人tv综合网色| 日本一卡精品视频免费| 亚洲国产精品婷婷久久| 97国产在线公开免费观看| 亚洲成在人线电影天堂色| 毛片免费视频播放| 亚洲老熟女五十路老熟女bbw| 日本19禁啪啪无遮挡免费动图| 美女免费精品高清毛片在线视| 免费国产在线观看| 一级特黄aaa大片免费看| 国产亚洲精品看片在线观看| 日本免费污片中国特一级| 亚洲日本在线免费观看| 成年人在线免费观看| 老司机午夜在线视频免费| 国产亚洲精品成人AA片新蒲金| 一级成人a毛片免费播放| 亚洲AV无码乱码在线观看代蜜桃| 国产美女无遮挡免费网站| 中文字幕不卡免费视频| 久久久久亚洲精品天堂| 午夜免费不卡毛片完整版| 亚洲无码日韩精品第一页| 一本色道久久88亚洲综合| xxxxx做受大片视频免费| 亚洲AV日韩精品久久久久| 中文字幕亚洲精品资源网| 很黄很黄的网站免费的| 国产成人va亚洲电影| 亚洲精品高清视频| 亚洲日产韩国一二三四区| 亚洲AⅤ无码一区二区三区在线 |