ASP.NET使用IHttpModule实现网站静态缓存

ASP.NET使用IHttpModule实现网站静态缓存

http://blog.csdn.net/mr_tanglin/article/details/6753771

原创 2011年09月06日 16:34:11

需求:

一网站已开发完成,考虑SEO优化,用户体验,开发周期(节约成本)等等,网站使用伪静态技术。

 

初期运行可以,后期问题就出现了,由于网站访问量增大,出现CPU100%情况,严重影响用户访问,由于不是真静态,所以程序比较耗内存,CPU。

 

分析:

考虑网站真静态,可是如果要改原来的代码,会是一个很费力的问题,效率不高。

 

如何不改动原代码,实现网站静态化?

 

IHttpModule IHttpHandler 都可以实现。

 

实现:

 网上查询很多资料,开始使用IHttpHandler 来实现

 

[csharp] view plain copy
 
  1. public class MyHandler : IHttpHandler  
  2. {  
  3.     public bool IsReusable  
  4.     {  
  5.         get { return true; }  
  6.     }  
  7.   
  8.     public void ProcessRequest(HttpContext context)  
  9.     {  
  10.         //处理代码  
  11.     }  
  12. }  

[csharp] view plain copy
 
  1. //配置web.config 在httphandler节增加配置  
  2.   
  3.    <httpHandlers>  
  4.   
  5.         <add verb="*" path="*" type="MyHandler"/>  
  6.   
  7.    </httpHandlers>  

可是发现handler 拦截用户请求后,无法在继续响应,只能使用response.writer来手动响应内容,如果将原页面手动输入,会出现版面混乱的问题,没有找到解决方案。

 

 

Google。发现IHttpModule 可以实现我想要的效果

 

[csharp] view plain copy
 
  1. using System;  
  2. using System.Web;  
  3. using System.Text.RegularExpressions;  
  4. using System.IO;  
  5. using System.Configuration;  
  6. using System.Collections.Generic;  
  7. namespace Product  
  8. {  
  9.     public class ProductModule : IHttpModule  
  10.     {  
  11.         public void Init(HttpApplication application)  
  12.         {  
  13.             application.BeginRequest += (new EventHandler(this.Application_BeginRequest));//请求开始  
  14.             application.EndRequest += (new EventHandler(this.Application_EndRequest));//请求结束  
  15.         }  
  16.         private void Application_BeginRequest(Object source, EventArgs e)  
  17.         {  
  18.             HttpApplication Application = (HttpApplication)source;  
  19.             CheckUrl(Application);  
  20.         }  
  21.         private void Application_EndRequest(Object source, EventArgs e)  
  22.         {  
  23.             //HttpApplication Application = (HttpApplication)source;  
  24.             //Application.Response.Write("test");  
  25.         }  
  26.         private void CheckUrl(HttpApplication application)  
  27.         {  
  28.             if (application.Request.RequestType.ToUpper() == "POST" || application.Request.UserAgent.ToLower() == "product")  
  29.             {  
  30.                 return;  
  31.             }  
  32.   
  33.             string[] resUrlTemp = new string[5];//待缓存的请求模板  
  34.             resUrlTemp[0] = "/model/modelsearch.aspx\\?clid=([\\d]+)&coid=([\\d]+)&bid=([\\d]+)&price=(.*)&model=(.*)&p=([\\d]+)&t=([0-2]{1,1})";  
  35.             resUrlTemp[1] = "/pic/imgsearch.aspx\\?clid=([\\d]+)&cbid=([\\d]+)&model=(.*)&p=([\\d]+)";  
  36.             resUrlTemp[2] = "/praise/PraiseSearch.aspx\\?clid=([\\d]+)&coid=([\\d]+)&model=(.*)&p=([\\d]+)";  
  37.             resUrlTemp[3] = "/price/sellerpricesearch.aspx\\?clid=([\\d]+)&coid=([\\d]+)&brand=([\\d]+)&price=(.*)&model=(.*)&p=([\\d]+)&t=([0-2]{1,1})";  
  38.             resUrlTemp[4] = "/dealer/sellersearch.aspx\\?pve=([\\d]+)&city=([\\d]+)&type=([\\d]+)&seller=(.*)&bid=([\\d]+)&model=(.*)&pagesize=([\\d]+)&p=([\\d]+)";  
  39.   
  40.             string reqUrl = application.Context.Request.Url.PathAndQuery.ToLower();//请求动态路径  
  41.               
  42.   
  43.             bool success = false;  
  44.             for (int i = 0; i < resUrlTemp.Length;i++ )  
  45.             {  
  46.                 if (!success)  
  47.                 {  
  48.                     Regex reg = new Regex(resUrlTemp[i]);//匹配当前请求是否需要缓存  
  49.                     MatchCollection mc = reg.Matches(reqUrl);  
  50.                     if (mc.Count > 0)  
  51.                     {  
  52.                         //静态页命名使用当前请求路径MD5加密命名  
  53.                         string PyReUrl = ConfigurationManager.ConnectionStrings["WebPhysicsUrl"].ConnectionString + "/Cache/" + i + "/" + System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(reqUrl, "MD5") + ".html";  
  54.   
  55.   
  56.                         FileInfo fi = new FileInfo(PyReUrl);//判断是否缓存  
  57.                         if (!fi.Exists)  
  58.                         {  
  59.                             //缓存页面  
  60.                             string WebUrl = ConfigurationManager.ConnectionStrings["WebUrl"].ConnectionString;  
  61.                             System.Net.HttpWebRequest Request = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(WebUrl + reqUrl);//Post请求当前页  
  62.                             Request.Method = "GET";  
  63.                             Request.Accept = "*/*";  
  64.                             Request.UserAgent = "Product";  
  65.                             Request.AllowAutoRedirect = true;  
  66.                             Request.MaximumAutomaticRedirections = 2;  
  67.   
  68.                             System.Net.HttpWebResponse Response = null;  
  69.                             try  
  70.                             {  
  71.                                 Response = (System.Net.HttpWebResponse)Request.GetResponse();//获得响应  
  72.                             }  
  73.                             catch(Exception ex)  
  74.                             {  
  75.                                 application.Response.Write("Response Error"+ex.Message);  
  76.                             }  
  77.                             if (Response != null)  
  78.                             {  
  79.                                 System.IO.Stream strm = Response.GetResponseStream();  
  80.                                 System.IO.StreamReader sr = new System.IO.StreamReader(strm, System.Text.Encoding.GetEncoding("gb2312"));  
  81.   
  82.   
  83.                                 StreamWriter Sw = null;  
  84.                                 try  
  85.                                 {  
  86.                                     if (!Directory.Exists(Directory.GetParent(PyReUrl).FullName))  
  87.                                         Directory.CreateDirectory(Directory.GetParent(PyReUrl).FullName);  
  88.   
  89.                                     FileStream Fs = new FileStream(PyReUrl, FileMode.Create, FileAccess.Write, FileShare.Read);  
  90.                                     Sw = new StreamWriter(Fs, System.Text.Encoding.Default, 512);  
  91.   
  92.                                     Sw.Write(sr.ReadToEnd());//写入  
  93.   
  94.                                     success = true;  
  95.                                 }  
  96.                                 catch(Exception ex)  
  97.                                 {  
  98.                                     Sw.Close();  
  99.                                     application.Response.Write("Writer Error"+ex.Message);  
  100.                                 }  
  101.   
  102.                                 sr.Close();  
  103.                                 Sw.Close();  
  104.                                 Response.Close();  
  105.                             }  
  106.                         }  
  107.                         else  
  108.                         {  
  109.                             //application.Response.Redirect(PyReUrl);//链接到静态页面 浏览器请求路径不变,不会影响收录  
  110.                             application.Server.Transfer("/Cache/" + i + "/" + System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(reqUrl, "MD5") + ".html");  
  111.                         }  
  112.                     }  
  113.                 }  
  114.             }  
  115.                   
  116.         }  
  117.         public void Dispose()  
  118.         {  
  119.         }  
  120.     }  
  121. }  

[csharp] view plain copy
 
  1. //webcongif配置文件  
  2. <httpModules>  
  3.     <add name="ProductModules" type="Product.ProductModule"/>  
  4. </httpModules>  

 

实现思路:

当用户发出请求后,IIS接到请求,伪静态解析得到动态请求路径,IHttpModule拦截到动态请求路径,正则匹配,查看当前请求路径是否静态缓存

1.不需要缓存。不处理,继续响应用户请求。

2.需要缓存。判断缓存是否存在

 (1.存在,将缓存响应给用户。

 (2.不存在,缓存当前请求。继续响应用户请求。

 

总体来说,第一次访问页面的人响应时间比较长,当缓存文件保存后,后续用户访问直接访问缓存内容,大大降低了服务器的压力,响应速度也更快。

 

当网站内容需要更新时,只需要删除缓存文件即可。

 

注意,并不是所有页面都可以缓存,因为你的页面可能有些需要页面回传,如果生成静态页,回传就失效了。

由于鄙人开发此网站前考虑都以后可能会使用静态,所有请求都是使用ajax实现,级联等效果也是ajax实现,并无页面回发,所以改起来很方便。

只需添加一个IHttpModule文件,改一下配置文件即可。

 

有对此感兴趣,有不懂的可以问我,乐意为大家解决问题。

 

生产缓存文件如下:

版权声明:本文为博主原创文章,未经博主允许不得转载。
 
 
posted @ 2017-11-06 09:56  sky20080101  阅读(104)  评论(0)    收藏  举报