前言
在Asp.Net Core Nginx部署一文中,主要是講述的如何利用Nginx來實現應用程序的部署,使用Nginx來部署主要有兩大好處,第一是利用Nginx的負載均衡功能,第二是使用Nginx的反向代理來降低我們后端應用程序的壓力。那除了以上兩點之外,其實我們還可以利用代理服務器的緩存功能來進一步的降低后端應用程序的壓力,提升系統的吞吐量(tps)。這一篇就來看一下具體應該如何去做吧。
目錄
- WEB 緩存
- ASP.NET Core 緩存
內存緩存
分布式緩存
Response 緩存 - Nginx 緩存
- 總結
WEB 緩存
之所以加這個目錄是因為有一部分初學者對緩存的認知不夠,特別是WEB中的緩存。
緩存它是一種空間換取時間的一種技術。
Web緩存(或HTTP緩存)是用于Web文檔,如HTML頁面和圖像,減少帶寬的使用,服務器的負載的一種信息技術。一個Web緩存系統存儲通過Cache來傳遞的文件的副本;如果滿足某些條件,則可以從緩存中得到后續的請求。
WEb緩存有幾種方式:
1、服務端緩存
利用 Memcached,Redis,In-Memery 等緩存技術實現對數據的緩存。
2、代理服務器緩存
利用類似nginx的反向代理服務器,對請求的url對應的輸出的進行緩存。這個緩存和應用程序實現的動態頁面緩存類似,只不過用反向代理充當了應用程序的緩存實現。
3、客戶端緩存
瀏覽器緩存,其實主要就是HTTP協議定義的緩存機制(如: Last-Modified,If-Modified-Since,Expires; Cache-control等)。
ASP.NET Core 緩存
- 內存緩存
最簡單的一種緩存,ASP.NET Core 提供了 IMemoryCache 接口來供我們使用。它存儲在本地的 WEB 服務器內容中,注意是單機的 WEB 服務器,如果你需要部署的是一個服務器集群的話,那么你應該用分布式緩存,而不是選擇這個。
就不詳細介紹了,想了解的可以直接看官方文檔。
- 分布式緩存
隨著云應用和服務器集群以及 docker 等技術的成熟,越來越多的應用程序開始考慮集群部署,因為它具有更好的性能和可伸縮可擴展性。那么這個時候就需要用到分布式緩存了。
在 ASP.NET Core應用中,已經對分布式緩存做了抽象,提供了 IDistributedCache 接口,該接口提供了添加,檢索,刪除等的同步和異步的方法。并且還默認提供了 Redis 和 SQLServer 的分布式緩存實現,我們也可以實現 IDistributedCache 接口來擴展自己的緩存系統。
需要說明的是Get,GetAsync
和Set,SetAsync
。 這兩個接口方法默認是使用的byte[]
,之所以沒有提供直接存儲對象的方法是因為微軟想把這個默認序列化的選擇交給用戶,因為每一個團隊的偏好是不一樣的,有些團隊喜歡使用 XML,有些喜歡使用 JSON,有些喜歡使用 Protobuf 等,所以在 項目中,你可以根據自己的偏好來擴展想要的方法。
具體使用方法還是直接看官方文檔好了。
關于使用也可以查看我的另外一篇博客: ASP.NET Core 使用 Redis 和 Protobuf 進行 Session 緩存。
- Response 緩存
在 ASP.NET Core中,有一種緩存叫做Response緩存,這個緩存主要是用來做代理服務器的緩存。它主要原理是在輸出的HTTP Response的header里面添加指定的緩存標記。這些緩存標記用來讓客戶端或者代理服務器來識別需要緩存的內容。然后當客戶端有請求到代理服務器的時候,代理服務器可以識別出一部分請求,然后直接把結果返回給瀏覽器,從而提高后端應用程序的性能和吞吐。
從這個圖中看出來,在第一次的時候,一個客戶端請求經過代理服務器請求的我們后端的WEB服務器上,然后WEB服務器在返回結果的META上添加了cache-control
標簽,它的值為public
。
下面是cache-control
標簽一些值的說明:
public
指示響應可被任何緩存區緩存。
private
指示對于單個用戶的整個或部分響應消息,不能被共享緩存處理。這允許服務器僅僅描述當用戶的部分響應消息,此響應消息對于其他用戶的請求無效。
no-cache
指示請求或響應消息不能緩存(HTTP/1.0用Pragma的no-cache替換)根據什么能被緩存
max-age
指示客戶機可以接收生存期不大于指定時間(以秒為單位)的響應。
min-fresh
指示客戶機可以接收響應時間小于當前時間加上指定時間的響應。
max-stale
指示客戶機可以接收超出超時期間的響應消息。如果指定max-stale消息的值,那么客戶機可以接收超出超時期指定值之內的響應消息。
Expires 表示存在時間,允許客戶端在這個時間之前不去檢查(發請求),等同max-age的
效果。但是如果同時存在,則被Cache-Control的max-age覆蓋。
格式:
Expires = "Expires" ":" HTTP-date
通過HTTP的META設置expires和cache-control
<meta http-equiv="Cache-Control" content="max-age=7200" />
<meta http-equiv="Expires" content="Mon, 20 Jul 2016 23:00:00 GMT" />
在 ASP.NET Core MVC 中,提供了ResponseCache
這個特性用來做上面這些事情。它被作為一個Attribute添加的Controller的Action上。
Duration
指示緩存的過期時間,對應到Cache-Control 的 max-age 。
Location
有三個值Any
,Client
,None
分別對應到Cache-Control的 public,private,no-cache。
NoStore
設置值是否被存儲。如果是true,它將設置Cache-Control為no-store
VaryByHeader
將在header中添加Vary標記。
CacheProfileName
使用的策略,在startup.cs中設置。
Order
在過濾器中的排序。
現在,我們已經知道了如果在Action中設置緩存標記了。
Nginx 緩存
對于一些靜態文件,比如程序用到的圖片,css,js等,Nginx是可以直接處理的,只需要配置一下。
如果使用Nginx來處理靜態文件的話,那么程序中startup.cs
就可以不用添加app.UseStaticFiles();
中間件了。
- 配置
打開nginx.conf文件,在ubuntu系統下位于/etc/nginx/conf.d/nginx.conf
沒有的話就新建一個。內容如下:
proxy_temp_path /usr/local/nginx/proxy_temp_dir 1 2; #注:proxy_temp_path和proxy_cache_path指定的路徑必須在同一分區
#keys_zone=cache1:100m 表示這個zone(緩存區域)名稱為cache1,分配的內存大小為100MB
#/usr/local/nginx/proxy_cache_dir/cache1 表示cache1這個zone的文件要存放的目錄
#levels=1:2 表示緩存目錄的第一級目錄是1個字符,第二級目錄是2個字符,即/usr/local/nginx/proxy_cache_dir/cache1/a/1b這種形式
#inactive=1d 表示這個zone中的緩存文件如果在1天內都沒有被訪問,那么文件會被cache manager進程刪除掉
#max_size=10g 表示這個zone的硬盤容量為10GB
proxy_cache_path /usr/local/nginx/proxy_cache_dir/cache1 levels=1:2 keys_zone=cache1:100m inactive=1d max_size=10g;
#upstream web-app {
# server webapp1:5090;
# server webapp2:5090;
#}
server {
listen 80;
server_name *.example.com;
#在日志格式中加入$upstream_cache_status
log_format format1 '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" $upstream_cache_status';
#訪問日志
access_log log/access.log fomat1;
#$upstream_cache_status表示資源緩存的狀態,有HIT MISS EXPIRED三種狀態
add_header X-Cache $upstream_cache_status;
#命中的正則表達式
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|js|css|html)$ {
proxy_pass http://127.0.0.1:5000;
#proxy_pass http://web-app;
#proxy_set_header Host $host;
#proxy_set_header X-Real-IP $remote_addr;
#proxy_set_header X-Forwarded-For $remote_addr;
#proxy_set_header Accept-Encoding "none";
#設定proxy_set_header Accept-Encoding '';(或是后臺服務器關閉gzip),這樣這臺機器才不會緩存被壓縮的文件,造成亂碼
#proxy_set_header Accept-Encoding ""; 這個也可
#如果后端的服務器返回502、504、執行超時等錯誤,自動將請求轉發到upstream負載均衡池中的另一臺服務器,實現故障轉移。
#proxy_next_upstream http_502 http_504 error timeout invalid_header;
#設置資源緩存的zone
proxy_cache cache1;
#設置緩存的key
proxy_cache_key $host$uri$is_args$args;
#設置狀態碼為200和304的響應可以進行緩存,并且緩存時間為10分鐘
proxy_cache_valid 200 304 10m;
# **!!!重要!!!** 這段配置加上后,proxy_cache就能支持后臺設定的Cache-Control,Expires。
proxy_ignore_headers "Cache-Control" "Expires";
expires 30d;
}
}
上面有一個配置項在 ASP.NET Core 程序中比較重要,就是proxy_ignore_headers
這個配置項,它代表支持后臺設定Cache-Control,Expires等。
其中upstream
節點是用來配置負載均衡的服務器的,proxy_pass
用來設置代理到upstream
節點,proxy_next_upstream
是用來配置故障轉移。
- 應用配置
使用sudo nginx -s reload
命令來重新加載配置。
總結
關于緩存
緩存確實是提升應用程序性能最快也是效果最明顯的方式之一,ASP.NET Core也為提供了很多種緩存方法。但是,在使用之前一定要了解每一種緩存的技術實現,切不可盲目使用。
關于部署
個人認為,在 ASP.NET Core 理想的分布式部署環境有兩種:
第一種是基于云的部署,比如使用Azure,AWS,阿里云等,那么我們可以使用他們提供的負載均衡器來幫助我們攔截洪水般的請求,然后借助于云提供的高可用的實例集群或者Docker集群來降低應用程序的壓力,提升吞吐。
比如我們項目現在使用的AWS的部署環境,借助于AWS來實現企業的私有云,包括高可用的Redis集群,彈性EC2集群,RDS集群,S3等,這個時候只需要專注于業務。
第二種是自己搭建集群環境,可以在服務器前端使用Nginx的負載均衡和緩存來攔截大部分的HTTP請求,然后后端使用Docker集群來做部署。
Docker部署可以參見本人的另外一篇文章:http://www.cnblogs.com/savorboard/p/dotnetcore-docker.html
在版本的快速迭代過程中,你還需要做的工作有如何提高部署的工作效率,那么可以使用一些Docker集群管理工具,后面會寫一篇文章專門介紹Docker的集群管理和 ASP.NET Core的一鍵發布。
本文地址:http://www.cnblogs.com/savorboard/p/dotnetcore-nginx-cache.html
作者博客:Savorboard
歡迎轉載,請在明顯位置給出出處及鏈接
文章列表
![]() |
不含病毒。www.avast.com |