您的位置:首页 > 理论基础 > 计算机网络

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

2011-09-06 16:34 417 查看
需求:

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

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

分析:

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

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

IHttpModule IHttpHandler 都可以实现。

实现:

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

public class MyHandler : IHttpHandler
{
public bool IsReusable
{
get { return true; }
}

public void ProcessRequest(HttpContext context)
{
//处理代码
}
}


//配置web.config 在httphandler节增加配置

<httpHandlers>

<add verb="*" path="*" type="MyHandler"/>

</httpHandlers>


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

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

using System;
using System.Web;
using System.Text.RegularExpressions;
using System.IO;
using System.Configuration;
using System.Collections.Generic;
namespace Product
{
public class ProductModule : IHttpModule
{
public void Init(HttpApplication application)
{
application.BeginRequest += (new EventHandler(this.Application_BeginRequest));//请求开始
application.EndRequest += (new EventHandler(this.Application_EndRequest));//请求结束
}
private void Application_BeginRequest(Object source, EventArgs e)
{
HttpApplication Application = (HttpApplication)source;
CheckUrl(Application);
}
private void Application_EndRequest(Object source, EventArgs e)
{
//HttpApplication Application = (HttpApplication)source;
//Application.Response.Write("test");
}
private void CheckUrl(HttpApplication application)
{
if (application.Request.RequestType.ToUpper() == "POST" || application.Request.UserAgent.ToLower() == "product")
{
return;
}

string[] resUrlTemp = new string[5];//待缓存的请求模板
resUrlTemp[0] = "/model/modelsearch.aspx\\?clid=([\\d]+)&coid=([\\d]+)&bid=([\\d]+)&price=(.*)&model=(.*)&p=([\\d]+)&t=([0-2]{1,1})";
resUrlTemp[1] = "/pic/imgsearch.aspx\\?clid=([\\d]+)&cbid=([\\d]+)&model=(.*)&p=([\\d]+)";
resUrlTemp[2] = "/praise/PraiseSearch.aspx\\?clid=([\\d]+)&coid=([\\d]+)&model=(.*)&p=([\\d]+)";
resUrlTemp[3] = "/price/sellerpricesearch.aspx\\?clid=([\\d]+)&coid=([\\d]+)&brand=([\\d]+)&price=(.*)&model=(.*)&p=([\\d]+)&t=([0-2]{1,1})";
resUrlTemp[4] = "/dealer/sellersearch.aspx\\?pve=([\\d]+)&city=([\\d]+)&type=([\\d]+)&seller=(.*)&bid=([\\d]+)&model=(.*)&pagesize=([\\d]+)&p=([\\d]+)";

string reqUrl = application.Context.Request.Url.PathAndQuery.ToLower();//请求动态路径

bool success = false;
for (int i = 0; i < resUrlTemp.Length;i++ )
{
if (!success)
{
Regex reg = new Regex(resUrlTemp[i]);//匹配当前请求是否需要缓存
MatchCollection mc = reg.Matches(reqUrl);
if (mc.Count > 0)
{
//静态页命名使用当前请求路径MD5加密命名
string PyReUrl = ConfigurationManager.ConnectionStrings["WebPhysicsUrl"].ConnectionString + "/Cache/" + i + "/" + System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(reqUrl, "MD5") + ".html";

FileInfo fi = new FileInfo(PyReUrl);//判断是否缓存
if (!fi.Exists)
{
//缓存页面
string WebUrl = ConfigurationManager.ConnectionStrings["WebUrl"].ConnectionString;
System.Net.HttpWebRequest Request = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(WebUrl + reqUrl);//Post请求当前页
Request.Method = "GET";
Request.Accept = "*/*";
Request.UserAgent = "Product";
Request.AllowAutoRedirect = true;
Request.MaximumAutomaticRedirections = 2;

System.Net.HttpWebResponse Response = null;
try
{
Response = (System.Net.HttpWebResponse)Request.GetResponse();//获得响应
}
catch(Exception ex)
{
application.Response.Write("Response Error"+ex.Message);
}
if (Response != null)
{
System.IO.Stream strm = Response.GetResponseStream();
System.IO.StreamReader sr = new System.IO.StreamReader(strm, System.Text.Encoding.GetEncoding("gb2312"));

StreamWriter Sw = null;
try
{
if (!Directory.Exists(Directory.GetParent(PyReUrl).FullName))
Directory.CreateDirectory(Directory.GetParent(PyReUrl).FullName);

FileStream Fs = new FileStream(PyReUrl, FileMode.Create, FileAccess.Write, FileShare.Read);
Sw = new StreamWriter(Fs, System.Text.Encoding.Default, 512);

Sw.Write(sr.ReadToEnd());//写入

success = true;
}
catch(Exception ex)
{
Sw.Close();
application.Response.Write("Writer Error"+ex.Message);
}

sr.Close();
Sw.Close();
Response.Close();
}
}
else
{
//application.Response.Redirect(PyReUrl);//链接到静态页面 浏览器请求路径不变,不会影响收录
application.Server.Transfer("/Cache/" + i + "/" + System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(reqUrl, "MD5") + ".html");
}
}
}
}

}
public void Dispose()
{
}
}
}


//webcongif配置文件
<httpModules>
<add name="ProductModules" type="Product.ProductModule"/>
</httpModules>


实现思路:

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

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

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

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

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

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

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

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

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

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

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

生产缓存文件如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐