ASP.NET頁面性能優化的十大做法

作者: shss  來源: 博客園  發布時間: 2010-07-25 17:08  閱讀: 4524 次  推薦: 0   原文鏈接   [收藏]  
 
摘要:本文是我對ASP.NET頁面載入速度提高的一些做法
[1] ASP.NET頁面性能優化的十大做法
[2] ASP.NET頁面性能優化的十大做法

 前言

  本文是我對ASP.NET頁面載入速度提高的一些做法,這些做法分為以下部分:

  • 1.采用 HTTP Module 控制頁面的生命周期。
  • 2.自定義Response.Filter得到輸出流stream生成動態頁面的靜態內容(磁盤緩存)。
  • 3.頁面GZIP壓縮。
  • 4.OutputCache 編程方式輸出頁面緩存。
  • 5.刪除頁面空白字符串。(類似Google)
  • 6.完全刪除ViewState。
  • 7.刪除服務器控件生成的垃圾NamingContainer。
  • 8.使用計劃任務按時生成頁面。(本文不包含該做法的實現)
  • 9.JS,CSS壓縮、合并、緩存,圖片緩存。(限于文章篇幅,本文不包含該做法的實現)
  • 10.緩存破壞。(不包含第9做法的實現)

  針對上述做法,我們首先需要一個 HTTP 模塊,它是整個頁面流程的入口和核心。

  一、自定義Response.Filter得到輸出流stream生成動態頁面的靜態內容(磁盤緩存)

如下的代碼我們可以看出,我們以 request.RawUrl 為緩存基礎,因為它可以包含任意的QueryString變量,然后我們用MD5加密RawUrl 得到服務器本地文件名的變量,再實例化一個FileInfo操作該文件,如果文件最后一次生成時間小于7天,我們就使用.Net2.0新增的TransmitFile方法將存儲文件的靜態內容發送到瀏覽器。如果文件不存在,我們就操作 response.Filter 得到的 Stream 傳遞給 CommonFilter 類,并利用FileStream寫入動態頁面的內容到靜態文件中。

namespace  ASPNET_CL.Code.HttpModules {
     public  class  CommonModule : IHttpModule {
         public  void  Init( HttpApplication application ) {
            application.BeginRequest += Application_BeginRequest;
        }

         private  void  Application_BeginRequest(  object  sender, EventArgs e ) {
            var context = HttpContext.Current;
            var request = context.Request;
            var url = request.RawUrl;

            var response = context.Response;
            var path = GetPath( url );
            var file =  new  FileInfo( path );

             if  ( DateTime.Now.Subtract( file.LastWriteTime ).TotalDays < 7 ) {
                response.TransmitFile( path );
                response.End();
                 return;
            }
             try  {
                var stream = file.OpenWrite();
                response.Filter =  new  CommonFilter( response.Filter, stream );
            }
             catch  ( Exception ) {
                 //Log.Insert("");
            }
        }

         public  void  Dispose() {

        }

         private  static  string  GetPath(  string  url ) {
            var hash = Hash( url );
             string  fold = HttpContext.Current.Server.MapPath(  "~/Temp/"  );
             return  string.Concat( fold, hash );
        }

         private  static  string  Hash(  string  url ) {
            url = url.ToUpperInvariant();
            var md5 =  new  System.Security.Cryptography.MD5CryptoServiceProvider();
            var bs = md5.ComputeHash( Encoding.ASCII.GetBytes( url ) );
            var s =  new  StringBuilder();
             foreach  ( var b  in  bs ) {
                s.Append( b.ToString(  "x2"  ).ToLower() );
            }
             return  s.ToString();
        }
    }
}

  二、頁面GZIP壓縮

對頁面GZIP壓縮幾乎是每篇講解高性能WEB程序的幾大做法之一,因為使用GZIP壓縮可以降低服務器發送的字節數,能讓客戶感覺到網頁的速度更快也減少了對帶寬的使用情況。當然,這里也存在客戶端的瀏覽器是否支持它。因此,我們要做的是,如果客戶端支持GZIP,我們就發送GZIP壓縮過的內容,如果不支持,我們直接發送靜態文件的內容。幸運的是,現代瀏覽器IE6.7.8.0,火狐等都支持GZIP。

為了實現這個功能,我們需要改寫上面的 Application_BeginRequest 事件:

         private void Application_BeginRequest( object sender, EventArgs e ) {
            var context = HttpContext.Current;
            var request = context.Request;
            var url = request.RawUrl;

            var response = context.Response;
            var path = GetPath( url );
            var file = new FileInfo( path );

            // 使用頁面壓縮
              ResponseCompressionType compressionType = this.GetCompressionMode( request );
            if ( compressionType != ResponseCompressionType.None ) {
                response.AppendHeader( "Content-Encoding", compressionType.ToString().ToLower() );
                if ( compressionType == ResponseCompressionType.GZip ) {
                    response.Filter = new GZipStream( response.Filter, CompressionMode.Compress );
                }
                else {
                    response.Filter = new DeflateStream( response.Filter, CompressionMode.Compress );
                }
            }

            if ( DateTime.Now.Subtract( file.LastWriteTime ).TotalMinutes < 5 ) {
                response.TransmitFile( path );
                response.End();
                return;
            }
            try {
                var stream = file.OpenWrite();
                response.Filter = new CommonFilter( response.Filter, stream );
            }
            catch ( Exception ) {
                //Log.Insert("");
            }
        }

        private ResponseCompressionType GetCompressionMode( HttpRequest request ) {
            string acceptEncoding = request.Headers[ "Accept-Encoding" ];
            if ( string.IsNullOrEmpty( acceptEncoding ) )
                return ResponseCompressionType.None;

            acceptEncoding = acceptEncoding.ToUpperInvariant();

            if ( acceptEncoding.Contains( "GZIP" ) )
                return ResponseCompressionType.GZip;
            else if ( acceptEncoding.Contains( "DEFLATE" ) )
                return ResponseCompressionType.Deflate;
            else
                return ResponseCompressionType.None;
        }

        private enum ResponseCompressionType {
            None,
            GZip,
            Deflate
        }

  三、OutputCache 編程方式輸出頁面緩存

ASP.NET內置的 OutputCache 緩存可以將內容緩存在三個地方:Web服務器、代理服務器和瀏覽器。當用戶訪問一個被設置為 OutputCache的頁面時,ASP.NET在MSIL之后,先將結果寫入output cache緩存,然后在發送到瀏覽器,當用戶訪問同一路徑的頁面時,ASP.NET將直接發送被Cache的內容,而不經過.aspx編譯以及執行MSIL的過程,所以,雖然程序的本身效率沒有提升,但是頁面載入速度卻得到了提升。

 

為了實現這個功能,我們繼續改寫上面的 Application_BeginRequest 事件,我們在 TransmitFile 后,將這個路徑的頁面以OutputCache編程的方式緩存起來:

 

 private void Application_BeginRequest( object sender, EventArgs e ) {
         
           //.............

            if ( DateTime.Now.Subtract( file.LastWriteTime ).TotalMinutes < 5 ) {
                response.TransmitFile( path );
                // 添加 OutputCache 緩存頭,并緩存在客戶端
                  response.Cache.SetExpires( DateTime.Now.AddMinutes( 5 ) );
                response.Cache.SetCacheability( HttpCacheability.Public );
                response.End();
                return;
            }
           
           //............
 }

 

[第1頁][第2頁]
0
0
 
標簽:ASP.NET
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()