使用輸出快取改善效能 (C#)

Microsoft提供

在本教學課程中,您將瞭解如何利用輸出快取,大幅改善 ASP.NET MVC Web 應用程式的效能。 您將瞭解如何快取控制器動作傳回的結果,如此一來,每次新的使用者叫用動作時,都不需要建立相同的內容。

本教學課程的目標是要說明如何利用輸出快取,大幅改善 ASP.NET MVC 應用程式的效能。 輸出快取可讓您快取控制器動作所傳回的內容。 如此一來,每次叫用相同的控制器動作時,都不需要產生相同的內容。

例如,假設您的 ASP.NET MVC 應用程式會在名為 Index 的檢視中顯示資料庫記錄清單。 一般而言,每次使用者叫用傳回索引檢視的控制器動作時,都必須藉由執行資料庫查詢從資料庫擷取資料庫記錄集。

另一方面,如果您利用輸出快取,則可以避免每次使用者叫用相同的控制器動作時執行資料庫查詢。 檢視可以從快取擷取,而不是從控制器動作重新產生。 快取可讓您避免在伺服器上執行備援工作。

啟用輸出快取

您可以將 [OutputCache] 屬性新增至個別控制器動作或整個控制器類別,以啟用輸出快取。 例如,清單 1 中的控制器會公開名為 Index () 的動作。 Index () 動作的輸出會快取 10 秒。

清單 1 – Controllers\HomeController.cs

using System.Web.Mvc;

namespace MvcApplication1.Controllers
{
    [HandleError]
    public class HomeController : Controller
    {
        [OutputCache(Duration=10, VaryByParam="none")]
        public ActionResult Index()
        {
            return View();
        }
    }
}

在 ASP.NET MVC 的 Beta 版本中,輸出快取不適用於類似 的 http://www.MySite.com/ URL。 您必須改為輸入類似 的 http://www.MySite.com/Home/Index URL。

在清單 1 中,Index () 動作的輸出會快取 10 秒。 如果您想要的話,您可以指定較長的快取持續時間。 例如,如果您想要快取控制器動作的輸出一天,您可以指定快取持續時間 86400 秒, (60 秒 * 60 分鐘 * 24 小時) 。

不保證內容會快取您指定的時間量。 當記憶體資源變低時,快取就會自動開始收回內容。

清單 1 中的主控制器會傳回清單 2 中的 [索引] 檢視。 此檢視沒有任何特殊之處。 [索引] 檢視只會顯示目前的時間 (請參閱圖 1) 。

清單 2 – Views\Home\Index.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="MvcApplication1.Views.Home.Index" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Index</title>
</head>
<body>
    <div>
    
    The current time is: <%= DateTime.Now.ToString("T") %>
    
    
    </div>
</body>
</html>

圖 1 – 快取索引檢視

clip_image002

如果您在瀏覽器的網址列中輸入 URL /Home/Index 多次叫用 Index () 巨集指令,並重複按瀏覽器中的 [重新整理/重載] 按鈕,則 [索引] 檢視所顯示的時間將不會變更 10 秒。 因為已快取檢視,所以會顯示相同的時間。

請務必瞭解,對於造訪您應用程式的每個人,都會快取相同的檢視。 叫用 Index () 動作的任何人都可以取得相同的索引檢視快取版本。 這表示網頁伺服器必須執行才能提供索引檢視的工作量會大幅減少。

清單 2 中的檢視是執行非常簡單的動作。 檢視只會顯示目前的時間。 不過,您可以輕鬆地快取顯示一組資料庫記錄的檢視。 在此情況下,每次叫用傳回檢視的控制器動作時,都不需要從資料庫擷取一組資料庫記錄。 快取可以減少網頁伺服器和資料庫伺服器必須執行的工作量。

請勿在 MVC 檢視中使用頁面 < %@ OutputCache % > 指示詞。 此指示詞從Web Form世界開始運作,不應在 ASP.NET MVC 應用程式中使用。

快取內容的位置

根據預設,當您使用 [OutputCache] 屬性時,內容會快取在三個位置:網頁伺服器、任何 Proxy 伺服器和網頁瀏覽器。 您可以修改 [OutputCache] 屬性的 Location 屬性,以確切控制內容快取的位置。

您可以將 Location 屬性設定為下列任一值:

·任何

·客戶

·下游

·伺服器

·沒有

·ServerAndClient

根據預設,Location 屬性具有 Any 值。 不過,在某些情況下,您可能只想在瀏覽器或伺服器上快取。 例如,如果您要快取針對每個使用者個人化的資訊,則不應該快取伺服器上的資訊。 如果您向不同的使用者顯示不同的資訊,則應該只快取用戶端上的資訊。

例如,清單 3 中的控制器會公開名為 GetName () 的動作,此動作會傳回目前的使用者名稱。 如果 Jack 登入網站並叫用 GetName () 巨集指令,則動作會傳回字串 「Hi Jack」。 如果 Jill 隨後登入網站並叫用 GetName () 動作,則她也會取得字串 「Hi Jack」。 在 Jack 一開始叫用控制器動作之後,字串會在網頁伺服器上快取給所有使用者。

清單 3 – Controllers\BadUserController.cs

using System.Web.Mvc;
using System.Web.UI;

namespace MvcApplication1.Controllers
{
    public class BadUserController : Controller
    {
        [OutputCache(Duration = 3600, VaryByParam = "none")]
        public string GetName()
        {
            return "Hi " + User.Identity.Name;
        }
    }
}

最有可能的是,清單 3 中的控制器無法以您想要的方式運作。 您不想要將訊息 「Hi Jack」 顯示給 Jill。

您不應該快取伺服器快取中的個人化內容。 不過,您可能想要快取瀏覽器快取中的個人化內容,以改善效能。 如果您在瀏覽器中快取內容,而且使用者多次叫用相同的控制器動作,則可以從瀏覽器快取擷取內容,而不是伺服器。

清單 4 中修改過的控制器會快取 GetName () 巨集指令的輸出。 不過,內容只會在瀏覽器上快取,而不是在伺服器上快取。 如此一來,當多個使用者叫用 GetName () 方法時,每位人員都會取得自己的使用者名稱,而不是另一個人的使用者名稱。

清單 4 – Controllers\UserController.cs

using System.Web.Mvc;
using System.Web.UI;

namespace MvcApplication1.Controllers
{
    public class UserController : Controller
    {
        [OutputCache(Duration=3600, VaryByParam="none", Location=OutputCacheLocation.Client, NoStore=true)]
        public string GetName()
        {
            return "Hi " + User.Identity.Name;
        }
    }
}

請注意,清單 4 中的 [OutputCache] 屬性包含設定為 OutputCacheLocation.Client 值的位置屬性。 [OutputCache] 屬性也包含 NoStore 屬性。 NoStore 屬性可用來通知 Proxy 伺服器和瀏覽器,他們不應該儲存永久的快取內容複本。

改變輸出快取

在某些情況下,您可能會想要不同快取版本的相同內容。 例如,假設您正在建立主版/詳細資料頁面。 主版頁面會顯示電影標題清單。 當您按一下標題時,您會取得所選電影的詳細資料。

如果您快取詳細資料頁面,則不論您按一下哪部電影,都會顯示相同電影的詳細資料。 第一位使用者選取的第一部電影將會顯示給所有未來的使用者。

您可以利用 [OutputCache] 屬性的 VaryByParam 屬性來修正此問題。 當表單參數或查詢字串參數不同時,這個屬性可讓您建立相同內容的不同快取版本。

例如,清單 5 中的控制器會公開名為 Master () 和 Details () 的兩個動作。 Master () 巨集指令會傳回電影標題清單,而 Details () 巨集指令會傳回所選電影的詳細資料。

清單 5 – Controllers\MoviesController.cs

using System.Linq;
using System.Web.Mvc;
using MvcApplication1.Models;

namespace MvcApplication1.Controllers
{
    public class MoviesController : Controller
    {
        private MovieDataContext _dataContext;

        public MoviesController()
        {
            _dataContext = new MovieDataContext();
        }

        [OutputCache(Duration=int.MaxValue, VaryByParam="none")]
        public ActionResult Master()
        {
            ViewData.Model = (from m in _dataContext.Movies 
                              select m).ToList();
            return View();
        }

        [OutputCache(Duration = int.MaxValue, VaryByParam = "id")]
        public ActionResult Details(int id)
        {
            ViewData.Model = _dataContext.Movies.SingleOrDefault(m => m.Id == id);
            return View();
        }


    }
}

Master () 巨集指令包含具有值 「none」 的 VaryByParam 屬性。 叫用 Master () 巨集指令時,會傳回相同的主檢視快取版本。 (請參閱圖 2) ,忽略任何表單參數或查詢字串參數。

圖 2 – /Movies/Master 檢視

clip_image004

圖 3 – /Movies/Details 檢視

clip_image006

Details () 巨集指令包含具有 「Id」 值的 VaryByParam 屬性。 當 Id 參數的不同值傳遞至控制器動作時,會產生不同的 [詳細資料] 檢視快取版本。

請務必瞭解,使用 VaryByParam 屬性會產生更多快取,而不是更少。 系統會針對每個不同版本的 Id 參數,建立不同的 [詳細資料] 檢視快取版本。

您可以將 VaryByParam 屬性設定為下列值:

* = 每當表單或查詢字串參數不同時,建立不同的快取版本。

none = 永不建立不同的快取版本

參數的分號清單 = 每當清單中的任何表單或查詢字串參數都不同時,建立不同的快取版本

建立快取設定檔

除了修改 [OutputCache] 屬性的屬性來設定輸出快取屬性,您也可以在 Web 組態 (web.config) 檔案中建立快取設定檔。 在 Web 組態檔中建立快取設定檔提供幾個重要的優點。

首先,藉由在 Web 組態檔中設定輸出快取,您可以控制控制器動作如何在單一中央位置快取內容。 您可以建立一個快取設定檔,並將設定檔套用至數個控制器或控制器動作。

其次,您可以修改 Web 組態檔,而不重新編譯您的應用程式。 如果您需要停用已部署至生產環境之應用程式的快取,您可以直接修改 Web 組態檔中定義的快取設定檔。 系統會自動偵測 Web 組態檔的任何變更並套用。

例如,清單 6 中的 < 快取 > Web 組態區段會定義名為 Cache1Hour 的快取設定檔。 快 < 取 > 區段必須出現在 Web 組態檔的 < system.web > 區段中。

清單 6 – web.config的快取區段

<caching>
<outputCacheSettings>
    <outputCacheProfiles>
        <add name="Cache1Hour" duration="3600" varyByParam="none"/>
    </outputCacheProfiles>
</outputCacheSettings>
</caching>

清單 7 中的控制器說明如何使用 [OutputCache] 屬性,將 Cache1Hour 設定檔套用至控制器動作。

清單 7 – Controllers\ProfileController.cs

using System;
using System.Web.Mvc;

namespace MvcApplication1.Controllers
{
    public class ProfileController : Controller
    {
        [OutputCache(CacheProfile="Cache1Hour")]
        public string Index()
        {
            return DateTime.Now.ToString("T");
        }
    }
}

如果您在清單 7 中叫用控制器公開的 Index () 巨集指令,則會傳回相同的時間 1 小時。

總結

輸出快取提供非常簡單的方法來大幅改善 ASP.NET MVC 應用程式的效能。 在本教學課程中,您已瞭解如何使用 [OutputCache] 屬性來快取控制器動作的輸出。 您也瞭解如何修改 [OutputCache] 屬性的屬性,例如 Duration 和 VaryByParam 屬性,以修改內容的快取方式。 最後,您已瞭解如何在 Web 組態檔中定義快取設定檔。