用异步缓存确保高流量网页及时更新与低错误率
2009-03-26 17:42:15 来源:WEB开发网我通常的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[] { "" })
- ››异步调用与线程(总结篇)
- ››缓存服务器在Linux下的应用
- ››确保数据质量的基本步骤
- ››确保系统安全:使用 IBM Compliance Expert 有效地...
- ››异步操作和 Web 服务,第 2 部分:构建异步 Web 服...
- ››异步操作和 Web 服务,第 3 部分: 向 Web 服务添加...
- ››确保系统安全 Windows 7 十大禁忌服务
- ››缓存的应用,调用速度要比每次都要从数据库中读要快...
- ››确保邮件系统安全的七条措施
- ››异步操作和 Web 服务,第 1 部分: 异步事务入门
- ››确保Windows电脑系统稳定、运行流畅的六个秘笈
- ››确保远程访问安全的五项策略
更多精彩
赞助商链接