Web開発におけるキャッシュの使用について
23805 ワード
Web Formの開発では、ViewStateという良いものが発見されました.パッケージされたコントロールの中でViewSatateを大量に使用しています.特にパッケージが良いほど、機能が強いコントロールほど、ViewStateが多く使用され、もちろんリソースも多く消費されています.ViewStateは最後にhtmlに解析する時実は暗号化処理を通じて1つの隠しドメインの中に置いて、この隠しドメインの値をコピーして手帳の中で保存することができて、いったいどれだけ大きいかを見て、もしこの保存txtファイルが何MBあることを発見したら、このViewStateの使用は問題があって、ページはきっと遅くて、ページのhtmlが多すぎるため、ブラウザが詰まって死ぬ可能性があります.非表示ドメインはinputであり、フォームのコミット時にサーバにコミットされます.ViewStateが多すぎると、サーバの圧力が増加します.
ページングがなければ、ページに数千ページのデータが直接表示され、ブラウザがどのような効果をもたらすか想像できます.Web Formは便利で迅速な開発を提供し、複雑さも増し、Pageページのライフサイクルを人為的に増やし、普段はView Stateの使用に注意しているが、すべてのものがView Stateを必要としているわけではないし、キャッシュが必要なものがすべてView State、Sessionに置かれているわけではない.もちろん今からASP.NET MVCが流行しているのは、Web Formが時代遅れで淘汰されたという意味ではありません.Web Formは依然として彼の優位性を持っていて、よく利用すれば同じように良い効果を実現することができます.
1、ここではマイクロソフトが提供するWeb開発のキャッシュ方式を紹介する.
System.Web.Caching.Cache
ここでのCacheはキー値ペアでキャッシュし,キャッシュ時間,キャッシュレベルなどを設定しているが,以下,このクラスのソースコードを見ることができる.
このクラスの使用は簡単で、最も主要なのは System.Web.UI.PageこのクラスはデフォルトでこのCacheクラスを使用しています.
このPageクラスの定義を見てみましょう.
2、2つ目は、マイクロソフトのエンタープライズ・ライブラリを使用して提供されるキャッシュです(ここでは詳しく説明しません)
3、自分でキャッシュクラスを書くことができる
ページングがなければ、ページに数千ページのデータが直接表示され、ブラウザがどのような効果をもたらすか想像できます.Web Formは便利で迅速な開発を提供し、複雑さも増し、Pageページのライフサイクルを人為的に増やし、普段はView Stateの使用に注意しているが、すべてのものがView Stateを必要としているわけではないし、キャッシュが必要なものがすべてView State、Sessionに置かれているわけではない.もちろん今からASP.NET MVCが流行しているのは、Web Formが時代遅れで淘汰されたという意味ではありません.Web Formは依然として彼の優位性を持っていて、よく利用すれば同じように良い効果を実現することができます.
1、ここではマイクロソフトが提供するWeb開発のキャッシュ方式を紹介する.
System.Web.Caching.Cache
ここでのCacheはキー値ペアでキャッシュし,キャッシュ時間,キャッシュレベルなどを設定しているが,以下,このクラスのソースコードを見ることができる.
using System;
using System.Collections;
using System.Reflection;
namespace System.Web.Caching
{
/// <summary>
/// Web 。 。
/// </summary>
public sealed class Cache : IEnumerable
{
// Fields
private CacheInternal _cacheInternal;
/// <summary>
/// System.Web.Caching.Cache.Insert(System.String,System.Object) absoluteExpiration
/// 。 。
/// </summary>
public static readonly DateTime NoAbsoluteExpiration = DateTime.MaxValue;
/// <summary>
/// System.Web.Caching.Cache.Insert(System.String,System.Object) System.Web.Caching.Cache.Add(System.String,System.Object,System.Web.Caching.CacheDependency,System.DateTime,System.TimeSpan,System.Web.Caching.CacheItemPriority,System.Web.Caching.CacheItemRemovedCallback)
/// slidingExpiration , 。 。
/// </summary>
public static readonly TimeSpan NoSlidingExpiration = TimeSpan.Zero;
private static CacheItemRemovedCallback s_sentinelRemovedCallback = new CacheItemRemovedCallback(SentinelEntry.OnCacheItemRemovedCallback);
// Methods
[SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
public Cache()
{
}
internal Cache(int dummy)
{
}
/// <summary>
/// System.Web.Caching.Cache , 、 ( Cache )
/// </summary>
/// <param name="key"> 。</param>
/// <param name="value"> 。</param>
/// <param name="dependencies"> 。 , , 。 , null。</param>
/// <param name="absoluteExpiration"> 。 , absoluteExpiration System.Web.Caching.Cache.NoAbsoluteExpiration。</param>
/// <param name="slidingExpiration"> 。 20 , 20 。 ,
/// slidingExpiration System.Web.Caching.Cache.NoSlidingExpiration。</param>
/// <param name="priority"> , System.Web.Caching.CacheItemPriority 。 ; 。</param>
/// <param name="onRemoveCallback"> ( )。 , 。</param>
/// <returns> Cache , System.Object, null。</returns>
public object Add(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback)
{
DateTime utcAbsoluteExpiration = DateTimeUtil.ConvertToUniversalTime(absoluteExpiration);
return this._cacheInternal.DoInsert(true, key, value, dependencies, utcAbsoluteExpiration, slidingExpiration, priority, onRemoveCallback, false);
}
/// <summary>
/// System.Web.Caching.Cache 。
/// </summary>
/// <param name="key"> 。</param>
/// <returns> , null。</returns>
public object Get(string key)
{
return this._cacheInternal.DoGet(true, key, CacheGetOptions.None);
}
internal object Get(string key, CacheGetOptions getOptions)
{
return this._cacheInternal.DoGet(true, key, getOptions);
}
public IDictionaryEnumerator GetEnumerator()
{
return this._cacheInternal.GetEnumerator();
}
public void Insert(string key, object value)
{
this._cacheInternal.DoInsert(true, key, value, null, NoAbsoluteExpiration, NoSlidingExpiration, CacheItemPriority.Normal, null, true);
}
public void Insert(string key, object value, CacheDependency dependencies)
{
this._cacheInternal.DoInsert(true, key, value, dependencies, NoAbsoluteExpiration, NoSlidingExpiration, CacheItemPriority.Normal, null, true);
}
public void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration)
{
DateTime utcAbsoluteExpiration = DateTimeUtil.ConvertToUniversalTime(absoluteExpiration);
this._cacheInternal.DoInsert(true, key, value, dependencies, utcAbsoluteExpiration, slidingExpiration, CacheItemPriority.Normal, null, true);
}
public void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemUpdateCallback onUpdateCallback)
{
if (((dependencies == null) && (absoluteExpiration == NoAbsoluteExpiration)) && (slidingExpiration == NoSlidingExpiration))
{
throw new ArgumentException(SR.GetString("Invalid_Parameters_To_Insert"));
}
if (onUpdateCallback == null)
{
throw new ArgumentNullException("onUpdateCallback");
}
DateTime utcAbsoluteExpiration = DateTimeUtil.ConvertToUniversalTime(absoluteExpiration);
this._cacheInternal.DoInsert(true, key, value, null, NoAbsoluteExpiration, NoSlidingExpiration, CacheItemPriority.NotRemovable, null, true);
string[] cachekeys = new string[] { key };
CacheDependency expensiveObjectDependency = new CacheDependency(null, cachekeys);
if (dependencies == null)
{
dependencies = expensiveObjectDependency;
}
else
{
AggregateCacheDependency dependency2 = new AggregateCacheDependency();
dependency2.Add(new CacheDependency[] { dependencies, expensiveObjectDependency });
dependencies = dependency2;
}
this._cacheInternal.DoInsert(false, "w" + key, new SentinelEntry(key, expensiveObjectDependency, onUpdateCallback), dependencies, utcAbsoluteExpiration, slidingExpiration, CacheItemPriority.NotRemovable, s_sentinelRemovedCallback, true);
}
public void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback)
{
DateTime utcAbsoluteExpiration = DateTimeUtil.ConvertToUniversalTime(absoluteExpiration);
this._cacheInternal.DoInsert(true, key, value, dependencies, utcAbsoluteExpiration, slidingExpiration, priority, onRemoveCallback, true);
}
/// <summary>
/// System.Web.Caching.Cache 。
/// </summary>
/// <param name="key"> System.String 。</param>
/// <returns> Cache 。 , null。</returns>
public object Remove(string key)
{
CacheKey cacheKey = new CacheKey(key, true);
return this._cacheInternal.DoRemove(cacheKey, CacheItemRemovedReason.Removed);
}
internal void SetCacheInternal(CacheInternal cacheInternal)
{
this._cacheInternal = cacheInternal;
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)this._cacheInternal).GetEnumerator();
}
// Properties
public int Count
{
get
{
return this._cacheInternal.PublicCount;
}
}
public long EffectivePercentagePhysicalMemoryLimit
{
get
{
return this._cacheInternal.EffectivePercentagePhysicalMemoryLimit;
}
}
public long EffectivePrivateBytesLimit
{
get
{
return this._cacheInternal.EffectivePrivateBytesLimit;
}
}
public object this[string key]
{
get
{
return this.Get(key);
}
set
{
this.Insert(key, value);
}
}
// Nested Types
private class SentinelEntry
{
// Fields
private CacheItemUpdateCallback _cacheItemUpdateCallback;
private CacheDependency _expensiveObjectDependency;
private string _key;
// Methods
public SentinelEntry(string key, CacheDependency expensiveObjectDependency, CacheItemUpdateCallback callback)
{
this._key = key;
this._expensiveObjectDependency = expensiveObjectDependency;
this._cacheItemUpdateCallback = callback;
}
public static void OnCacheItemRemovedCallback(string key, object value, CacheItemRemovedReason reason)
{
CacheItemUpdateReason expired;
CacheItemUpdateCallback callback;
Cache.SentinelEntry entry = value as Cache.SentinelEntry;
switch (reason)
{
case CacheItemRemovedReason.Expired:
expired = CacheItemUpdateReason.Expired;
goto Label_0034;
case CacheItemRemovedReason.Underused:
break;
case CacheItemRemovedReason.DependencyChanged:
expired = CacheItemUpdateReason.DependencyChanged;
if (!entry.ExpensiveObjectDependency.HasChanged)
{
goto Label_0034;
}
break;
default:
return;
}
return;
Label_0034:
callback = entry.CacheItemUpdateCallback;
try
{
CacheDependency dependency;
DateTime time;
TimeSpan span;
object obj2;
callback(entry.Key, expired, out obj2, out dependency, out time, out span);
if ((obj2 != null) && ((dependency == null) || !dependency.HasChanged))
{
HttpRuntime.Cache.Insert(entry.Key, obj2, dependency, time, span, entry.CacheItemUpdateCallback);
}
else
{
HttpRuntime.Cache.Remove(entry.Key);
}
}
catch (Exception exception)
{
HttpRuntime.Cache.Remove(entry.Key);
try
{
WebBaseEvent.RaiseRuntimeError(exception, value);
}
catch
{
}
}
}
// Properties
public CacheItemUpdateCallback CacheItemUpdateCallback
{
get
{
return this._cacheItemUpdateCallback;
}
}
public CacheDependency ExpensiveObjectDependency
{
get
{
return this._expensiveObjectDependency;
}
}
public string Key
{
get
{
return this._key;
}
}
}
}
}
このクラスの使用は簡単で、最も主要なのは System.Web.UI.PageこのクラスはデフォルトでこのCacheクラスを使用しています.
このPageクラスの定義を見てみましょう.
public class Page : TemplateControl, IHttpHandler
{
public Cache Cache { get; }
}
このCacheはpublicプロパティで、直接使用できます.キャッシュはメモリに保存されています.毎回データベースやファイルから読み込む必要はありません.このViewStateを使用する必要はありません.2、2つ目は、マイクロソフトのエンタープライズ・ライブラリを使用して提供されるキャッシュです(ここでは詳しく説明しません)
3、自分でキャッシュクラスを書くことができる
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
namespace ConsoleApplication1
{
public sealed class Cache
{
private Dictionary<string, CacheObject> _directory = new Dictionary<string, CacheObject>();
private static Cache _instance = null;
private static string _lock = "lock";
private Thread _thread = null;
private int _interval = 5000;
/// <summary>
/// ( 5000 )
/// </summary>
public int Interval
{
get { return _interval; }
set { _interval = value; }
}
public static Cache GetInstance()
{
lock (_lock)
{
if (_instance == null)
{
_instance = new Cache();
}
return _instance;
}
}
private Cache()
: this(true)
{
//
}
/// <summary>
///
/// </summary>
/// <param name="autoClear">true: ;false: </param>
private Cache(bool autoClear)
{
if (autoClear)
{
_thread = new Thread(new ThreadStart(ClearThread));
//_thread.IsBackground = true;
_thread.Start();
}
}
private void ClearThread()
{
while (_directory != null)
{
Thread.Sleep(_interval);
ClearTimeout();
}
}
private void ClearTimeout()
{
lock (_directory)
{
List<string> list = new List<string>();
foreach (KeyValuePair<string, CacheObject> item in _directory)
{
if (item.Value.StopTime == null || item.Value.StopTime < DateTime.Now)
{
if (item.Value.CallBack != null)
{
item.Value.CallBack.Invoke(item.Value.StorageObject, null);
}
list.Add(item.Key);
}
}
foreach (string item in list)
{
_directory.Remove(item);
}
}
}
/// <summary>
///
/// </summary>
/// <param name="key"> </param>
/// <returns>true|false</returns>
public bool Exist(string key)
{
ClearTimeout();
lock (_directory)
{
return _directory.ContainsKey(key);
}
}
/// <summary>
///
/// </summary>
/// <param name="key"> </param>
/// <returns>true|false</returns>
public bool Remove(string key)
{
lock (_directory)
{
CacheObject obj = null;
if (_directory.TryGetValue(key, out obj))
{
if (obj.CallBack != null)
{
obj.CallBack.Invoke(obj.StorageObject, null);
}
}
return _directory.Remove(key);
}
}
/// <summary>
///
/// </summary>
/// <param name="key"> </param>
/// <returns></returns>
public object Get(string key)
{
ClearTimeout();
object rtn = null;
lock (_directory)
{
foreach (KeyValuePair<string, CacheObject> item in _directory)
{
if (item.Key == key)
{
// ,
if (item.Value.TimeSpan != TimeSpan.MinValue)
{
item.Value.StartTime = DateTime.Now;
item.Value.StopTime = DateTime.Now + item.Value.TimeSpan;
}
rtn = item.Value.StorageObject;
break;
}
}
}
return rtn;
}
public object this[string key]
{
get
{
return Get(key);
}
set
{
ClearTimeout();
Add(key, value);
}
}
/// <summary>
/// ( 20 )
/// ,
/// </summary>
/// <param name="key"> </param>
/// <param name="value"> </param>
/// <returns>true|false</returns>
public bool Add(string key, object value)
{
return Add(key, value, DateTime.Now.AddMinutes(20));
}
/// <summary>
/// 、
/// </summary>
/// <param name="key"> </param>
/// <param name="value"> </param>
/// <param name="time"> </param>
/// <returns></returns>
public bool Add(string key, object value, DateTime time)
{
return Add(key, value, time, null);
}
/// <summary>
/// 、
/// </summary>
/// <param name="key"> </param>
/// <param name="value"> </param>
/// <param name="time"> </param>
/// <param name="callBack"> </param>
/// <returns></returns>
public bool Add(string key, object value, DateTime time, EventHandler callBack)
{
return Add(key, value, TimeSpan.MinValue, time, callBack);
}
/// <summary>
/// ( , , )
/// </summary>
/// <param name="key"> </param>
/// <param name="value"> </param>
/// <param name="timeSpan"> </param>
/// <param name="time"> </param>
/// <param name="callBack"> </param>
/// <returns>true|false</returns>
private bool Add(string key, object value, TimeSpan timeSpan, DateTime time, EventHandler callBack)
{
bool flag = false;
lock (_directory)
{
// 、
if (_directory.ContainsKey(key))
{
foreach (KeyValuePair<string, CacheObject> item in _directory)
{
if (item.Key == key)
{
item.Value.StorageObject = value;
item.Value.CallBack = callBack;
flag = true;
break;
}
}
}
else
{
CacheObject obj = new CacheObject();
obj.StorageObject = value;
obj.CallBack = callBack;
obj.TimeSpan = timeSpan;
obj.StartTime = DateTime.Now;
if (timeSpan == TimeSpan.MinValue)
{
obj.StopTime = time;
}
else
{
obj.StopTime = DateTime.Now + timeSpan;
}
_directory.Add(key, obj);
flag = true;
}
}
return flag;
}
/// <summary>
/// 、 ( )
/// </summary>
/// <param name="key"> </param>
/// <param name="value"> </param>
/// <param name="timeSpan"> 、 </param>
/// <returns></returns>
public bool Add(string key, object value, TimeSpan timeSpan)
{
return Add(key, value, timeSpan, DateTime.MinValue, null);
}
/// <summary>
/// 、 ( )
/// </summary>
/// <param name="key"> </param>
/// <param name="value"> </param>
/// <param name="timeSpan"> 、 </param>
/// <param name="callBack"> </param>
/// <returns></returns>
public bool Add(string key, object value, TimeSpan timeSpan, EventHandler callBack)
{
return Add(key, value, timeSpan, DateTime.MinValue, callBack);
}
}
class CacheObject
{
private object _storageObject = null;
/// <summary>
///
/// </summary>
public object StorageObject
{
get { return _storageObject; }
set { _storageObject = value; }
}
private DateTime _startTime = DateTime.Now;
/// <summary>
///
/// </summary>
public DateTime StartTime
{
get { return _startTime; }
set { _startTime = value; }
}
private DateTime _StopTime = DateTime.Now;
/// <summary>
///
/// </summary>
public DateTime StopTime
{
get { return _StopTime; }
set { _StopTime = value; }
}
private TimeSpan _timeSpan = TimeSpan.MinValue;
/// <summary>
///
/// </summary>
public TimeSpan TimeSpan
{
get { return _timeSpan; }
set { _timeSpan = value; }
}
private EventHandler _callBack = null;
/// <summary>
///
/// </summary>
public EventHandler CallBack
{
get { return _callBack; }
set { _callBack = value; }
}
}
}