现在的位置: 首页 > 综合 > 正文

asp.net cache Management

2012年10月09日 ⁄ 综合 ⁄ 共 17040字 ⁄ 字号 评论关闭
Although cache management is not an issue in Windows applications, it has always been a challenge in the web environment.
Since HTTP is a stateless protocol and a web server doesn't recognize users between different requests, it becomes very important for us to recognize a particular user between different requests and also store data so that it can be re-used between different requests.
ASP.NET provides many features for storing data both in the client (browser) and the server (web server) sides, but sometimes we get confused with when to use what.
In ASP.NET we come across features like Session, Application and Cache objects, but it is important for us to understand the difference between them in order to effectively use them in web applications.
Background
In this article, I will touch upon the different cache management options available in ASP.NET.
In a web application, sometimes we require to store data in the server side to avoid costly data retrieval operation from data stores and time consuming data formatting logic to improve application performance as well as to re-use the same data in subsequent requests across users,applications and machines.
So, to achieve this we need to store (cache) data in the server side.

Caching helps us to achieve three important aspects of QoS (Quality Of Service):

  • Performance - Caching improves application performance by minimizing data retrieval and formatting operations.
  • Scalability - Since caching minimizes data retrieval and formatting operations, it reduces the load on server resources thus increasing the scalability of the application.
  • Availability - Since the application uses data from a cache, the application will survive failures in other systems and databases.

    In a web application, we can cache data, pages etc. both in server and client sides. Let us have a look at the different options available in ASP.NET for caching data both in server and client sides.
    ASP.NET session state is used to cache data per user session. It means that the data cannot be shared across multiple users and the data usage is limited to the user session it is created in. ASP.NET Session object is used for this purpose.
    ASP.NET session state can be managed in three different ways:

  • InProc - Stored in the aspnet_wp.exe process area. The session data is lost when the process or the application domain is recycled.
  • StateServer - Session state is stored in a separate process (aspnet_state.exe) which can be stored in a different machine. Since it can be stored in a different machine, this option will work in a web farm scenario(Multi machine).
  • SQLServer - Session state is stored in a SQL Server database. This option will also work in a web farm scenario.(Multi Machine???????) 

    ****************************************************************************************
    Both in StateServer and SQLServer options, we need to ensure that the objects we cache are serializable as(because) data storages are out-of-process systems.
    Both these options have impact on the application performance as data retrieval and saving operations take more time when compared to the InProc option.
    So based on our application requirement we should choose the option that best suits our requirement.
    The following example shows how the Session object can be used in the code:

    string empNum = Request.QueryString["empnum"];
    if (empNum != null)
    {
        
    string details = null;

        
    if (Session["EMP_DETAILS"== null)
        
    {
            
    //Get Employee Details for employee number passed
            string details = GetEmployeeDetails(Convert.ToInt32(empNum));

            Session[
    "EMP_DETAILS"= details;
        }

        
    else
        
    {
            details 
    = Session["EMP_DETAILS"];
        }


        
    //send it to the browser
        Response.Write(details);
    }

    ASP.NET application object

    ASP.NET provides an object called Application object to store data that is accessible to all user requests. The life span of this object is tied to the application and it is re-created every time the application starts.
    Unlike ASP.NET Session object this object is accessible to all user requests.
    Since this storage is created and maintained in an application domain space, this should not be used for data storage in a web farm scenario.
    This option is very useful to store data like the application metadata (CONFIG files data) that can be loaded to the Application object during application start up and can be used during the life of the application without reloading it every time for each user request.
    But if there is a requirement to invalidate the cached data whenever there is any change to the CONFIG files while the application is running,(请求的数据更改后,要得到更改后的数据,而此时application 正在运行) this option should not be used as it doesn't provide any feature to expire the cached data.
    So in this case other options like the ASP.NET Cache object should be used, which is explained below.

    ASP.NET cache object

    ASP.NET cache object is my favorite caching mechanism.That's why I love to talk more about it.
    ASP.NET provides a key-value pair object - the Cache object which is available in the System.Web.Caching namespace.
    The scope of it is the application domain and the life span is tied to the application.
    Unlike the ASP.NET Session object, this object is accessible to all user requests. Although both Application and Cache objects look the same, the key difference between them is the added features provided by the Cache object like the expiration policies and dependencies。

    It means that the data stored in the cache object can be expired/removed based on some predefined time limit set by the application code or when the dependent entity gets changed whereas(相反,尽管) this feature is not available in the Application object.

    Let us discuss the different expiration policies and the dependencies that are supported.

    Dependency

    Dependency means that an item can be removed((常与from连用)拿走;撤走,除去) from the cache when a dependent entity gets changed.
    So a dependent relationship can be defined on an item (whose removal from the cache) will depend on the dependent. There are two types of dependencies supported in ASP.NET
    File dependency -
    This provides an option to remove an item automatically from the cache whenever a disk file changes.
    Let's say in my application I am using an XML file to store error details (error number and error message mapping) which is used to retrieve an error message for a given error number at runtime.
    So instead of reading the file from the disk each time I need an error message,
    let's say I decide to load it once at application startup and store it in the ASP.NET cache for further use.
    So, if I need to change the CONFIG file to add new error messages or change some of the existing error messages while the application is running, then what will happen to my cached data?
    Do I need to stop the application and start it again to reflect the file changes in the application?
    The answer is no.
    The cache data can be invalidated(使无效) whenever the file changes by using the File dependency option.
    The following example shows how File dependency can be used to invalidate the cache item.
    So whenever the errors.xml file changes the cache item will automatically get expired and will be removed from the cache.

     

    object errorData;
     
    //Load errorData from errors.xml 
     CacheDependency fileDependency = 
         
    new CacheDependency(Server.MapPath("errors.xml")); 
     Cache.Insert(
    "ERROR_INFO", errorData, fileDependency);

    Key dependency - Key dependency is similar to file dependency but the only difference is that instead of a file the item is dependent on another item in the cache and gets invalidated when the dependent item gets changed or removed.
    This option is useful when multiple related items are added to the cache and those items are to be removed if the primary item is changed.
    For e.g. employee number, name, address and salary are added to the cache and if the employee number is updated/removed ,(so) all the related employee information are removed.
    In this case the employee number dependency can be used for other employee information.

    The following example shows how Key dependency can be used to invalidate the cache items.

    string[] relatedKeys = new string[1]; 
    relatedKeys[
    0= "EMP_NUM";
    CacheDependency keyDependency 
    = new CacheDependency(null, relatedKeys); 
    Cache[
    "EMP_NUM"= 5435;
    Cache.Insert(
    "EMP_NAME""Shubhabrata", keyDependency);
    Cache.Insert(
    "EMP_ADDR""Bhubaneswar", keyDependency);
    Cache.Insert(
    "EMP_SAL""5555USD", keyDependency);

    Expiration policy

    Expiration policy sets the policy for how and when an item in the cache should expire.
    Time based expiration - Time based expiration provides an option to expire an item in the cache at a predefined time. The expiration time can be set as absolute time like 31st October 2005 12:00 or sliding time i.e. relative to the current time when the item is accessed.

    //Absolute Expiration
    Cache.Insert("EMP_NAME""Shubhabrata"null
                 DateTime.Now.AddDays(
    1), Cache.NoSlidingExpiration);

    //Sliding Expiration
    Cache.Insert("EMP_NAME""Shubhabrata"null
                 Cache.NoAbsoluteExpiration, TimeSpan.FromSeconds(
    60));

    How to know when an item is removed?
    In the above examples we learned how to remove an item from the cache but sometimes we want to know when an item is removed from the cache.
    Yes, it is possible by using cache callbacks.
    In the error details example shown above, the cached item expires whenever the errors.xml file changes.
    Suppose we want to update the cache with the latest error details.
    To find out when the error details are removed from the cache we can use cache callback for further processing (reloading the error details again to the cache).

    The following example shows how to use cache callback to handle the item expiration scenario:

    private void AddItemsToCache()
    {    
        
    int empNum = 5435;
        CacheItemRemovedCallback onEmpDetailsRemove 
    = 
                        
    new CacheItemRemovedCallback(EmpDetailsRemoved);
        Cache.Insert(
    "EMP_NUM", empNum, null
                                  Cache.NoAbsoluteExpiration, 
                                  Cache.NoSlidingExpiration, 
                                  CacheItemPriority.Default, 
                                  onEmpDetailsRemove);
    }


    private void EmpDetailsRemoved(string key, object val, 
                                  CacheItemRemovedReason reason)
    {
        
    //When the item is expired
        if (reason == CacheItemRemovedReason.Expired)
        
    {
            
    //Again add it to the Cache
            AddItemsToCache();
        }

    }

    In the above example you must have noticed the parameter CacheItemPriority used along with the callback method.
    CacheItemPriority is used to set the priority of the item that we are adding to the cache.
    The priority needs to be set to tell the cache that in case of low memory in the server remove the (which) cached items to free memory based on the priority set.
    This process is known as scavenging.(净化, 清除)
    .NET remoting
    You might be thinking how .NET remoting can be used for data caching? The same question came to my mind when I heard about it for the first time.
    As you know the .NET remoting singleton object shares the same instance with multiple clients so singleton objects can be used to store and share data between different client invocations.
    (发动,调动) 
    Since .NET remoting can be used outside the process and machine, this option is very useful when we want to cache data and share it across servers and users particularly in a web farm scenario.
    In this approach(途径;通路) we can store the data as member variables of singleton remoting object and provide methods to read and save data.
    But while implementing this we need to ensure that the remoting object (used as cache) is not destroyed by the garbage collector.
    For that we will have to set the remoting cache object's lease period (租约)to infinite(无限大) so that the lease period never times out.
    We can do that by overriding the InitializeLifetimeService method of MarshalByRefObject and return null from this method.
    But the only issue (问题; 争端;) with this approach is performance.

    As the analysis(分解, 分析) says the performance is very poor in this approach when compared to other approaches.
    Anyway it is up to (胜任, 从事于) the application designers/developers to analyze(分析,分解) different options and use the best one that suits the requirement.

    Memory-mapped files

    You all know what a memory-mapped file is.
    It is basically about mapping a file on disk to a specific range of addresses in the application's process address space.
    This option allows different processes to use the same data by increasing the application performance.
    As using memory-mapped file is not very popular among .NET developers, I would personally not suggest this approach as implementing this involves a lot of complexities and also .NET Framework doesn't support this.
    But if anyone is very much interested in using this approach then they will have to develop their own custom solution as per(根据,按照) their own requirement.

     

    Static variables

    We use static variables for storing data or objects globally so that it can be accessed during the life of the application.
    Similarly, in ASP.NET we can use static objects for caching data and we can also provide methods to retrieve and save data to the cache.

    As static variables are stored in the process area, performance wise it is faster. 

    ****************************************
    But since it is very difficult to implement expiration policies and dependencies incase of ( use ) static variables,
    I generally prefer ASP.NET cache object over this option.
    Another problem is that the custom static cache object has to be thread-safe which has to be implemented carefully.
    Custom static cache object can be defined as shown below

    public class CustomCache
    {
        
    //Synchronized to implement thread-safe
        static Hashtable _myCache = 
                 Hashtable.Synchronized(
    new Hashtable());
        
        
    public static object GetData(object key)
        
    {
            
    return _myCache[key];
        }

        
        
    public static void SetData(object key, object val)
        
    {
            _myCache[key] 
    = val;
        }

    }

    Database

    We can also use a database for storing data and sharing the data across users and machines. This approach is very useful when we want to cache large amounts of data.

    *********************
    Using this approach for storing small amount of data is not a good idea because of performance
    .
    For storing small amount of data we should go for other ASP.NET in-process caching mechanisms.
    As the data needs to be stored in a database all the objects need to be XML serialized so that it is easier to store and retrieve.
    We can also use other types of serialization formats available in the .NET Framework.
    ASP.NET page output caching
    Sometimes in our application in some pages the output generally doesn't change for a specific period of time.
    For example in a HR website, the salary details of an employee doesn't change very frequently and it changes only once in a month.
    Generally it changes only on the 1st day of every month.
    So during a month the salary details page will show the same details for a particular employee.
    So in this case isn't it a good idea to cache the page somewhere in the server to avoid business calculation processing, calls to database and page rendering logic every time the employee wants to see his salary details.
    In my opinion, Yes! It is a very good idea. To achieve this, ASP.NET provides a feature to store the output of a page in the server for a specific period of time.
    It also provides features to store a fragment of a page which is known as Page fragment caching. Here I am not going to talk much about Page Output Caching as there are other articles available in the Internet that cover this mechanism in detail.
    This would a very lengthy section if I start discussing it. I am planning to cover this in another article.

     

    <!-- VaryByParm - different versions of same page will be 
    cached based on the parameter sent through HTTP Get/Post
    Location - where the page is cached 
    -->
    <%@OutputCache Duration="60" VaryByParam="empNum" Location="Server"%>

    Let us do a comparison between the different options that we have discussed so far

    Option Works in Web Farm scenario? Remarks

    ASP.NET Session State
    - InProc
    - StateSerer
    - SQLServer

    No
    Yes
    Yes

    Unlike other option, it stores only user session specific data
    ASP.NET Application Object No  
    ASP.NET Cache Object No  
    .NET Remoting Yes  
    Memory-Mapped files No  
    Static Variables No  
    Database Yes  
    ASP.NET Page Output Caching No

    *****************************************************************************
    Client side cache management
    In the previous sections we discussed about the different caching options available in the server side but sometimes we may need to cache data or pages in the client side to improve application performance.
    Using this mechanism reduces the load on server but this mechanism has some security issues as we cache the data in client side.
    There are different options available for client-side caching.
    I am going to talk briefly about a few of them.
    Cookies
    Cookie is a very familiar term in web development environment. Cookie is a client-side storage that is sent to the server for each request and also received as response back from the server.
    Because of its size limitation (4096 bytes) it should be used for storing small amount of data.
    Expiration policies can be set for cookies to invalidate the items after a certain period of time. The following example shows how Cookie can be used in an ASP.NET application:

    if (this.Request.Cookies["MY_NAME"== null

        
    this.Response.Cookies.Add(new HttpCookie("MY_NAME"
                                           
    "Shubhabrata Mohanty")); 
    }
     
    else 

        
    this.Response.Write(this.Request.Cookies["MY_NAME"].Value); 
    }

    ViewState
    ASP.NET ViewState is a new concept. Here the data related to the pages and controls are stored in ViewState which retains the values across multiple requests to the server.
    If you remember correctly, in VB-ASP applications we used to store data across multiple requests using hidden fields.
    ViewState is actually implemented internally as hidden fields in ASP.NET but here the data is hashed to improve security as against hidden fields.
    To see how ViewState is implemented, you can view the source of the page in which ViewState is used in the Internet browser. ViewState should not be used to store large amounts of data as it is passed to the server for each request

    protected void Page_Load(object sender, EventArgs e) 
    {
        
    if (this.ViewState["MY_NAME"== null
        

            
    this.ViewState["MY_NAME"= "Shubhabrata Mohanty";
        }
     
        
        
    //txtName is a TextBox control 
        this.txtName.Text = this.ViewState["MY_NAME"].ToString(); 
    }

    Hidden fields
    Hidden fields are very popular among VB-ASP web developers. Hidden field is similar to any other control in a page but the visible state of this control is always false. Like ViewState we should not use it for storing large amounts of data.
    NOTE:
    Similarly hidden frames can be used to cache data in the client side. But please note that hidden frames are not supported by all Internet browsers

    <!--In ASP.NET-->
    <asp:HiddenField ID="myHiddenField" Value="Shubhabrata" 
                                                 runat
    ="server" />
    <!--In HTML-->
    <input id="myHiddenField" type="hidden" value="Shubhabrata" />

    Microsoft Internet Explorer caching

    Since I am talking about ASP.NET then why not discuss about another caching capability from Microsoft? Microsoft Internet Explorer provides caching mechanism to cache pages in the client side.
    This can be set using the EXPIRES directive added to the header of the pages or by setting it manually in IIS. In IIS go to the HTTP header tab of the properties window of the page and then select the Enable Content Expiration checkbox.
    We should use this option for caching static pages and images in the client side.

  • 抱歉!评论已关闭.