.NET Core ResponseCache【緩存篇(一)】

1、前言css

  源碼git

   一、最近一直在看項目性能優化方式,俗話說的好項目優化第一步那固然是添加緩存,咱們的項目之因此卡的和鬼同樣,要麼就是你的代碼循環查詢數據庫(這個以前在咱們的項目中常常出現,如今慢慢在修正)或者代碼作了不少不應作的事情。這個時候就能夠引入咱們的緩存了。(只要你的代碼不是寫的特別差,好比以前實習的我)。web

  二、緩存主要分爲兩種 客戶端(瀏覽器緩存)、服務端緩存。當咱們的數據不須要及時返回的時候,能夠考慮將頁面緩存到客戶的瀏覽器中進行保存,在必定的時間內訪問直接讀取瀏覽器緩存的信息。咱們經過設置HTTP的響應頭 Cache-Control 來完成頁面存儲到瀏覽器緩存中以下所示:
redis

 2、客戶端(瀏覽器緩存)數據庫

  一、在老的版本的MVC裏面,有一種能夠緩存視圖的特性(OutputCache),能夠保持同一個參數的請求,在N段時間內,直接從mvc的緩存中讀取,不去走視圖的邏輯。瀏覽器

//老版本的.NET 作法
[OutputCache(Duration =20)]//設置過時時間爲20秒  
    public ActionResult ExampleCacheAction()  
    {  
        var  time=DateTime.Now.ToString("yyyy年MM月dd日 HH時mm分ss秒");  
        ViewBag.time= time;  
        return View();  
    }  

  二、在.Net core 中就沒有(OutputCache)了,使用的是(ResponseCache)特性。官方文檔上稱:響應緩存可減小客戶端或代理對 web 服務器的請求數。 響應緩存還可減小量工做的 web 服務器執行程序生成響應。 響應緩存由標頭,指定你但願客戶端、 代理和緩存響應的中間件如何控制。緩存

 /*
         Duration 表明緩存持續時間(秒)至少1秒
         VaryByHeader 設置vary 請求頭信息使用vary頭有利於內容服務的動態多樣性。例如,使用Vary: User-Agent頭,緩存服務器須要經過UA判斷是否使用緩存的頁面。
         Location 緩存位置
                  None 報頭設置爲「no-cache」不使用緩存
                  Client 只緩存在客戶端。設置「Cache-control」標題爲「private」。
                  Any 緩存在代理和客戶端。設置「Cache-control」標題爲「public」。
        NoStore   緩存中不得存儲任何關於客戶端請求和服務端響應的內容。每次由客戶端發起的請求都會下載完整的響應內容。若是設置爲False Duration必須大於0
        VaryByQueryKeys 能夠按照相同頁面,不一樣的參數進行相應的存儲
        CacheProfileName 設置緩存配置文件的值,能夠經過設置不一樣的緩存參數
         */
        [ResponseCache(Duration = 50, VaryByQueryKeys = new string[] { "q","name" })]
        public IActionResult Index(int q,string name)
        {
            return View(DateTime.Now);
        }

  三、經過運行咱們能夠看到,瀏覽器多了一個cache-control:public,max-age=50 它的意思是public緩存在代理和客戶端。max-age=50表明緩存的時間50秒。性能優化

  四、還有一種簡單粗暴的實現方式,由於咱們知道添加了這個特性只是在響應請求頭中添加了一個cache-control:public,max-age=50,那麼咱們能夠也能夠直接在請求響應中設置這個請求頭就完事了,效果都是同樣的。服務器

public IActionResult Index()
{
    //直接一,簡單粗暴,不要拼寫錯了就好~~
    Response.Headers[Microsoft.Net.Http.Headers.HeaderNames.CacheControl] = "public, max-age=600";
    
    //直接二,略微優雅點
    //Response.GetTypedHeaders().CacheControl = new Microsoft.Net.Http.Headers.CacheControlHeaderValue()
    //{
    //    Public = true,
    //    MaxAge = TimeSpan.FromSeconds(600)
    //};

    return View();
}

  五、有時候爲了統一管理緩存配置,咱們能夠將緩存配置提早寫到配置中,使用名字進行調用。[ResponseCache(CacheProfileName ="test")],在Startup中注入視圖的時候寫入。mvc

//設置一些緩存策略
            services.AddControllersWithViews(options =>
            {
                options.CacheProfiles.Add("default", new CacheProfile
                {
                    Duration = 60
                });

                options.CacheProfiles.Add("test", new CacheProfile
                {
                    Duration = 30,
                    Location=ResponseCacheLocation.Client
                });
            });

  六、[ResponseCache] 參數

    •   Duration 設置緩存的存儲時間(以秒爲單位)。設置「Cache-control」中的「max-age」。
    •   Location
      •   Any 緩存在代理和客戶端。設置「Cache-control」標題爲「public」。
      •   Client 只緩存在客戶端。設置「Cache-control」標題爲「private」。
      •   None 每次有請求發出時,緩存會將請求發到服務器 ,服務器端會驗證請求中所描述的緩存是否過時,若未過時(注:實際就是返回304),則緩存才使用本地緩存副本。 報頭設置爲「no-cache」。
    •   NoStore 緩存中不得存儲任何關於客戶端請求和服務端響應的內容。每次由客戶端發起的請求都會下載完整的響應內容。
    •   VaryByHeader 使用vary頭有利於內容服務的動態多樣性。例如,使用Vary: User-Agent頭,緩存服務器須要經過UA判斷是否使用緩存的頁面。
    •   VaryByQueryKeys 能夠按照相同頁面,不一樣的參數進行相應的存儲
    •   CacheProfileName 設置緩存配置文件的值,能夠經過設置不一樣的緩存參數

3、服務端緩存

  一、ResponseCache也能夠設置服務端緩存,將咱們返回的數據存儲在服務端中在必定的時間內返回存儲的數據,這裏我先引入一個案例,有時候咱們須要傳遞不一樣的參數進行緩存。

     案例:當咱們訪問的數據帶分頁參數的時候咱們怎麼作呢?VaryByQueryKeys前面咱們講了這個,能夠根據不一樣的參數進行緩存,那麼咱們如今使用看看 

        結果:當咱們運行的時候,發現報錯了,報錯的意思大體是說咱們沒有使用中間件,可是爲何我這個緩存要使用到中間件呢?實際上是由於要區分,咱們請求的參數,而後會將咱們的數據進行緩存起來,就是實現了服務端緩存。這裏的咱們就要使用微軟提供的中間件了。

 二、咱們主要是在Startup中注入services.AddResponseCaching();app.UseResponseCaching();中間件。服務端緩存能夠緩存頁面數據和API數據,同時若是咱們服務端存在數據,也就是緩存命中的狀況下,會直接從緩存中取,不會再進入咱們的方法。

 public void ConfigureServices(IServiceCollection services)
        {
              services.AddResponseCaching(options =>
            {
                options.UseCaseSensitivePaths = false;
                options.MaximumBodySize = 1024;
                options.SizeLimit = 100 * 1024*1024;
            });
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseResponseCaching();
        }

服務端緩存配置以下,當咱們配置添加了中間件和注入緩存以後,就可使用VaryByQueryKeys了。當咱們訪問一次以後就會將結果緩存到咱們的客戶端緩存中,和服務端緩存各一份。當咱們使用同一個瀏覽器訪問的時候訪問的就是客戶端緩存信息,當咱們切換瀏覽器訪問的時候也不會請求咱們的方法,會先進入到咱們的中間件中查看是否存在服務端緩存,若是存在就是直接拿緩存進行返回,若是沒有就會請求方法返回,而後再將結果進行緩存。

屬性

描述

MaximumBodySize

響應正文的最大可緩存大小(以字節爲單位)。 默認值爲 64 * 1024 * 1024 (64 MB)。

SizeLimit

響應緩存中間件的大小限制(以字節爲單位)。 默認值爲 100 * 1024 * 1024 (100 MB)。

UseCaseSensitivePaths

肯定是否將響應緩存在區分大小寫的路徑上。 默認值是 false。

 三、對於一些常年不變或比較少變的js,css等靜態文件,也能夠把它們緩存起來,避免讓它們老是發起請求到服務器,並且這些靜態文件能夠緩存更長的時間!若是已經使用了CDN,這一小節的內容就能夠暫且忽略掉了。。。對於靜態文件,.NET Core有一個單獨的StaticFiles中間件,若是想要對它作一些處理,一樣須要在管道中進行註冊。UseStaticFiles有幾個重載方法,這裏用的是帶StaticFileOptions參數的那個方法。由於StaticFileOptions裏面有一個OnPrepareResponse可讓咱們修改響應頭,以達到HTTP緩存的效果。

app.UseStaticFiles(new StaticFileOptions
{
    OnPrepareResponse = context =>
    {
        context.Context.Response.GetTypedHeaders().CacheControl = new Microsoft.Net.Http.Headers.CacheControlHeaderValue
        { 
            Public = true,
            //for 1 year
            MaxAge = System.TimeSpan.FromDays(365)
        };
    }
});

4、使用前置條件

  • 請求必須致使服務器響應,狀態代碼爲200(正常)。
  • 請求方法必須爲 GET 或 HEAD。
  • 在 Startup.Configure中,響應緩存中間件必須置於須要緩存的中間件以前。
  • Authorization 標頭不得存在。
  • Cache-Control 標頭參數必須是有效的,而且響應必須標記爲 「public」 且未標記爲 「private」。
  • 若是 Cache-Control 標頭不存在,則 Pragma: no-cache 標頭不得存在,由於 Cache-Control 標頭在存在時將覆蓋 Pragma 標頭。
  • Set-Cookie 標頭不得存在。
  • Vary 標頭參數必須有效且不等於 *。
  • Content-Length 標頭值(若是已設置)必須與響應正文的大小匹配。
  • 不使用 IHttpSendFileFeature。
  • Expires 標頭和 max-age 和 s-maxage 緩存指令指定的響應不能過期。
  • 響應緩衝必須成功。 響應的大小必須小於配置的或默認 SizeLimit。 響應的正文大小必須小於配置的或默認的 MaximumBodySize。
  • 「請求」 或 「響應」 標頭字段中不得存在 「no-store」 指令。
相關文章
相關標籤/搜索