英文原文:http://msdn.microsoft.com/zh-cn/library/cc511588(en-us).aspx
Enterprise Library 缓存应用程序块允许开发人员在应用程序中合并一个局部缓存,它支持内存内的缓存,和可选的可以是数据库存储或独立存储的后端存储。应用程序块可以不做修改的使用,它提供所有必须的获取、添加和移除缓存数据的功能。可配置的到期和清除策略也是应用程序块的一部分。
在构建企业范围发布的应用程序时,架构和开发人员都要面对许多挑战,缓存可以帮助他们战胜其中的包括下面这些挑战:
- 性能。缓存用存储数据使用者尽可能关闭的相应数据来提高应用程序的性能,这避免了重复数据的创建、处理和传输。
- 可扩展性。在缓存中存储信息有利于节省资源,并在应用程序需求增加时提高可扩展性。
- 可用性。将数据存储在缓存中,应用程序也许可以在系统失败时幸存,如网络延迟、Web 服务问题和硬件错误。
普通场景
缓存应用程序块适用于下列性情况:
- 必须重复访问表态数据或者很少改变的数据。
- 在创建、访问或传输中数据访问是昂贵的。
- 数据必须总是可用的,即使在源,如服务器不可用时。
可以在下列应用程序类型中使用缓存应用程序块:
- Windows Forms
- 控制台应用程序
- Windows 服务
- COM+ 服务器
- ASP.NET Web 应用程序或者 Web 服务,如果需要的特性没有包括在 ASP.NET 缓存中。
缓存应用程序块将部署在一个独立的应用程序域中,每个应用程序域可以有一个或多个缓存,有或没有后端存储都可以。缓存不能在不同应用程序域*享。
缓存应用程序块优化了性能,并且是线程安全和异常安全的。可以扩展它以包含自己的到期策略和后端存储。
示例应用代码
下列代码展示了如何添加一个条目到缓存中,并从缓存中取出一个条目。它创建了一个 Product 类型的对象,然后将它添加到缓存中,一起的还有为2的清除优先级、一条在条目到期后不刷新它的指令、以及从条目最后一次访问开始的5分钟的有效期。
ICacheManager productsCache = CacheFactory.GetCacheManager();
string id = "ProductOneId";
string name = "ProductXYName";
int price = 50;
Product product = new Product(id, name, price);
productsCache.Add(product.ProductID, product, CacheItemPriority.Normal, null, new SlidingTime(TimeSpan.FromMinutes(5)));
// Retrieve the item.
product = (Product) productsCache.GetData(id);
缓存应用程序块的亮点
Enterprise Library 缓存的应用程序块包括以下特性:
- 您可以使用图形化的Enterprise Library 配置工具来管理配置。
- 您可以设置一个持久的存储位置,使用隔离存储或Enterprise Library 数据访问的应用程序块,其状态是与在内存中缓存同步的。
- 您可以扩展应用程序块,通过由创建自定义到期的政策和存储位置。
- 您可以得到应用程序块在一个线程安全的方式执行的保证。
决定何时使用缓存的应用程序块
缓存的应用程序块的的设计的目标是当应用程序和缓存存在于同一系统最常见的数据高速缓存的情况。高速缓存是本地这意味着只有该应用程序能够使用。 当它运作是这些指导方针,应用程序块是下列情况理想的解决方案:
- 场景需要以一致形式在不同的应用环境中使用缓存 。例如,通过使用缓存的应用程序块,开发人员可以写类似的代码执行缓存中的应用组件宿主在Internet信息服务( IIS ),企业服务,以及智能客户端的环境。此外,同样的缓存配置选项可用于所有环境。
- 场景需要一个可配置的和后端存储持久化 。缓存的应用程序块既支持独立的存储和数据库后端存储。开发人员可以创建额外的后端存储提供者并把它们添加到缓存的应用程序块的配置设置。 应用程序块也可以数据缓存保存到后端存储之前进行加密。
- 场景需要 改变缓存的配置而不需要修改应用程序源代码 。开发人员首先写代码使用一个或多个命名的缓存。系统操作者和开发人员就可以使用Enterprise Library 配置工具设置这些命名缓存。
- 缓存项需要下列任何过期设置:绝对时间,滑动时间,延长时间格式(例如,每天晚上的午夜十点),文件的依赖,或从不过期 。 关于过期设置更详细信息,请参看缓存的过期设计过程 。
- 开发人员希望修改缓存的应用程序块的源代码 。关于如何修改缓存的应用程序块的更详细信息,参见修改应用程序设计指导。
此外,缓存应用程序块提供了一个与其他Enterprise Library的应用应用程序块一样的一致的开发模式。 缓存的应用程序块与数据访问的应用程序块为后端存储的功能无缝集成。在相同的方式,安全应用程序块,包括缓存的应用程序块所提供的缓存的能力。开发人员和操作人员使用使用Enterprise Library配置工具配置的应用应用程序块。
替换使用缓存的应用程序块
当有多个应用程序需要使用时,例如,您不能通过Web farm同步缓存时。不过,如果您需要从根本上改变应用程序块的行为您可以通过自定义类来替换CacheManager 类来实现。
使用应用程序块开发应用程序
输入缓存配置信息
这些过程解释了如何配置缓存应用程序块。与节点相关的属性显示在右边的面板中。如果要使用数据访问应用程序块做为后端存储,在配置缓存应用程序块之前就必须配置该应用程序块。
添加应用程序块
- 打开配置文件,更多信息,请参见配置应用程序块。
- 右单击 Application Configuration,指向 New ,然后单击 CachingApplicationBlock。
- 配置控制台自动添加带有默认设置的 CacheManager 节点。
配置缓存管理器(Cache Manager)
- 单击 Caching Application Block 节点。
- (可选)修改 DefaultCacheManager 属性名。如果代码没有指定特定的缓存管理器的话,将使用默认的缓存管理器。输入一个新的名称或者从下拉列表中选择一个。默认的名称是 CacheManager 。
- 单击 CacheManager 节点(如果已重命名了缓存管理器,节点将拥有了赋予的名称)。
- (可选)设置 ExpirationPollFrequencyInSeconds 属性。这是定时器控制后台调度程序多久检查过期的条目的频率。单位是秒,最少时间为1秒,默认为60秒。
- 设置 MaximumElementsInCacheBeforeScavenging 属性。这是清除前可以缓存的最大元素数量。默认设置为1000元素。
- ( 可选 )重命名 CacheManager 节点。默认名称是 CacheManager 。
- 设置 NumberToRemoveWhenScavenging 属性。这是在清除开始后移除的元素数量,默认设置为10元素。
默认情况下,缓存存储条目仅在内存中,并赋予后端存储的值为 NullBackingStore 。可以配置缓存应用程序块使用数据库缓存存储、独立存储或者定制的存储。数据库缓存存储使用数据访问应用程序块。
为数据库缓存存储配置缓存应用程序块
- 右单击 CacheManager (或者重命名后的缓存管理器名称),指向 New ,然后单击 DatabaseCacheStorage 。
- 配置控制台自动添加数据访问应用程序块。关于配置数据访问应用程序块的信息,请参见数据访问应用程序块的文档。
- 单击 DataCacheStorage 节点。
- 设置 DatabaseInstance 属性。这是数据库连接字符串的名称,它必须与数据访问应用程序块配置中的某个连接字符串的名称对应。可以输入名称或者从下拉列表中选择它。
- ( 可选 ) 用重命名 DataCacheStorage 节点来设置 Name 属性。
- 设置 PartitionName 属性。这标识了缓存管理器将使用的数据库部分。
为独立存储配置缓存应用程序块
- 右单击 CacheManager (或者重命名后的缓存管理器名称),指向 New ,然后单击 Isolated Storage 。
- 如果要加密保存在独立存储中的信息,右单击Isolated Storage ,指向 New ,并单击 Symmetric Storage Encryption 。配置控制台自动添加加密应用程序块。关于配置加密应用程序块的更多信息,请参见加密应用程序块的文档。
- (可选) 重命名 IsolatedStorage 节点来设置Name 属性。
- 设置 PartitionName 属性。这标识了缓存管理器将使用的独立存储的区域。
为定制缓存存储配置缓存应用程序块
- 右单击 CacheManager (或者重命名后的缓存管理器名称),指向 New ,然后单击 Custom CacheStorage 。
- 在右面板的 Attributes 属性节中,单击省略号按钮(...)。
- 在 EditableKeyValueCollectionEditor 对话框中,单击 Add 添加一个新的名称/值对。
- 在EditableKeyValueCollectionEditor对话框的右面板中,输入键名称和属性的值。
- 适当的添加更多的名称/值对,然后单击 OK 。
- ( 可选) 在放置在配置控制台的右面板中的 Name 属性节中,修改定制缓存存储的名称。默认的名称是 CacheStorage 。
- 在右面板的 Type 属性节中,单击省略号按钮。如果需要的类型没有包含在程序集文件夹中,单击 TypeSelector 上的 LoadAssembly 来查找包含需要的类型的程序集。
如果要添加另一个缓存、管理器的实例,右单击 CacheManagers 节点,指向 New ,然后单击 CacheManager ,重复前面的步骤。在这只能有一个默认的缓存管理器,每个缓存管理器都必须有唯一的名称。
使用说明
缓存应用程序块的配置设置将影响应用程序的缓存使用模式和它的系统环境,如可用的内存数量。例如,如果应用程序添加了一个比在清除时(这是一个配置设置)移除的缓存的比例大得多的条目到缓存中,缓存将持续增长。随着时间的推移,这将导致内存不足。使用应用程序块的性能计数器来协助为每个应用程序调整配置设置。
添加应用程序代码
缓存应用程序块被设计为支持绝大多数存储数据到缓存中的情况。在添加应用程序代码时,涉及在关键场景中的场景,从中选择一个最适合的情况。使用与场景一起的代码或者按需要修改它。
准备应用程序
- 添加到缓存应用程序块的引用 。在 Visual Studio 中,在解决方案管理器中右单击项目,然后单击 添加引用 。单击 浏览 标签查找 Microsoft.Practices.EnterpriseLibrary.Caching.dll 程序集的位置。选择程序集,然后单击 确定 添加引用。
- 使用同样的步骤设置对 Enterprise Library 通用程序集的引用,名称为 Microsoft.Practices.EnterpriseLibrary.Common.dll。
- 用同样的步骤设置对 Enterprise Library 通用程序集的引用,Microsoft.Practices.EnterpriseLibrary.Common.dll ,以及对 ObjectBuiler 程序集的引用,Microsoft.Practices.EnterpriseLibrary.ObjectBuilder2.dll.。
- 如果使用了数据库后端存储,添加对 Microsoft.Practices.EnterpriseLibrary.Caching.Database.dll 和 Microsoft.Practices.EnterpriseLibrary.Data.dll 的引用。
- 如果使用了加密应用程序块加密缓存中的数据,添加对 Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.dll 和 Microsoft.Practices.EnterpriseLibrary.Caching.Cryptography.dll 的引用。
- (可选) 要不带完全限定的元素引用来使用来自缓存应用程序块的元素,添加下列的 using 语句(C#)到源代码的顶部。
using Microsoft.Practices.EnterpriseLibrary.Caching; using Microsoft.Practices.EnterpriseLibrary.Caching.Expirations;
下一步,添加应用程序代码。通常用二步来创建使用缓存应用程序块的代码:
- 创建CacheManager 对象。
- 调用适当的方法。
每个关键场景都示范了如何加入这些步骤到应用程序中。
选择后端存储
每个缓存管理器都可以配置为仅将数据保存在内存中,这意味着它使用的是空后端存储;或者配置为将数据既保存在内存中也保存到持久存储中。持久存储的类型在配置后端存储时指定。后端存储使缓存的数据在应用程序必须重启时得以幸免。在它的初始状态下,缓存应用程序块支持二种持久后端存储,每一种都适用于特定的情况:
- 独立存储
- 数据库缓存存储
开发人员可以扩展缓存应用程序块以支持其他的后端存储类型,有关此主题的更多信息,请参见添加一个新的后端存储。
使用NULL后端存储
空后端存储是配置缓存应用块的默认选择。它不持久化缓存的条目,这意味着缓存的数据仅保存在内存中,而不存在于持久存储中。空后端存储适用于在应用程序重启时要从原始数据源刷新缓存的条目的情况。它可以用于所有支持的应用程序类型,这些类型的列表,请参见缓存应用程序块介绍。
使用独立存储的后端存储
独立存储适用于下列情况:
- 需要持久存储且用户量少
- 使用数据库的开销非常大
- 没有数据库
关于何时使用独立存储的更多信息,请参见 MSDN 上的 Scenarios for Isolated Storage 在配置使用独立存储时,后端存储由缓存实例名称、用户名、程序集和应用程序域来隔离。
独立存储适用于智能客户端和每个应用程序域有自己的缓存的服务器程序。同时也要注意,因为独立存储总是用用户来隔离,所以服务器应用程序必须模拟请求应用程序的用户。
使用数据访问应用程序块后端存储
使用数据访问应用程序块后端存储允许存储缓存的数据到一个数据库中。现在,缓存应用程序块包含一个创建需要的 SQL Server 数据库模式的脚本,并且应用程序块已经测试了对应的 SQL Server 数据库。开发人员可以使用其他类型的数据库做为后端存储,但必须修改应用程序块的源代码。每种数据库类型必须有一个用于数据访问应用程序块的数据库提供程序并包含兼容的模式。
数据访问应用程序块后端存储选项适用于智能客户端和每个应用程序域有自己的缓存的服务器应用程序,以及要访问数据库的情况。
运行在单一应用程序域中的每个 CacheManager 必须使用不同的数据库分区,一个分区定义为应用程序名称和缓存实例名称的组合。数据库可以与使用缓存的应用程序运行在同一服务器上或不同服务器上。数据库支持的使用缓存的应用程序数量仅依赖于数据库的存储限制。
服务器场景的考虑
单一的缓存管理器不能跨应用程序域共享。部署在多台计算机上的服务器应用程序在每台计算机上都有唯一的内存缓存副本,运行在同一计算机上的多个进程也是这样的,包括运行在自己的进程中并使用了缓存应用程序块的企业服务组件。每个进程有自己的内存缓存副本。
不同应用程序不能使用一样的数据访问应用程序块后端存储实例和分区。用缓存应用程序块配置使用同样的数据库实例和分区来运行不同的应用程序将导致不可预知的结果,并且不推荐这样做。
当同样的应用程序运行在多个进程中时(例如,如果应用程序部署在 Web farm 中的多台计算机中),可以使用下列三种方法之一来配置缓存应用程序块:
- 所有的应用程序实例使用同样的数据库实例,但每个应用程序实例使用不同的数据库分区。更多信息,请参见后面的场景一。
- 所有应用程序实例使用同样的数据库实例、同样的数据库分区,并且所有的缓存管理器都可以读和写缓存。更多信息,请参见后面的场景二。
- 所有应用程序实例使用同样的数据库实例、同样的数据库分区,但仅有一个缓存管理器可以写缓存。所有缓存管理器可以从缓存中读。更多信息,请参见后面的场景三。
场景一:分区的缓存
场景一是所有应用程序实例使用同样的数据库实例,但每个应用程序实例使用不同的数据库分区的情形。在这个场景中,每个缓存管理器的操作都是独立的。尽管它们共享了同样的后端存储数据库实例,每个缓存管理器持久缓存数据到不同的分区。此时每个应用程序实例仅有一个有效的缓存。当应用程序重启时,每个缓存管理器从后端存储中的自己的分区中加载它的数据。
如果应用程序预加载缓存,每个部署的应用程序实例都从原始数据源中获取数据。预加载数据使用每个部署的应用程序实例的后端存储储存空间。这意味着在使用缓存的条件下,部署同样的应用程序到多个进程并不比部署不同的应用程序更有效率。
部署同样的应用程序到多台服务器,服务器的每个配置应用程序块都配置为相同的(例如,所有应用程序块使用同样的过期策略),不保证在每个后端存储分区中的数据是相同的。在后端存储分区中的数据复制了配置为使用后端存储分区的缓存管理器的内存缓存数据。内存缓存中的内容随着使用缓存应用程序特定实例而变化,因为应用程序要求路由到不同的服务器,所以每台服务器中内存缓存可能是不同的,因此后端存储分区中的内容也可能是不同的。这意味着,即使所有应用程序同时关闭再重启,也不能保证在每个缓存用后端存储中的数据初始化后其内存缓存中的数据是一样的。
场景二:共享分区
场景二是所有应用程序的实例使用同样的数据库实例和同样的数据库分区,而且所有的缓存管理器都读写缓存。在此场景中,每个应用程序实例操作相互唯一的内存缓存。当应用程序创建一个缓存管理器时,缓存管理器将后端存储中的数据放入内存缓存中,这意味着,如果应用程序在它启动时创建一个缓存管理器,并且如果所有应用程序实例都同时启动的话,每个内存缓存将加载同样的数据。因为应用程序使用了相同的分区,每个应用程序实例不需要在后端存储中的附加存储。
缓存管理器创建的时间是从后端存储加载数据到内存缓存的唯一时间。在此之后,内存缓存中的内容将由使用缓存的应用程序实例所决定。应用程序实例使用缓存的方法可以互不相同,因为需要路由到不同的服务器。运行的不同应用程序实例可以有不同内容的内存缓存。
随着应用程序添加和删除条目,内存缓存的内容会改变,内存缓存的内容在缓存管理器移除或清除过期条目时也会改变。随着内存缓存的改变,缓存管理更新后端存储以反映这些改变。后端存储在它的内存发生改变时不会通知缓存管理器。因此,当一个应用程序实例改变后端存储的内容时,其他应用程序将有与后端存储数据不匹配的内存缓存。这意味着,在应用程序重启以后,内存缓存可以有与在应用程序重启前不一样的内容。
当条目过期时,应用程序可以由缓存管理器提供的提交事件来通知,应用程序可以使用这个通知来从源数据源中刷新缓存的数据。当应用程序添加刷新的缓存条目到缓存中时,缓存管理器也用这些数据更新后端存储。如果应用程序部署在多台计算机上,每个应用程序实例都会收到事件,然后为同样的条目初始化对原始数据源的请求。这多个请求可以对应用程序和原始数据源的性能形成重大的消极影响。因此,使用通知来为刷新过期缓存条目的目的而监视过期在此场景中是不推荐的。
场景三:单一写
场景三是所有应用程序使用同样的数据库实例、同样的数据库分区,而仅有一个缓存管理器可以写缓存,所有的缓存管理器可以从缓存中读。在此场景中,只有一个应用程序实例写缓存,所有其他实用程序实例只能从缓存中读取。可以写缓存的应用程序实例是主机 ,主机的内存缓存与后端存储有着同样的数据。在每个应用程序实例中的内存缓存在缓存管理器创建时用来自后端存储中的数据填充。只能从缓存中读取的应用程序实例获取一个数据快照,因为应用程序实例没有刷新它们的缓存的能力,它们的缓存将在条目过期时失效并缩水。
本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号