《ASP.NET Core 6框架揭秘》實例演示[34]:緩存整個響應內容

我們利用ASP.NET開發的大部分API都是為了對外提供資源,對于不易變化的資源內容,針對某個維度對其實施緩存可以很好地提供應用的性能。《內存緩存與分布式緩存的使用》介紹的兩種緩存框架(本地內存緩存和分布式緩存)為我們提供了簡單易用的緩存讀寫編程模式,本篇介紹的則是針對針對HTTP響應內容實施緩存,ResponseCachingMiddleware中間件賦予我們的能力[本文節選《ASP.NET Core 6框架揭秘》第22章]。

目錄
[S2201]基于路徑的響應緩存(源代碼)
[S2202]基于指定的查詢字符串緩存響應(源代碼)
[S2203]基于指定的請求報頭緩存響應(源代碼)
[S2204]緩存屏蔽(源代碼)

[S2201]基于路徑的響應緩存

為了確定響應內容是否被緩存,如下的演示程序針對路徑“/{foobar?}”注冊的中間件會返回當前的時間。如代碼片段所示,我們調用UseResponseCaching擴展方法對ResponseCachingMiddleware中間件進行了注冊, AddResponseCaching擴展方法則注冊了該中間件依賴的服務。

using?Microsoft.Net.Http.Headers;var?app?=?WebApplication.Create();
app.UseResponseCaching();
app.MapGet("/{foobar}",?Process);
app.Run();static?DateTimeOffset?Process(HttpResponse?response)
{response.GetTypedHeaders().CacheControl?=?new?CacheControlHeaderValue{Public?=?true,MaxAge?=?TimeSpan.FromSeconds(3600)};return?DateTimeOffset.Now;
}

終結點處理方法Process在返回當前時間之前添加了一個Cache-Control響應報頭,并且將它的值設置為“public, max-age=3600”(public表示緩存的是可以被所有用戶共享的公共數據,而max-age則表示過期時限,單位為秒)。要證明整個響應的內容是否被緩存,只需要驗證在緩存過期之前具有相同路徑的多個請求對應的響應是否具有相同的主體內容。

GET?http://localhost:5000/foo?HTTP/1.1
Host:?localhost:5000HTTP/1.1?200?OK
Content-Type:?application/json;?charset=utf-8
Date:?Tue,?14?Dec?2021?02:13:39?GMT
Server:?Kestrel
Cache-Control:?public,?max-age=3600
Content-Length:?35"2021-12-14T10:13:39.8838806+08:00"
GET?http://localhost:5000/foo?HTTP/1.1
Host:?localhost:5000HTTP/1.1?200?OK
Content-Type:?application/json;?charset=utf-8
Date:?Tue,?14?Dec?2021?02:13:39?GMT
Server:?Kestrel
Age:?3
Cache-Control:?public,?max-age=3600
Content-Length:?35"2021-12-14T10:13:39.8838806+08:00"
GET?http://localhost:5000/bar?HTTP/1.1
Host:?localhost:5000HTTP/1.1?200?OK
Content-Type:?application/json;?charset=utf-8
Date:?Tue,?14?Dec?2021?02:13:49?GMT
Server:?Kestrel
Cache-Control:?public,?max-age=3600
Content-Length:?35"2021-12-14T10:13:49.0153031+08:00"
GET?http://localhost:5000/bar?HTTP/1.1
Host:?localhost:5000HTTP/1.1?200?OK
Content-Type:?application/json;?charset=utf-8
Date:?Tue,?14?Dec?2021?02:13:49?GMT
Server:?Kestrel
Age:?2
Cache-Control:?public,?max-age=3600
Content-Length:?35"2021-12-14T10:13:49.0153031+08:00"

如下所示的四組請求和響應是在不同時間發送的,其中兩個和后兩個請求采用的請求路徑分別為“/foo”和“/bar”。可以看出采用相同路徑的請求會得到相同的時間戳,意味著后續請求返回的內容來源于緩存,并且說明了響應內容默認是基于請求路徑進行緩存的。由于請求發送的時間不同,所以返回的緩存副本的“年齡”(對應響應報頭Age)也是不同的。

[S2202]基于指定的查詢字符串緩存響應

一般來說,對于提供資源的API來說,請求的路徑可以作為資源的標識,所以請求路徑決定返回的資源,這也是響應基于路徑進行緩存的理論依據。但是在很多情況下,請求路徑僅僅是返回內容的決定性因素之一,即使路徑能夠唯一標識返回的資源,但是資源可以采用不同的語言來表達,也可以采用不同的編碼方式,所以最終的響應的內容還是不一樣的。在編寫請求處理程序的時候,我們還經常根據請求攜帶的查詢字符串來生成響應的內容。以我們的演示的返回當前時間戳的實例來說,我們可以利用請求攜帶的查詢字符串“utc”或者請求報頭“X-UTC”來決定返回的是本地時間還是UTC時間。

using?Microsoft.AspNetCore.Mvc;
using?Microsoft.Net.Http.Headers;var?app?=?WebApplication.Create();
app.UseResponseCaching();
app.MapGet("/{foobar?}",?Process);
app.Run();static?DateTimeOffset?Process(HttpResponse?response,[FromHeader(Name?=?"X-UTC")]?string??utcHeader,[FromQuery(Name?="utc")]string??utcQuery)
{response.GetTypedHeaders().CacheControl?=?new?CacheControlHeaderValue{Public?=?true,MaxAge?=?TimeSpan.FromSeconds(3600)};return?Parse(utcHeader)????Parse(utcQuery)????false??DateTimeOffset.UtcNow?:?DateTimeOffset.Now;static?bool??Parse(string??value)=>?value?==?null??null:?string.Compare(value,?"1",?true)?==?0?||?string.Compare(value,?"true",?true)?==?0;
}

由于響應緩存默認采用的Key是派生于請求的路徑,但是對于我們修改過的這個程序來說,默認的這個緩存鍵的生成策略就有問題了。程序啟動后,我們采用路徑“/foobar”發送了如下兩個請求,其中第一個請求返回了實時生成的本地時間(+08:00表示北京時間采用的時區),對于第二個情況下,我們本來希望指定“utc”查詢字符串以返回一個UTC時間,但是我們得到卻是緩存的本地時間。

GET?http://localhost:5000/foobar?HTTP/1.1
Host:?localhost:5000HTTP/1.1?200?OK
Content-Type:?application/json;?charset=utf-8
Date:?Tue,?14?Dec?2021?02:54:54?GMT
Server:?Kestrel
Cache-Control:?public,?max-age=3600
Content-Length:?35"2021-12-14T10:54:54.6845646+08:00"
GET?http://localhost:5000/foobar?utc=true?HTTP/1.1
Host:?localhost:5000HTTP/1.1?200?OK
Content-Type:?application/json;?charset=utf-8
Date:?Tue,?14?Dec?2021?02:54:54?GMT
Server:?Kestrel
Age:?7
Cache-Control:?public,?max-age=3600
Content-Length:?35"2021-12-14T10:54:54.6845646+08:00"

[S2203]基于指定的請求報頭緩存響應

要解決這個問題,必須要讓我們希望的緩存維度作為緩存鍵的組成部分。就我們演示程序來說,就是得讓響應緩存的Key不僅僅包括請求的路徑,還應該包括查詢字符串“utc”和請求報頭“X-UTC”的值。為此我們對演示的程序進行了相應的修改。如下面的代碼片段所示,我們從當前HttpContext上下文中提取出IResponseCachingFeature特性,并將設置了它的VaryByQueryKeys屬性使之包含了參與緩存的查詢字符串的名稱“utc”。為了讓自定義請求報頭“X-UTC”的值也參與緩存,我們將“X-UTC”作為Vary響應報頭的值。

using?Microsoft.AspNetCore.Mvc;
using?Microsoft.AspNetCore.ResponseCaching;
using?Microsoft.Net.Http.Headers;var?app?=?WebApplication.Create();
app.UseResponseCaching();
app.MapGet("/{foobar?}",?Process);
app.Run();static?DateTimeOffset?Process(HttpContext?httpContext,[FromHeader(Name?=?"X-UTC")]?string??utcHeader,[FromQuery(Name?="utc")]string??utcQuery)
{var?response?=?httpContext.Response;response.GetTypedHeaders().CacheControl?=?new?CacheControlHeaderValue{Public?=?true,MaxAge?=?TimeSpan.FromSeconds(3600)};var?feature?=?httpContext.Features.Get<IResponseCachingFeature>()!;feature.VaryByQueryKeys?=?new?string[]?{?"utc"?};response.Headers.Vary?=?"X-UTC";return?Parse(utcHeader)????Parse(utcQuery)????false???DateTimeOffset.UtcNow?:?DateTimeOffset.Now;static?bool??Parse(string??value)=>?value?==?null??null:?string.Compare(value,?"1",?true)?==?0?||?string.Compare(value,?"true",?true)?==?0;
}

對于我們修正過演示程序來說,請求查詢字符串“utc”的值會作為響應緩存鍵的一部分,我們在重啟應用后發送了如下針對“/foobar”的四個請求。前兩個請求和后兩個請求采用相同的查詢字符串(“?utc=true”和“?utc=false”),所以后一個請求會返回緩存的內容。

GET?http://localhost:5000/foobar?utc=true?HTTP/1.1
Host:?localhost:5000HTTP/1.1?200?OK
Content-Type:?application/json;?charset=utf-8
Date:?Tue,?14?Dec?2021?02:59:23?GMT
Server:?Kestrel
Cache-Control:?public,?max-age=3600
Vary:?X-UTC
Content-Length:?35"2021-12-14T02:59:23.0540999+00:00"
GET?http://localhost:5000/foobar?utc=true?HTTP/1.1
Host:?localhost:5000HTTP/1.1?200?OK
Content-Type:?application/json;?charset=utf-8
Date:?Tue,?14?Dec?2021?02:59:23?GMT
Server:?Kestrel
Age:?3
Cache-Control:?public,?max-age=3600
Vary:?X-UTC
Content-Length:?35"2021-12-14T02:59:23.0540999+00:00"

從上面給出的報文的內容可以看出,響應報文具有一個值為“X-UTC”的Vary報頭,它告訴客戶端響應的內容會根據這個名為“X-UTC”的請求報頭進行緩存。為了驗證這一點,我們在重啟應用后針對“/foobar”發送了如下四個請求,前兩個請求和后兩個請求采用相同的X-UTC(“X-UTC: True”和“X-UTC: False”),所以后一個請求會返回緩存的內容。

GET?http://localhost:5000/foobar?HTTP/1.1
X-UTC:?True
Host:?localhost:5000HTTP/1.1?200?OK
Content-Type:?application/json;?charset=utf-8
Date:?Tue,?14?Dec?2021?03:05:06?GMT
Server:?Kestrel
Cache-Control:?public,?max-age=3600
Vary:?X-UTC
Content-Length:?34"2021-12-14T03:05:06.977078+00:00"
GET?http://localhost:5000/foobar?HTTP/1.1
X-UTC:?True
Host:?localhost:5000HTTP/1.1?200?OK
Content-Type:?application/json;?charset=utf-8
Date:?Tue,?14?Dec?2021?03:05:06?GMT
Server:?Kestrel
Age:?3
Cache-Control:?public,?max-age=3600
Vary:?X-UTC
Content-Length:?34"2021-12-14T03:05:06.977078+00:00"
GET?http://localhost:5000/foobar?HTTP/1.1
X-UTC:?False
Host:?localhost:5000HTTP/1.1?200?OK
Content-Type:?application/json;?charset=utf-8
Date:?Tue,?14?Dec?2021?03:05:17?GMT
Server:?Kestrel
Cache-Control:?public,?max-age=3600
Vary:?X-UTC
Content-Length:?35"2021-12-14T11:05:17.0068036+08:00"
GET?http://localhost:5000/foobar?HTTP/1.1
X-UTC:?False
Host:?localhost:5000HTTP/1.1?200?OK
Content-Type:?application/json;?charset=utf-8
Date:?Tue,?14?Dec?2021?03:05:17?GMT
Server:?Kestrel
Age:?19
Cache-Control:?public,?max-age=3600
Vary:?X-UTC
Content-Length:?35"2021-12-14T11:05:17.0068036+08:00"

響應緩存通過復用已經生成的響應內容來提升性能,但不意味任何請求都適合以緩存的內容予以回復,請求攜帶的一些報頭會屏蔽掉響應緩存。或者更加準確的說法是,客戶端請求攜帶的一些報頭會“提醒”服務端當前場景需要返回實時內容。比如攜帶Authorization報頭的請求默認情況下將不會使用緩存的內容予以回復,下面的請求/響應體現了這一點。

GET?http://localhost:5000/foobar?HTTP/1.1
Host:?localhost:5000HTTP/1.1?200?OK
Content-Type:?application/json;?charset=utf-8
Date:?Tue,?14?Dec?2021?03:13:10?GMT
Server:?Kestrel
Cache-Control:?public,?max-age=3600
Vary:?X-UTC
Content-Length:?35"2021-12-14T11:13:10.4605924+08:00"
GET?http://localhost:5000/foobar?HTTP/1.1
Authorization:?foobar
Host:?localhost:5000HTTP/1.1?200?OK
Content-Type:?application/json;?charset=utf-8
Date:?Tue,?14?Dec?2021?03:13:17?GMT
Server:?Kestrel
Cache-Control:?public,?max-age=3600
Vary:?X-UTC
Content-Length:?35"2021-12-14T11:13:18.0918033+08:00"

關于Authorization請求報頭與緩存的關系,它與前面介紹的根據指定的請求報頭對響應內容進行緩存是不一樣的,當ResponseCachingMiddleware中間件在處理請求時,只要請求攜帶了此報頭,緩存策略將不再使用。如果客戶端對數據的實時性要求很高,那么它更希望服務總是返回實時生成的內容,這種情況下它利用利用攜帶的一些請求報頭向服務端傳達這樣的意圖,此時一般會使用到報頭“Cache-Control:no-cache”或者“Pragma:no-cache”。這兩個請求報頭對響應緩存的屏蔽作用體現在如下所示的四組請求/響應中。

GET?http://localhost:5000/foobar?HTTP/1.1
Host:?localhost:5000HTTP/1.1?200?OK
Content-Type:?application/json;?charset=utf-8
Date:?Tue,?14?Dec?2021?03:15:16?GMT
Server:?Kestrel
Cache-Control:?public,?max-age=3600
Vary:?X-UTC
Content-Length:?34"2021-12-14T11:15:16.423496+08:00"
GET?http://localhost:5000/foobar?HTTP/1.1
Cache-Control:?no-cache
Host:?localhost:5000HTTP/1.1?200?OK
Content-Type:?application/json;?charset=utf-8
Date:?Tue,?14?Dec?2021?03:15:26?GMT
Server:?Kestrel
Cache-Control:?public,?max-age=3600
Vary:?X-UTC
Content-Length:?35"2021-12-14T11:15:26.7701298+08:00"
GET?http://localhost:5000/foobar?HTTP/1.1
Pragma:?no-cache
Host:?localhost:5000HTTP/1.1?200?OK
Content-Type:?application/json;?charset=utf-8
Date:?Tue,?14?Dec?2021?03:15:36?GMT
Server:?Kestrel
Cache-Control:?public,?max-age=3600
Vary:?X-UTC
Content-Length:?35"2021-12-14T11:15:36.5283536+08:00"

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/280214.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/280214.shtml
英文地址,請注明出處:http://en.pswp.cn/news/280214.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

常見端口介紹

Win常用端口 TCP端口&#xff08;靜態端口&#xff09;TCP 0 ReservedTCP 1TCP Port Service MultiplexerTCP 2DeathTCP 5Remote Job Entry,yoyoTCP 7EchoTCP 11SkunTCP 12BomberTCP 16SkunTCP 17SkunTCP 18消息傳輸協議&#xff0c;skunTCP 19SkunTCP 20FTP Data,Amanda TCP 2…

如何更改Windows 10鎖定屏幕超時

By default, Windows 10’s lock screen times out and switches off your monitor after one minute. If you’d like it to stick around longer than that–say, if you have background picture you like looking at or you enjoy having Cortana handy–there’s a simple…

ios 開發賬號 退出協作_如何在iOS 10中的Notes上進行協作

ios 開發賬號 退出協作iOS’ Notes app provides a convenient way to remember the great ideas you come up with and all the things you have to do. The app has evolved over the years, and iOS 10 adds even more features–including collaboration. iOS的Notes應用程…

poj 1182

食物鏈Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 86494 Accepted: 25887Description 動物王國中有三類動物A,B,C&#xff0c;這三類動物的食物鏈構成了有趣的環形。A吃B&#xff0c; B吃C&#xff0c;C吃A。 現有N個動物&#xff0c;以1&#xff0d;N編號。每…

條款6:若不想使用編譯器自動生成的函數,就該明確拒絕

如果自己定義的類中并不需要copy assignment操作符或者copy構造函數&#xff0c;為了避免編譯器自動生成因為編譯器自動生成的沒什么用&#xff0c;一般是按照順序進行賦值或者拷貝&#xff0c;對于有對象內含有指針的話可能會出現一些問題可以在private中聲明&#xff08;并不…

為什么Android Geeks購買Nexus設備

The Galaxy S III is the highest-selling Android phone, but much of the geeky buzz is around the Nexus 4 – and the Galaxy Nexus before it. Nexus devices are special because they don’t have some of Android’s biggest problems. Galaxy S III是最暢銷的Android…

你的知識死角不能否定你的技術能力

有些事情你不知道&#xff0c;但你一定能解決。 有些人通過我賬號資料里的微信加我&#xff0c;然后問我一些所謂“怎么辦”的問題&#xff0c;不是我不告訴你&#xff0c;而是我確實不知道。我確實有很高的title&#xff0c;也確實有很多的技術積累&#xff0c;但我并沒有達到…

算法練習(十二)

The Suspects Description 嚴重急性呼吸系統綜合癥( SARS), 一種原因不明的非典型性肺炎,從2003年3月中旬開始被認為是全球威脅。為了減少傳播給別人的機會, 最好的策略是隔離可能的患者。 在Not-Spreading-Your-Sickness大學( NSYSU), 有許多學生團體。同一組的學生經常彼此相…

day4----函數-閉包-裝飾器

day4----函數-閉包-裝飾器 本文檔內容&#xff1a; 1 python中三種名稱空間和作用域 2 函數的使用 3 閉包 4 裝飾器 一 python中三種名稱空間和作用域 1.1名稱空間&#xff1a; 當程序運行時&#xff0c;代碼從上至下依次執行&#xff0c;它會將變量與值得關系存儲在一個空間中…

濾波器和均衡器有什么區別_什么是均衡器,它如何工作?

濾波器和均衡器有什么區別It’s in your car, home theater system, phone, and audio player but it doesn’t have an instruction manual. It’s an equalizer, and with a little know-how you can tweak your audio and fall in love with it all over again. 它在您的汽車…

網絡視頻監控與人臉識別

明天又要去面試了&#xff0c;趁次機會也將以前做的東西總結一下&#xff0c;為以后理解提供方便&#xff0c;也再加深下印象。 網絡視頻監控與人臉識別主要由三個程序組成&#xff1a;1、視頻采集與傳輸程序&#xff1b;2、接受與顯示程序&#xff1b;3、人臉識別程序。下面就…

esxi.主機配置上聯端口_為什么現代的電腦機箱仍然具有USB 2.0端口?

esxi.主機配置上聯端口With USB 3.0 becoming more prevalent with each passing year now, you may have found yourself wondering why modern computers still have USB 2.0 ports built into them. With that in mind, today’s SuperUser Q&A post has the answers to…

使用命令導入、導出mysql數據

1.導出全部數據庫 利用mysqldump的—all-databases參數可以一口氣把你數據庫root用戶下的所有數據庫一口氣導出到一個sql文件里。然后&#xff0c;重裝系統后使用source命令可以再一口氣倒回來。 需要確定mysql安裝的路徑&#xff1a;本機是&#xff1a;C:\Program Files\MySQL…

面試--跨域--cors

cors是什么 cors 跨域資源共享 Cross-origin resource sharing是一種跨域的解決方案 它允許瀏覽器向跨源服務器&#xff0c;發出XMLHttpRequest請求&#xff0c;從而克服了AJAX只能同源使用的限制。 但是需要瀏覽器的支持。值得注意的是&#xff1a;整個CORS通信過程&#xff0…

【原理圖操作】原理圖更新PCB時未改動元器件布局變動問題?

轉載PCB布局、布線完工之后&#xff0c;由于設計功能&#xff0c;發現不完善時, 原理圖部分功能需要改動&#xff0c;再改原理圖&#xff0c;修改完成后&#xff0c;導入PCB過程中&#xff0c;發現PCB中未改動&#xff08;部分&#xff09;的元器件 布局發生了變化&#xff0c;…

關閉edge任務欄預覽_如何在Microsoft Edge中關閉選項卡預覽

關閉edge任務欄預覽Now that it has extension support, Microsoft Edge is becoming a more and more viable browser. One feature people seem to either love or hate is the pop-up preview you get when you hover over a tab. There’s no built-in setting that lets y…

oracle 創建view時,授權給用戶

解決方法&#xff1a; 以dba用戶登錄 sqlplus / as sysdba 賦予scott用戶創建VIEW的權限 grant create view to scott 以scott用戶登錄oracle conn scott/tiger 創建視圖成功 CREATE OR REPLACE VIEW myview AS 轉載于:https://www.cnblogs.com/523823-wu/p/7635436.html

[BZOJ 1072] 排列perm

Link&#xff1a; BZOJ 1072 傳送門 Solution&#xff1a; 一道直接next_permutation純暴力就能過的題&#xff1f; 難道2007年時大家都不知道next_permutation這個函數嗎 還是用復雜度更優的狀壓DP吧 設$dp[i][j]$為狀態為$i$且對$d$余$j$的個數&#xff0c; 注意$dp[(1<&l…

智能手機丟失 數據安全_丟失智能手機時該怎么辦

智能手機丟失 數據安全Phones get stolen or lost everyday. With a plethora of data ripe for identity-theft on it, a lost phone can easily make your blood run cold. Take a deep breath, How-To Geek will talk you through this. 手機每天都會被盜或丟失。 隨著大量用…

程序員怎樣成為一名架構師?

在今天的技術圈&#xff0c;可能隨便遇到一個人遞給你一張名片&#xff0c;title 就是某某架構師。架構師多如過江之鯽&#xff0c;也正是眼下業內一個有趣的現象。對于架構師&#xff0c;你有什么看法&#xff1f;什么是架構師&#xff1f;隨便打開某招聘網站&#xff1a;系統…