65.9K
CodeProject 正在变化。 阅读更多。
Home

WCF 缓存

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.69/5 (15投票s)

2009年12月9日

CPOL

4分钟阅读

viewsIcon

107297

downloadIcon

4073

一个WCF服务缓存的例子。

caching_enabled_20s.JPG

引言

在本文中,我将讨论WCF服务中的缓存,并演示如何实现WCF缓存。

源代码

源代码包含两个Windows应用程序。第一个托管一个演示WCF服务。第二个应用程序是WCF演示客户端。解决方案还包含我编写的WCFCache类,该类允许您轻松地将缓存功能添加到WCF服务或任何其他类型的应用程序。要运行代码,您需要下载AdventureWorks数据库,该数据库可以从这里下载。此外,您需要使用所需的值更新WCF服务器的配置文件中的连接字符串。

WCF缓存

如果明智地使用,WCF中的缓存绝对是一件好事。假设您在服务中有一个执行昂贵查询的方法,并且此方法经常被调用,那么很大一部分调用都会提取相同的数据,结果数据的大小不至于太大而无法存储在内存中(当然,如果它将被存储在内存中),并且数据可以被认为是有效的,那么这是使用某种缓存的理想场所。

如何将缓存添加到WCF?您可以实现一个自定义解决方案,例如这个,您可以使用一些第三方组件,或者您可以使用System.Web.Caching.Cache类。我不推荐最后一个,因为我从未在此上下文中使用过它。我在网络上发现了关于此的不同意见。对我来说,微软明确建议不要这样做这一事实就足以成为不使用的理由:“Cache类不适用于ASP.NET应用程序之外。它专为在ASP.NET中使用而设计和测试,以提供Web应用程序的缓存。在其他类型的应用程序中,例如控制台应用程序或Windows Forms应用程序,ASP.NET缓存可能无法正常工作。” http://msdn.microsoft.com/en-us/library/system.web.caching.cache.aspx

一个典型的使用缓存的数据访问方法执行以下两个常规步骤:检查缓存中是否存在请求的数据,如果找到则返回数据。如果未在缓存中找到数据,则从数据存储中提取数据,将其存储在缓存中,然后返回数据。

此外,您必须注意在特定条件下删除或更新缓存中的数据。通常,这是在数据不再有效(已更改,或未更新太长时间)或数据未使用太长时间时完成的。

使用WCFCache类

该类的设计目的是提供与System.Web.Caching.Cache类似的功能。该类通过其静态属性使用。它允许您从缓存中添加或删除项目。它具有指示项目过期时间和/或滑动过期时间的可能性。以下是一些使用该类的例子

//add/update an item to the cache. No expiration date. No sliding expiration time.
WCFCache.Current[productID] = product;

//add/update an item in the cache.
//The item will expire in 2 minutes. No sliding expiration time.
WCFCache.Current.Insert(productID, product, DateTime.Now.AddMinutes(2));

//add/update an item to the cache. No expiration date. 
//Expiration sliding time is 30 seconds.
WCFCache.Current.Insert(productID, product, new TimeSpan(0, 0, 30), true);

//get an item from the cache
product = (Product)WCFCache.Current[productID]

//change cache refresh frequency. Default value is 20 seconds.
//This means each 20 seconds the cache is inspected for expired items.
WCFCache.Current.CacheRefreshFrequency = new TimeSpan(0,0,10);

现在,让我们稍微讨论一下它的实现方式。在内部,数据存储在哈希表中以便更快地访问。为了使该类线程安全,我使用了ReaderWriterLockSlim类。ReaderWriterLockSlim允许多个线程进行读取和独占访问进行写入。以下是Insert方法的一个重载版本的实现方式

public void Insert(object key, object value)
{
    _itemsLock.EnterWriteLock();
    try
     {
          _items[key] = new WCFCacheItem(value);
      }
      finally
      {
          _itemsLock.ExitWriteLock();
      }
}

其中_itemsLockReaderWriterLockSlim_items是哈希表。

为了检查缓存中过期的项目,我使用了System.Threading.Timer

代码测试

为了测试该类,我创建了一个WCF服务和WCF客户端,两者都是Windows应用程序的形式。客户端在启动时创建一定数量(可从UI配置)的线程。每个线程将选择一个随机的产品ID,并尝试从服务器获取该产品的数据。在服务器端,公开了两种方法。一种用于获取初始的产品ID列表,另一种用于获取特定产品的数据。只有第二种方法使用缓存。可以在服务器UI中禁用或启用缓存。此外,可以指定创建的缓存项目的滑动过期时间。以下是使用缓存启用的测试运行5分钟的结果

caching_enabled_40s.JPG

和禁用缓存

caching_disabled.JPG

正如您所看到的,启用缓存的平均调用时间为78毫秒,禁用缓存的平均调用时间为528毫秒。如果获取产品的查询运行时间更长,那么差异将相应地更大。

结论

感谢您的阅读。 我希望这对您有用。

© . All rights reserved.