CommunityServer缓存技术

 
CS 中缓存对性能的优化起了非常大的作用,今天做一次深入的研究。经过大致的代码浏览发现CS中的缓存分为2种:一种采用System.Web.Caching,另一种采用HttpContext.Items(由于CS大量的采用服务器端控件没有使用页面级的缓存)。
首先研究一下System.web.Caching.Cache的使用
在 CommunityServerComponents项目中发现了CommunityServer.Components.CSCache,查看一下代码
        private CSCache(){}
 
        //>> Based on Factor = 5 default value
        public static readonly int DayFactor = 17280;
        public static readonly int HourFactor = 720;
        public static readonly int MinuteFactor = 12;
 
        private static readonly Cache _cache;
 
        private static int Factor = 5;
 
        public static void ReSetFactor( int cacheFactor)
        {
            Factor = cacheFactor;
        }
 
        ///
        /// Static initializer should ensure we only have to look up the current cache
        /// instance once.
        ///
        static CSCache()
        {
            HttpContext context = HttpContext.Current;
            if (context != null )
            {
                _cache = context.Cache;
            }
            else
            {
                _cache = HttpRuntime.Cache;
            }
        }
发现其实是对 System.Web.Caching.Cache作了一个封装(在CS中这样的例子比比皆是如:CSContext),主要实现了一下功能:
1 、插入:Insert、MicroInsert(插入生存周期短的缓存项目)、Max(插入生存周期很长的缓存项目,在系统运行期间永久缓存)
2、获取:Get
3、移除:Remove、RemoveByPattern
4、全部清除:Clear
另外大家看一下“
private static int Factor = 5;” ,如果希望不用缓存则直接设置为Factor=0即可,如果希望延长缓存生存周期则适当调大Factor值,也可以在CommunityServer.config中修改“cacheFactor”的数值。
在解决方案中搜索一下“CSCache”,会发现有63个文件,分析一下缓存内容主要有2种类型:配置文件及从数据库读取的实体。
一个是配置文件信息(例如:CommunityServer.Configuration.CSConfiguration、CommunityServer.Galleries.Components.GalleryConfiguration、CommunityServer.Blogs.Components.WeblogConfiguration等)
例如CommunityServer.Configuration.CSConfiguration
        public static CSConfiguration GetConfig()
        {
            CSConfiguration config = CSCache.Get(CacheKey) as CSConfiguration;
            if (config == null )
            {
                string path;
                if (HttpContext.Current != null )
                    path = HttpContext.Current.Server.MapPath("~/communityserver.config");
                else
                    path = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + "communityserver.config";
 
                XmlDocument doc = new XmlDocument();
                doc.Load(path);
                config = new CSConfiguration(doc);
                CSCache.Max(CacheKey,config,new CacheDependency(path));
 
                CSCache.ReSetFactor(config.CacheFactor);
            }
            return config;
           
        }
        public static CSConfiguration GetConfig()
        {
            CSConfiguration config = CSCache.Get(CacheKey) as CSConfiguration;
            if (config == null )
            {
                string path;
                if (HttpContext.Current != null )
                    path = HttpContext.Current.Server.MapPath("~/communityserver.config");
                 else
                    path = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + "communityserver.config";
 
                XmlDocument doc = new XmlDocument();
                doc.Load(path);
                config = new CSConfiguration(doc);
                CSCache.Max(CacheKey,config,new CacheDependency(path));
 
                CSCache.ReSetFactor(config.CacheFactor);
            }
            return config;
           
        }
可以看到对communityserver.config的配置信息在第一次使用时从配置文件中读取出来并加入采用CSCache.Max()永久缓存,其失效策略为communityserver.config文件的更改。回顾一下,System.Web.Caching.Cache的失效策略一般有三种情况:文件的更改、缓存中其他缓存内容的更改、定义失效时间。GalleryConfiguration及WeblogConfiguration内的缓存失效策略是第2种情况的一个示例
        public static WeblogConfiguration Instance()
        {
            string cacheKey = "WeblogConfiguration";
            WeblogConfiguration config = CSCache.Get(cacheKey) as WeblogConfiguration;
 
            if (config == null )
            {
                XmlNode node = CSConfiguration.GetConfig().GetConfigSection("CommunityServer/Weblog");
                config = new WeblogConfiguration();
                ...
                CacheDependency dep = new CacheDependency(null, newstring[]);
                CSCache.Insert(cacheKey, config, dep);
            }
 
            return config;
        }
另一种是数据库实体的缓存,以CommunityServer.Discussions.Components.Posts为例
        public static PostSet GetPosts( int postID, int pageIndex, int pageSize, int sortBy, int sortOrder)
        {
           PostSet postSet;
            CSContext csContext = CSContext.Current;
            string key = "Forum-Posts::P:-PI:-PS:-SB:-SO:";
            string postCollectionKey = string.Format(key,postID,pageIndex,pageSize, sortBy, sortOrder);
 
             // Attempt to retrieve from Cache
            postSet = CSCache.Get(postCollectionKey) as PostSet; //   forumContext.Context.Cache[postCollectionKey];
 
            if (postSet == null ) {
                // Create Instance of the CommonDataProvider
                ForumDataProvider dp = ForumDataProvider.Instance();
 
                postSet = dp.GetPosts(postID, pageIndex, pageSize, sortBy, sortOrder, CSContext.Current.User.UserID, true );
 
                CSCache.Insert(postCollectionKey,postSet,6);
            }
 
            return postSet;
        }
GetPosts() 首先从缓存中读取postSet = CSCache.Get(postCollectionKey) as PostSet;
如果缓存中不存在则从数据库中读取并放入缓存(缓存失效策略为定义的时间段),这是CS减少数据库连接次数最有效的方式。另外其缓存key值的设置规则也是非常值得学习的。
  然后研究一下HttpContext.Items的使用
        public static WeblogConfiguration Instance()
        {
            string cacheKey = "WeblogConfiguration";
            WeblogConfiguration config = CSCache.Get(cacheKey) as WeblogConfiguration;
 
            if (config == null )
            {
                XmlNode node = CSConfiguration.GetConfig().GetConfigSection("CommunityServer/Weblog");
                config = new WeblogConfiguration();
                ...
                CacheDependency dep = new CacheDependency(null, newstring[]);
                CSCache.Insert(cacheKey, config, dep);
            }
 
            return config;
        }
另一种是数据库实体的缓存,以 CommunityServer.Discussions.Components.Posts为例
        public static PostSet GetPosts( int postID, int pageIndex, int pageSize, int sortBy, int sortOrder)
        {
            PostSet postSet;
            CSContext csContext = CSContext.Current;
            string key = "Forum-Posts::P:-PI:-PS:-SB:-SO:";
            string postCollectionKey = string.Format(key,postID,pageIndex,pageSize, sortBy, sortOrder);
 
            // Attempt to retrieve from Cache
            postSet = CSCache.Get(postCollectionKey) as PostSet; //   forumContext.Context.Cache[postCollectionKey];
 
            if (postSet == null ) {
                // Create Instance of the CommonDataProvider
                ForumDataProvider dp = ForumDataProvider.Instance();
 
                postSet = dp.GetPosts(postID, pageIndex, pageSize, sortBy, sortOrder, CSContext.Current.User.UserID, true );
 
                CSCache.Insert(postCollectionKey,postSet,6);
            }
 
            return postSet;
        }
GetPosts()首先从缓存中读取 postSet = CSCache.Get(postCollectionKey) as PostSet;
如果缓存中不存在则从数据库中读取并放入缓存(缓存失效策略为定义的时间段),这是CS减少数据库连接次数最有效的方式。另外其缓存key值的设置规则也是非常值得学习的。
  然后研究一下HttpContext.Items的使用
  然后研究一下HttpContext.Items的使用
        private static Hashtable GetForums(CSContext csContext, bool ignorePermissions, bool cacheable, bool flush) {
            Hashtable unfilteredForums    = null ;
            Hashtable forums;
 
            int settingsID = CSContext.Current.SiteSettings.SettingsID;
            string cacheKey = string .Format("Forums-Site:",settingsID);
            string localKey = string .Format("ForumsForUser:",ignorePermissions);
 
            if (flush)
            {
                CSCache.Remove(cacheKey);
                csContext.Items[localKey] = null ;
            }
 
            #if DEBUG_NOCACHE
                cacheable = false ;
            #endif
 
            // Have we already fetched for this request?
            //
           
            //If something is in the context with the current cache key, we have already processed and validated this request!
            unfilteredForums = csContext.Items[localKey] as Hashtable;
 
            //We do not need to revalidate this collection on the same request
            if ((unfilteredForums != null ))
                return unfilteredForums;
            else if (!cacheable)
                csContext.Items.Remove(cacheKey);
           
            //Is it safe to use the cached version?
             if ((!cacheable))
                CSCache.Remove(cacheKey);
 
            //If we find the forums in the cache, we need to revalidate them. DO NOT return the coolection unless
            //the call specifies ignorepermissions
            unfilteredForums = CSCache.Get(cacheKey) as Hashtable;
 
            // Get the raw forum groups
            //
            if ( unfilteredForums == null ) {
                unfilteredForums = ForumDataProvider.Instance().GetForums();
 
                // Dynamically add the special forum for private messages
                //
                unfilteredForums.Add( 0, PrivateForum() );
 
                // Cache if we can
                //
                if (cacheable)
                    CSCache.Insert(cacheKey,unfilteredForums,CSCache.MinuteFactor * 15,CacheItemPriority.High);
 
            }
 
            // Are we ignoring permissions?
            //
            if (ignorePermissions)
            {
                //Save us the logic look up later
                csContext[localKey] = unfilteredForums;
                return unfilteredForums;
            }
 
            // We need to create a new hashtable
            //
            forums = new Hashtable();
            User user = CSContext.Current.User;
 
            // Filter the list of forums to only show forums this user
            // is allowed to see
            //
            foreach (Forum f in unfilteredForums.Values) {
 
                // The forum is added if the user can View, Read
                //
                
                if ( Permissions.ValidatePermissions(f,Permission.View,user) )
                    if (f.IsActive || user.IsForumAdministrator)
                        forums.Add(f.SectionID, f);
               
            }
 
            // Insert into request cache
            //
            csContext[localKey] = forums;
 
            return forums;
 
        }
第一次访问时首先从数据库中读取数据并存储到Cache及HttpContext.Items中,但是请求结束后HttpContext.Items的缓存即可消失,到底能起什么作用呢?搜索GetForums()发现有多个服务器端控件使用这个方法,如果有多个其中的控件出现在一个页面即一个请求中时,则缓存就发生作用了
        private static Hashtable GetForums(CSContext csContext, bool ignorePermissions, bool cacheable, bool flush) {
            Hashtable unfilteredForums    = null ;
            Hashtable forums;
 
            int settingsID = CSContext.Current.SiteSettings.SettingsID;
            string cacheKey = string .Format("Forums-Site:",settingsID);
            string localKey = string .Format("ForumsForUser:",ignorePermissions);
 
            if (flush)
            {
                CSCache.Remove(cacheKey);
                csContext.Items[localKey] = null ;
            }
 
            #if DEBUG_NOCACHE
                cacheable = false ;
            #endif
 
            // Have we already fetched for this request?
            //
           
            //If something is in the context with the current cache key, we have already processed and validated this request!
            unfilteredForums = csContext.Items[localKey] as Hashtable;
 
            //We do not need to revalidate this collection on the same request
            if ((unfilteredForums != null ))
                return unfilteredForums;
            else if (!cacheable)
                csContext.Items.Remove(cacheKey);
           
            //Is it safe to use the cached version?
            if ((!cacheable))
                CSCache.Remove(cacheKey);
 
            //If we find the forums in the cache, we need to revalidate them. DO NOT return the coolection unless
            //the call specifies ignorepermissions
            unfilteredForums = CSCache.Get(cacheKey) as Hashtable;
 
            // Get the raw forum groups
            //
            if ( unfilteredForums == null ) {
                unfilteredForums = ForumDataProvider.Instance().GetForums();
 
                // Dynamically add the special forum for private messages
                //
                unfilteredForums.Add( 0, PrivateForum() );
 
                 // Cache if we can
                //
                if (cacheable)
                    CSCache.Insert(cacheKey,unfilteredForums,CSCache.MinuteFactor * 15,CacheItemPriority.High);
 
            }
 
            // Are we ignoring permissions?
            //
            if (ignorePermissions)
            {
                //Save us the logic look up later
                csContext[localKey] = unfilteredForums;
                return unfilteredForums;
            }
 
            // We need to create a new hashtable
            //
            forums = new Hashtable();
            User user = CSContext.Current.User;
 
            // Filter the list of forums to only show forums this user
            // is allowed to see
            //
            foreach (Forum f in unfilteredForums.Values) {
 
                // The forum is added if the user can View, Read
                //
               
                if ( Permissions.ValidatePermissions(f,Permission.View,user) )
                    if (f.IsActive || user.IsForumAdministrator)
                        forums.Add(f.SectionID, f);
               
            }
 
            // Insert into request cache
            //
            csContext[localKey] = forums;
 
            return forums;
 
        }
第一次访问时首先从数据库中读取数据并存储到Cache及HttpContext.Items中,但是请求结束后HttpContext.Items的缓存即可消失,到底能起什么作用呢?搜索GetForums()发现有多个服务器端控件使用这个方法,如果有多个其中的控件出现在一个页面即一个请求中时,则缓存就发生作用了
 
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值