因爲訪問量大,做頁面瀏覽量的時候不能直接操作庫;用文件來記錄的話,雖然減緩了數據庫的壓力但是對服務器I/O卻是一個考驗;而緩存正是.Net的一大優勢,所以想出HttpHandler結合Cache來減緩I/O操作,這樣I/O跟數據庫的壓力都解決了!
首先創建統計類庫
1.創建CounterHelper統計類
using System;
using System.Web;
using System.Web.Caching;
using System.Collections.Specialized;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Text;
using System.IO;
namespace MYSpace.Counter
{
/// <summary>
/// Counter 的摘要說明。
/// </summary>
public class CounterHelper
{
private int _Hits = 0; //累計的點擊數
private string _FileName = "";
private string FilePth = string.Empty;
private string ErrorLogFilePth = string.Empty;
private int[] HitsArr = {-1,0,0}; //HitsArr[0]表示總的點擊數HitsArr標識昨天的點擊數HitsArr表示今天的點擊數
CacheItemRemovedCallback onRemove = null;//CacheItemRemovedCallback對象
private string CacheName = "UpdateHitsForExpired";//緩存名稱
private object LockForAddHits = new object();//LockForAddHits鎖
private object LockForItemRemovedFromCacheHits = new object();//ItemRemovedFromCacheHits 鎖
/**//// <summary>
/// 構造函數
/// </summary>
public CounterHelper(string filename)
{
_FileName = filename;
CacheName = filename;
HttpContext ctx = HttpContext.Current;
FilePth = ctx.Server.MapPath("~/" + _FileName + ".txt");
ErrorLogFilePth = ctx.Server.MapPath("~/" + _FileName + ".txt");
LoadHits();
}
/**//// <summary>
/// 將累計點擊數保存到全局變量,當它達到一定量時保存到文本文件,並清空
/// </summary>
public void AddHits()
{
lock(LockForAddHits)
{
if( Hits != 0 )
{
Add();
if(Hits > 200 )
{
//--移除
HttpRuntime.Cache.Remove(CacheName);
}
}
else
{
onRemove = new CacheItemRemovedCallback(ItemRemovedFromCache);
HttpRuntime.Cache.Insert(
CacheName,
"This Object For Expired",
null,
DateTime.Now.AddSeconds(5) ,
TimeSpan.Zero,
System.Web.Caching.CacheItemPriority.Normal,
onRemove
);
Add();
}
}
}
/**//// <summary>
/// 保存到文本文件
/// </summary>
/// <param name="AllId"></param>
private void SaveHitsToFile(int hits)
{
string hitsinfo = string.Empty;
DateTime LastWriteTime = File.GetLastWriteTime(FilePth);
if((DateTime.Today - LastWriteTime).TotalDays >0 )
{
//--表示今天第一次寫數據
HitsArr[1] = HitsArr[2];//--將當前累計的點擊數賦給昨天的點擊數
HitsArr[2] = hits;//--設置今天的點擊數
using(StreamWriter streamWriter = new StreamWriter(FilePth,false) )
{
streamWriter.Write(string.Format("{0},{1},{2}",HitsArr[0] + hits,HitsArr[1] ,hits));
streamWriter.Flush();
}
}
else
{
using(StreamWriter streamWriter = new StreamWriter(FilePth,false) )
{
streamWriter.Write(string.Format("{0},{1},{2}",HitsArr[0] + hits,HitsArr[1], HitsArr[2] + hits));
streamWriter.Flush();
}
}
}
/**//// <summary>
/// 當緩存被移除或過期是觸發的回調事件
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="reason"></param>
private void ItemRemovedFromCache(string key, object value,CacheItemRemovedReason reason)
{
try
{
//清空並寫到文本文件
#region
int hits = 0;;
lock(LockForItemRemovedFromCacheHits)
{
hits = Hits;
HitsArr[0] += hits;
HitsArr[2] += hits;
Hits = 0;
}
if(hits == 0)
{
return;
}
else
{
SaveHitsToFile(hits);
}
#endregion
}
catch(Exception ex)
{
using(StreamWriter streamWriter = new StreamWriter(ErrorLogFilePth,false) )
{
streamWriter.Write(string.Format("時間:{0}/r/n描述信息:{1}/r/n",DateTime. Now,ex.Message));
streamWriter.Flush();
}
}
}
/**//// <summary>
/// 獲取所有的點擊數
/// </summary>
public int AllHits
{
get
{
return HitsArr[0] + Hits;
}
}
/**//// <summary>
/// 獲取昨天點擊數
/// </summary>
public int YesterdayHits
{
get
{
return HitsArr[1];
}
}
/**//// <summary>
/// 獲取今天點擊數
/// </summary>
public int TodayHits
{
get
{
return HitsArr[2] + Hits;
}
}
/**//// <summary>
/// 加載點擊數
/// </summary>
private void LoadHits()
{
if (HttpRuntime.Cache[CacheName] == null)
{
HttpContext ctx = HttpContext.Current;
if (!File.Exists(FilePth))
{
//--第一次使用
using (StreamWriter streamWriter = new StreamWriter(FilePth))
{
streamWriter.Write(string.Format("{0},{1},{2}", 0, 0, 0));
streamWriter.Flush();
}
HitsArr[0] = 0;
HitsArr[1] = 0;
HitsArr[2] = 0;
}
else
{
string hitsinfo = string.Empty;
using (StreamReader objStreamReader = new StreamReader(FilePth))
{
hitsinfo = objStreamReader.ReadLine();
}
if (hitsinfo != "")
{
string[] arr = hitsinfo.Split(',');
HitsArr[0] = Convert.ToInt32(arr[0]);//全部
HitsArr[1] = Convert.ToInt32(arr[1]);//昨天
HitsArr[2] = Convert.ToInt32(arr[2]);//今天
}
else
{
HitsArr[0] = 0;
HitsArr[1] = 0;
HitsArr[2] = 0;
}
}
HttpRuntime.Cache["b" + CacheName] = HitsArr;
}
else
{
HitsArr = (int[])HttpRuntime.Cache["b" + CacheName];
//HitsArr[0] += 1;
//HitsArr[2] += 1;
}
}
/**//// <summary>
/// 獲取累計的點擊數
/// </summary>
private int Hits
{
get
{
return _Hits;
}
set
{
_Hits = value;
}
}
/**//// <summary>
/// 累加
/// </summary>
/// <param name="id"></param>
private void Add()
{
if(HitsArr[2]<14000)
{
//_Hits = _Hits + new Random(DateTime.Now.Second).Next(60,80);
_Hits = _Hits + 1;
}
else
{
_Hits = _Hits + 1;//_Hits = _Hits + new Random(DateTime.Now.Second).Next(2,8); 傳回指定範圍的隨機數
}
}
/**//// <summary>
/// 文件名
/// </summary>
/// <summary>
/// 獲取文件名
/// </summary>
public string FileName
{
get { return _FileName; }
set { _FileName = value; }
}
}
}
2.創建HttpHandler
<%@ WebHandler Language="C#" Class="HttpHandler" %>
using System;
using System.Web;
using System.Text.RegularExpressions;
namespace MYSpace.Counter
{
/// <summary>
/// HitsHandler 的摘要說明。
/// </summary>
public class CounterHandler : IHttpHandler
{
public void ProcessRequest(HttpContext ctx)
{
CounterHelper objCounterHelper = new CounterHelper(ctx.Request.QueryString["id"].ToString());
objCounterHelper.AddHits();
ctx.Response.Write(string.Format("document.write('頁面訪問量:{0} 昨日:{1} 今日:{2} id :{3}')", objCounterHelper.AllHits, objCounterHelper.YesterdayHits, objCounterHelper.TodayHits, ctx.Request.Url.AbsoluteUri));
}
public bool IsReusable
{
get
{ return false; }
}
}
}
生成dll後創建一個Website,然後把dll引用進來!
接着在web.config裏面添加配置:
<httpHandlers>
<add verb="*" path="count.aspx" type="MYSpace.Counter.CounterHandler,MYSpace.Counter" />
</httpHandlers>
最後在web頁面調用就ok了。頁面代碼如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>無標題頁</title>
<SCRIPT LANGUAGE="JavaScript" src='count.aspx?id=o4'></SCRIPT>
</head>
<body>
<form id="form1" runat="server">
<div>
</div>
</form>
</body>
</html>
很簡單吧,這裏只介紹到寫入文件,如果想寫入庫裏面,直接讀取文件裏的數值就搞定!