需求:
一網站已開發完成,考慮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文件,改一下配置文件即可。
有對此感興趣,有不懂的可以問我,樂意爲大家解決問題。
生產緩存文件如下: