我通常的WEB開發中,有時我們會碰以這種情況,一個頁面有很多模塊組成,而這些模塊之間是不關鏈的,就像一個網站的首頁,里面有很多塊塊,有些是讀新聞的,有些是讀產品信息,還有一些部分是讀論壇,博客之類的地方.而這個頁面的要求是很高的,無論在什么情況下都要保證頁面是可以正確打開的(當然服務器故障是沒有辦法的).而且網站的流量很大.
通常這樣的頁面是需要生成靜態頁來保證頁面正確的,但是這種做法會有很大的問題,如果網站中一個小塊異常了,會導致整個頁面不更新.
現在我們給出這樣一個解決方案:頁面分兩級緩存,一級為內存緩存,二級為文件緩存.這里的文件緩存是起輔助做用的,有一種特殊的情況,一個asp.net應用程序池是會重新初始化的,初始化完過后,內存數據會被清空,這個時候如果我們直接去執行數據訪問程序,那么我們不能保證當時情況下程序的正確性和性能(對于程序調用過多的頁面來說,執行速度慢,大量的并發請求會導致服務器崩潰).
也就是說,對于頁面程序來說,如果程序一執行會先去讀內存,如果發現內存為空,那么改去讀相應的緩存文件,如果文件還沒生成,那么再執行程序(這種情況只在程序在服務器上第一運行是發生).
為了確保頁面更新及時,這里需要異步緩存,也就是說為每一個模塊起一個線程來維護,如果線程方法執行成功,那么更新內存中的內容.這里建議把文件更新另起一個線程式,因為文件更新可以時間間隔長一起,結約系統資源.例如,每個模塊內存更新速度是20秒,那么文件的可以設為5分鐘.
下面給出一段代碼,這個主要是用于緩存處理的.....
+ expand sourceview plaincopy to clipboardPRint?
using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.xml.Linq;
using System.IO;
using System.Collections.Generic;
using System.Threading;
using System.Diagnostics;
/// <summary>
/// 本類主要負責處理根把相關參數設置緩存結果
/// </summary>
public class CacheSvr
{
public delegate string ProcessDataDelegate(params object[] args);
public static string cacheDir = "D:/tmpFile";
public static Dictionary<string, string> cacheTable = new Dictionary<string, string>();
public static ReaderWriterLockSlim lockx = new ReaderWriterLockSlim();
public static Dictionary<string, Thread> threadTable = new Dictionary<string, Thread>();
public CacheSvr()
{
//
// TODO: Add constructor logic here
//
}
#region 文件緩存邏輯
/// <summary>
/// 保存程序執行結果致文件
/// </summary>
/// <param name="thisDelegate">所要執行的方法</param>
/// <param name="fileName">文件名</param>
/// <param name="args">參數列表</param>
/// <returns></returns>
public static void saveDataFile(CacheItem item)
{
string result = item.doProcess();
if (result.Length > 0)
{
write(result, item.CacheName);
}
}
/// <summary>
/// 寫文件代碼
/// </summary>
/// <param name="text">寫入內容</param>
/// <param name="fileName">文件名</param>
public static void write(String text, string fileName)
{
try
{
String path = cacheDir;
path = path + fileName + ".cache";
Stream fsc = File.Create(path);
fsc.Close();
Stream fs = File.Open(path, FileMode.Open, Fileaccess.Write);
TextWriter tw = new StreamWriter(fs, System.Text.Encoding.GetEncoding(936));
tw.Write(text);
tw.Close();
fs.Close();
}
catch
{
}
}
public static string readFile(string fileName)
{
string content = "";
try
{
//Stopwatch watch = new Stopwatch();
//watch.Start();
String path = cacheDir;
path = path + fileName + ".cache";
Stream fs = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read);
StreamReader tr = new StreamReader(fs, System.Text.Encoding.GetEncoding(936));
content = tr.ReadToEnd();
//content += "/r/n <!--read from file " + path + "--> /r/n";
tr.Close();
fs.Close();
//watch.Stop();
//content = content + "<!--執行時間為:" + watch.ElapsedMilliseconds + "-->/r/n";
}
catch
{
content = "";
}
return content;
}
#endregion
#region 內存緩存模塊
/// <summary>
/// 內存緩存
/// </summary>
/// <param name="thisDelegate">所需執行的方法</param>
/// <param name="cacheName">內存中的名字</param>
/// <param name="args">參數列表</param>
/// <returns></returns>
public static void saveDataCache(CacheItem item)
{
string result = item.doProcess();
if (result.Length > 0)
{
cache(result, item.CacheName);
}
}
/// <summary>
/// 向內存中寫入內容
/// </summary>
/// <param name="text"></param>
/// <param name="cacheName"></param>
public static void cache(string text, string cacheName)
{
lockx.EnterWriteLock();
try
{
//text += "/r/n<!--緩存更新,時間為:" + DateTime.Now.ToString() + "-->/r/n";
cacheTable[cacheName] = text;
}
catch { }
finally { lockx.ExitWriteLock(); }
}
public static void writelog(String text, string fileName)
{
try
{
String path = cacheDir;
path = path + fileName + ".cache";
if (!File.Exists(path))
{
Stream fsc = File.Create(path);
fsc.Close();
}
Stream fs = File.Open(path, FileMode.Append, FileAccess.Write);
TextWriter tw = new StreamWriter(fs, System.Text.Encoding.GetEncoding(936));
tw.Write(text);
tw.Close();
fs.Close();
}
catch
{
}
}
public static string readCache(string cacheName)
{
string content = "";
lockx.EnterReadLock();
try
{
bool result = cacheTable.TryGetValue(cacheName, out content);
//if (result)
//{
// content += "/r/n <!--read from memory--> /r/n";
//}
return content;
}
catch
{
return "";
}
finally
{
lockx.ExitReadLock();
}
}
#endregion
#region 線程處理模塊
public static void UpdateCache(object obj)
{
CacheItem thisCache = (CacheItem)obj;
writelog("線程:" + thisCache.CacheName + "--啟動于:" + DateTime.Now.ToString() + "/r/n", "exceptions");
while (true)
{
try
{
saveDataCache(thisCache);
}
catch
{
}
Thread.Sleep(thisCache.memoryTime * 1000);//內存20秒更新
}
}
public static void UpdateFile(object obj)
{
CacheItem thisCache = (CacheItem)obj;
while (true)
{
try
{
saveDataFile(thisCache);
}
catch
{
}
Thread.Sleep(thisCache.fileTime * 1000);//文件2分鐘緩存
}
}
public static Thread getThread(string threadName)
{
Thread tmpThread = null;
lockx.EnterReadLock();
try
{
if (threadTable.Keys.Contains(threadName))
{
tmpThread = threadTable[threadName];
}
}
catch
{
}
finally
{
lockx.ExitReadLock();
}
return tmpThread;
}
/// <summary>
/// 添加緩存
/// </summary>
/// <param name="item">緩存對象</param>
public static void saveCache(CacheItem item)
{
string mCacheName = item.CacheName + "_memory";
string fCacheName = item.CacheName + "_file";
Thread memoryCache = getThread(mCacheName);
Thread fileCache = getThread(fCacheName);
if (memoryCache == null)
{
memoryCache = new Thread(new ParameterizedThreadStart(UpdateCache));
memoryCache.IsBackground = true;
memoryCache.Start(item);
}
if (fileCache == null)
{
fileCache = new Thread(new ParameterizedThreadStart(UpdateFile));
fileCache.IsBackground = true;
fileCache.Start(item);
}
lockx.EnterWriteLock();
try
{
threadTable[mCacheName] = memoryCache;
threadTable[fCacheName] = fileCache;
}
catch { }
finally { lockx.ExitWriteLock(); }
}
public static string readCacheContent(CacheItem item)
{
//Stopwatch watch = new Stopwatch();
//watch.Start();
string content = readCache(item.CacheName);
if (content==null || content.Length < 0)
{
content = readFile(item.CacheName);
saveCache(item);
}
//讀取緩存失敗
if (content != null && content.Length <= 0)
{
//throw (new Exception("讀取內容失敗:" + item.CacheName));
content = item.doProcess();
//saveCache(item);
}
return content;
//watch.Stop();
//content += ("/r/n<!--方法執行時間:" + watch.ElapsedMilliseconds + "-->/r/n");
}
#endregion
#region 公共處理
public static string saveCache(string cacheName, ProcessDataDelegate mainMathod, object[] args)
{
using (CacheItem tmpCache = new CacheItem())
{
tmpCache.CacheName = cacheName;
tmpCache.CacheDelegate = mainMathod;
tmpCache.CacheArgs = args;
string content = "";
content = readCacheContent(tmpCache);
return content;
}
}
#endregion
}
using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Xml.Linq;
using System.IO;
using System.Collections.Generic;
using System.Threading;
using System.Diagnostics;
/// <summary>
/// 本類主要負責處理根把相關參數設置緩存結果
/// </summary>
public class CacheSvr
{
public delegate string ProcessDataDelegate(params object[] args);
public static string cacheDir = "D:/tmpFile";
public static Dictionary<string, string> cacheTable = new Dictionary<string, string>();
public static ReaderWriterLockSlim lockx = new ReaderWriterLockSlim();
public static Dictionary<string, Thread> threadTable = new Dictionary<string, Thread>();
public CacheSvr()
{
//
// TODO: Add constructor logic here
//
}
#region 文件緩存邏輯
/// <summary>
/// 保存程序執行結果致文件
/// </summary>
/// <param name="thisDelegate">所要執行的方法</param>
/// <param name="fileName">文件名</param>
/// <param name="args">參數列表</param>
/// <returns></returns>
public static void saveDataFile(CacheItem item)
{
string result = item.doProcess();
if (result.Length > 0)
{
write(result, item.CacheName);
}
}
/// <summary>
/// 寫文件代碼
/// </summary>
/// <param name="text">寫入內容</param>
/// <param name="fileName">文件名</param>
public static void write(String text, string fileName)
{
try
{
String path = cacheDir;
path = path + fileName + ".cache";
Stream fsc = File.Create(path);
fsc.Close();
Stream fs = File.Open(path, FileMode.Open, FileAccess.Write);
TextWriter tw = new StreamWriter(fs, System.Text.Encoding.GetEncoding(936));
tw.Write(text);
tw.Close();
fs.Close();
}
catch
{
}
}
public static string readFile(string fileName)
{
string content = "";
try
{
//Stopwatch watch = new Stopwatch();
//watch.Start();
String path = cacheDir;
path = path + fileName + ".cache";
Stream fs = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read);
StreamReader tr = new StreamReader(fs, System.Text.Encoding.GetEncoding(936));
content = tr.ReadToEnd();
//content += "/r/n <!--read from file " + path + "--> /r/n";
tr.Close();
fs.Close();
//watch.Stop();
//content = content + "<!--執行時間為:" + watch.ElapsedMilliseconds + "-->/r/n";
}
catch
{
content = "";
}
return content;
}
#endregion
#region 內存緩存模塊
/// <summary>
/// 內存緩存
/// </summary>
/// <param name="thisDelegate">所需執行的方法</param>
/// <param name="cacheName">內存中的名字</param>
/// <param name="args">參數列表</param>
/// <returns></returns>
public static void saveDataCache(CacheItem item)
{
string result = item.doProcess();
if (result.Length > 0)
{
cache(result, item.CacheName);
}
}
/// <summary>
/// 向內存中寫入內容
/// </summary>
/// <param name="text"></param>
/// <param name="cacheName"></param>
public static void cache(string text, string cacheName)
{
lockx.EnterWriteLock();
try
{
//text += "/r/n<!--緩存更新,時間為:" + DateTime.Now.ToString() + "-->/r/n";
cacheTable[cacheName] = text;
}
catch { }
finally { lockx.ExitWriteLock(); }
}
public static void writelog(String text, string fileName)
{
try
{
String path = cacheDir;
path = path + fileName + ".cache";
if (!File.Exists(path))
{
Stream fsc = File.Create(path);
fsc.Close();
}
Stream fs = File.Open(path, FileMode.Append, FileAccess.Write);
TextWriter tw = new StreamWriter(fs, System.Text.Encoding.GetEncoding(936));
tw.Write(text);
tw.Close();
fs.Close();
}
catch
{
}
}
public static string readCache(string cacheName)
{
string content = "";
lockx.EnterReadLock();
try
{
bool result = cacheTable.TryGetValue(cacheName, out content);
//if (result)
//{
// content += "/r/n <!--read from memory--> /r/n";
//}
return content;
}
catch
{
return "";
}
finally
{
lockx.ExitReadLock();
}
}
#endregion
#region 線程處理模塊
public static void UpdateCache(object obj)
{
CacheItem thisCache = (CacheItem)obj;
writelog("線程:" + thisCache.CacheName + "--啟動于:" + DateTime.Now.ToString() + "/r/n", "exceptions");
while (true)
{
try
{
saveDataCache(thisCache);
}
catch
{
}
Thread.Sleep(thisCache.memoryTime * 1000);//內存20秒更新
}
}
public static void UpdateFile(object obj)
{
CacheItem thisCache = (CacheItem)obj;
while (true)
{
try
{
saveDataFile(thisCache);
}
catch
{
}
Thread.Sleep(thisCache.fileTime * 1000);//文件2分鐘緩存
}
}
public static Thread getThread(string threadName)
{
Thread tmpThread = null;
lockx.EnterReadLock();
try
{
if (threadTable.Keys.Contains(threadName))
{
tmpThread = threadTable[threadName];
}
}
catch
{
}
finally
{
lockx.ExitReadLock();
}
return tmpThread;
}
/// <summary>
/// 添加緩存
/// </summary>
/// <param name="item">緩存對象</param>
public static void saveCache(CacheItem item)
{
string mCacheName = item.CacheName + "_memory";
string fCacheName = item.CacheName + "_file";
Thread memoryCache = getThread(mCacheName);
Thread fileCache = getThread(fCacheName);
if (memoryCache == null)
{
memoryCache = new Thread(new ParameterizedThreadStart(UpdateCache));
memoryCache.IsBackground = true;
memoryCache.Start(item);
}
if (fileCache == null)
{
fileCache = new Thread(new ParameterizedThreadStart(UpdateFile));
fileCache.IsBackground = true;
fileCache.Start(item);
}
lockx.EnterWriteLock();
try
{
threadTable[mCacheName] = memoryCache;
threadTable[fCacheName] = fileCache;
}
catch { }
finally { lockx.ExitWriteLock(); }
}
public static string readCacheContent(CacheItem item)
{
//Stopwatch watch = new Stopwatch();
//watch.Start();
string content = readCache(item.CacheName);
if (content==null || content.Length < 0)
{
content = readFile(item.CacheName);
saveCache(item);
}
//讀取緩存失敗
if (content != null && content.Length <= 0)
{
//throw (new Exception("讀取內容失敗:" + item.CacheName));
content = item.doProcess();
//saveCache(item);
}
return content;
//watch.Stop();
//content += ("/r/n<!--方法執行時間:" + watch.ElapsedMilliseconds + "-->/r/n");
}
#endregion
#region 公共處理
public static string saveCache(string cacheName, ProcessDataDelegate mainMathod, object[] args)
{
using (CacheItem tmpCache = new CacheItem())
{
tmpCache.CacheName = cacheName;
tmpCache.CacheDelegate = mainMathod;
tmpCache.CacheArgs = args;
string content = "";
content = readCacheContent(tmpCache);
return content;
}
}
#endregion
}
現在給一個使用的例子:
view plaincopy to clipboardprint?
#region 廣告下文字鏈
public static string getTopAdList(params object[] args)
{
BeanOper oper = new BeanOper();
StringBuilder result = new StringBuilder();
result.Append("<div class=/"ad1/">");
result.Append("<ul>");
result.Append(oper.getAdNewsHtml(3519, 1, 9, "ad1_"));
result.Append("</ul>");
result.Append("<div class=/"clear/"></div>");
result.Append("</div>");
return result.ToString();
}
#endregion
CacheSvr.saveCache("TopAdList", new CacheSvr.ProcessDataDelegate(IndexHtml.getTopAdList), new object[] { "" })
新聞熱點
疑難解答