利用HttpHandler和Cache統計點擊量

     因爲訪問量大,做頁面瀏覽量的時候不能直接操作庫;用文件來記錄的話,雖然減緩了數據庫的壓力但是對服務器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>
很簡單吧,這裏只介紹到寫入文件,如果想寫入庫裏面,直接讀取文件裏的數值就搞定!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章