標籤:
緩衝介紹
如果每次進入頁面的時候都查詢資料庫產生頁面內容的話,如果訪問量非常大,則網站效能會非常差,
而如果只有第一次訪問的時候才查詢資料庫產生頁面內容,以後都直接輸出內容,則能提高系統效能,
這樣無論多少人訪問都只訪問一次資料庫,資料庫壓力不變
緩衝是一種用空間換取時間的技術,存在於電腦中很多地方,用來將一些慢速裝置中的常用資料儲存
在快速裝置中,取資料的時候直接從快速裝置中取,比如CPU二級緩衝,WINDOWS檔案讀取緩衝
緩衝存在失效的問題:為了保證從緩衝中讀取資料和慢速資料中資料一致,則需要在慢速資料中對應
的資料發生變化的時候,清除緩衝中相應的資料
緩衝是改進網站效能的第一個手段,就像索引是改進資料庫效能的第一個手段一樣
ASP.NET緩衝主要分為:
頁面緩衝,
資料來源緩衝,
資料緩衝
1.頁面緩衝
給頁面添加 <%@OutputCache Duration="15" VaryByParam="none"%> 標籤就可以啟用頁面緩衝,
這樣整個頁面的內容都會被緩衝,頁面中的ASP.NET代碼,資料來源在緩衝期間都不會運行,而是直接
輸出緩衝的頁面內容,Duration 表示緩衝時候,以秒為單位,超過這個時間則緩衝失效,再次產生以
後會再緩衝15秒,以些類推,在在Page_Load處設定斷點,修改資料庫可測試
緩衝是存在伺服器,不是用戶端,因為用HttpWatch還是能看到向伺服器提交請求
緩衝是針對所有這個頁面的訪問者,這樣1個訪問者和 1萬個訪問者,一次訪問和100萬次訪問對資料
的壓力是一樣的
對於看新聞頁面來講,如果如上設定的話,則會緩衝在第一個看到的新聞,因為?id=2,?id=3隻是頁面
的不兩隻參數而已,為了能讓不同的新聞各自緩衝,因此可以設定VaryByParam="id",表示對於不同的
id參數進行單獨緩衝,如果有多個確定緩衝的參數,則將參數名用 分號; 隔開即可,比如VaryByParam="id;num"
如果想讓任何不同的查詢字串都建立不同的緩衝,則設定VaryByParam="*",一般情況下設定*就足夠
在WebUserControl中也可以像頁面緩衝一樣設定控制項的緩衝
2.資料來源緩衝
設定ObjectDataSource的CacheDuration (緩衝時間:秒),EnableCaching=true
這樣每隔CacheDuration指定的時間段才調用SelectMethod指定的方法來執行資料庫查詢,
其他時候都是直接返回緩衝的資料。
緩衝固定的時間適用於首頁、文章列表等訪問頻繁的頁面,對於看貼頁面則不適合,假設有100萬個
文章,如果每個文章都是固定緩衝1小時的話,假設一小時之內有10萬個文章被看了,那麼就要緩衝
十萬個文章,非常佔用記憶體,因為“百年一看”的“墳帖”偶然被訪問一次也緩衝一個小時,佔用記憶體
這時候可以採用“滑動視窗(sliding)”策略,比如文章緩衝10分鐘,如果10分鐘之內又訪問了,則
緩衝的失效時間修改為從被訪問這一刻起的10分鐘之後,以此類推。這樣經常訪問的文章就可以“長
期緩衝”,而不經常訪問的文章也不會因為偶然訪問而長期佔用緩衝。設定方法,
資料來源:CacheExpirationPolicy="Sliding"
貌似滑動有問題。不是問題,Sliding只是策略,伺服器會參考
3.緩衝其他 (自訂緩衝)
頁面緩衝、資料來源緩衝等內部都是使用HttpRuntime.Cache來實現緩衝的,在一些頁面緩衝、資料來源
緩衝完成不了的特殊的緩衝要求中,可以直接調用HttpRuntime.Cache進行緩衝。在如鵬網項目中會講到
(*)ASP.Net緩衝預設是儲存在記憶體中的,還可以配置儲存到資料庫中,大型網站還會配合使用Memcached等技術
清除緩衝。在緩衝還未失效的時候可能需要立即清空緩衝,讓資料庫的修改立即反映到介面中
ASP.Net沒有提供現成的方法,可以使用Hack層級的代碼
// 儲存緩衝 null 表示緩衝依賴// 鍵,值,緩衝依賴對象,絕對到期時間,區間Cache.Insert("user","xgao",null,DateTime.Now.AddSeconds(10),TimeSpan.Zero);// 簡單儲存緩衝Cache["test"] = "這是一個測試!";//讀取緩衝lbl.text = Cache["user"];
緩衝依賴(依賴於檔案)
原理:它是依賴指定的檔案,一但檔案被刪除,修改,緩衝將也會被刪除
依賴於檔案內容 CacheDependency cDep = new CacheDependency(filePath);
執行個體如下: 實現當檔案內容不變的時候,就讀緩衝的,內容一變就更新緩衝
protected void Page_Load(object sender, EventArgs e){ if (Cache["fileText"] == null) { Response.Write("檔案被修改,緩衝被刪除,但又建立了新的緩衝,下次訪問可得到!"); // 得到指定檔案的實體路徑 string filePath = Server.MapPath("~/CacheDep.txt"); // 讀取指定檔案 string Text = File.ReadAllText(filePath); // 建立緩衝的檔案依賴對象(依賴的檔案的服務實體路徑) CacheDependency cDep = new CacheDependency(filePath); // 鍵,值,緩衝依賴對象,無絕對到期時間,無滑動到期時間,優先順序,更新回呼函數 Cache.Insert("fileText", Text, cDep, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Normal, callback); } else { Response.Write(Cache["fileText"].ToString()); }}// 緩衝依賴的回呼函數(當緩衝被清除時調用些方法)public void callback(string key, object value, CacheItemRemovedReason reason){ string filePath = Server.MapPath("~/CacheLog.txt"); string msg = "Cache["+key+"]="+value+"緩衝被移除,因為:"+reason+"\r\n"; File.AppendAllText(filePath, msg);}
緩衝依賴(依賴於資料庫)
依賴於資料庫內容(輪詢機制/通知機制)
輪詢機制: 是FW不週期性去檢查資料庫
1.在資料庫建立版本表(ID、Ver 欄位 用來儲存某張表的版本)
2.在資料庫建立觸發器(比如在新聞表上建立)
3.使用C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727中的aspnet_regsql.exe:
註冊:aspnet_regsql -S . -E -ed -d 資料庫名 -et -t 版本表名
刪除:aspnet_regsql -S . -E -d 資料庫名 -dt -t 版本表名
取消資料庫緩衝依賴: aspnet_regsql -S . -E -dd 資料庫名 版本表名
列出登入表:aspnet_regsql -S . -E -d 資料庫名 –lt
4.配置web.config
5.資料庫依賴對象
SqlCacheDependency cDep = new SqlCacheDependency("DepName", "BankVer");
aspnet_regsql -S(伺服器) . -E(整合登陸)/-U sa -P 123 -ed(啟動/-dd關閉) -d(資料庫名) GSSMS -et(指定緩衝依賴的表名/-dt禁用表名) -t(表名) Aticle
資料庫依賴 執行個體:
1>. 表bank如下:
------------------------
IDNameManey
------------------------
1xgao1000
2zsan1
3lshi2000
------------------------
表BankVer如下:
--------------
IDVerNum
--------------
10
--------------
2>. 在bank表裡建立觸發器:
create Trigger [bankTri]on [bank]for insert,update,deleteas update BankVer set VerNum=VerNum+1
3>. 開啟資料庫的緩衝依賴(CMD下運行):
aspnet_regsql -S . -E -ed -d TestData -et -t BankVer
4>. 在網站的 web.config配置在 <system.web> 下:
<caching> <sqlCacheDependency enabled="true"> <databases> <!-- pollTime為輪詢時間間隔 15 秒 --> <add name="DepName" connectionStringName="conStr" pollTime="15000"/> </databases> </sqlCacheDependency></caching>
5>. 前台代碼:
<form id="form1" runat="server"> <div> <asp:GridView ID="gvBankList" runat="server"></asp:GridView> </div> </form>
6>. 後台代碼:
protected void Page_Load(object sender, EventArgs e) { if (Cache["bankList"] == null) { Response.Write("資料以更改!以下從資料庫讀取的!</br>"); DataTable dt = GetBankList(); gvBankList.DataSource = dt; gvBankList.DataBind(); SqlCacheDependency sqlDep = new SqlCacheDependency("DepName", "BankVer"); Cache.Insert("bankList", dt, sqlDep, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.Normal,callback); } else { Response.Write("以下是從緩衝裡讀取的</br>"); gvBankList.DataSource = Cache["bankList"]; gvBankList.DataBind(); } } public void callback(string key,object value,CacheItemRemovedReason reason) { string filePath = Server.MapPath("~/CacheLog.txt"); string msg = "資料庫依賴 Cache[" + key + "]=" + value + "緩衝被移除,因為:" + reason + "\r\n"; File.AppendAllText(filePath, msg); } public DataTable GetBankList() { string connStr = ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString; SqlConnection conn = new SqlConnection(connStr); SqlCommand cmd = conn.CreateCommand(); cmd.CommandText = "select * from bank"; DataSet ds = new DataSet(); SqlDataAdapter sda = new SqlDataAdapter(cmd); sda.Fill(ds); return ds.Tables[0]; }
所使用的通知機制:是資料通訊FW
ASP.NET緩衝 Cache