asp.net core2 mvc 基礎教程--快取
快取簡介
快取的優點:
- 提高網站的訪問速度
- 適用於不易改變的資料
快取的缺點:
- 仔細規劃
- 奇怪的副作用
快取的地點:
- 伺服器(單伺服器)
- 快取伺服器(多伺服器)
- 客戶端
In-Memory 快取
- 最簡單的
- IMemoryCache
- 適用於 Sticky Session(粘滯的會話)
- 適用於任何型別的物件
Sticky Session:In-Memory 快取儲存在 Web 伺服器的記憶體中,只有本伺服器能訪問到。當 Web 應用部署在多伺服器時,需保證使用者訪問的伺服器就是之前進行快取的伺服器。
通過 services.AddMemoryCache();
在 Startup ConfigureServices 中啟用記憶體快取。
MemoryCacheEntryOptions:
- Absolute expiration time 絕對過期時間
- Sliding expiration time:每次請求訪問快取後,都會重置快取的過期時間
- 快取優先順序
- PostEvictionDelegate:快取資料被清除時呼叫該委託
在 AlbumController 中使用 In-Memory Cache:
// GET: Album public async Task<ActionResult> Index() { if (!_memoryCache.TryGetValue( CacheEntryConstants.AlbumsOfToday,out List<Album> cachedAlbums)) { cachedAlbums = await _albumService.GetAllAsync(); var cacheEntryOptions = new MemoryCacheEntryOptions() .SetSlidingExpiration(TimeSpan.FromSeconds(30)); cacheEntryOptions.RegisterPostEvictionCallback(FillCache, this); _memoryCache.Set(CacheEntryConstants.AlbumsOfToday, cachedAlbums, cacheEntryOptions); }return View(cachedAlbums); } private void FillCache(object key, object value, EvictionReason reason, object state) { // 不具體實現 Console.WriteLine("Cache entry is evicted!"); }
Cache Tag Helper
格式:
<cache>@await Component.InvokeAsync("xxx")</cache>
- 伺服器端
- 實際使用 IMemoryCache,也要求 Sticky Session
屬性:
- enabled
- expires-on:絕對過期時間
- expires-after
- expires-sliding
- vary-by-header:如果請求的 header 變了,快取就需要重新整理
- vary-by-query
- vary-by-route
- vary-by-cookie
- vary-by-user
- vary-by
- priority
示例:
<cache expires-after="@TimeSpan.FromSeconds(30)"> @await Component.InvokeAsync("InternetStatus") </cache>
分散式快取
特點:
- 無需 Sticky Session
- 可擴充套件
- Web 伺服器重啟不會影響快取
- 效能更好
介面與常用方法:
- IDistributedCache
- Get, GetAsync
- Set, SetAsync
- Refresh, RefreshAsync
- Remove, RemoveAsync
型別:
- 分散式 Memory Cache(僅適合開發時使用)
- 分散式 Sql Server Cache
- 分散式 Redis Cache(推薦)
Redis Cache
通過 Docker 安裝 Redis:docker pull redis
如果拉取速度很慢,推薦使用阿里雲的映象加速器(簡單教程)。
執行容器:docker run --name my-redis -d -p 6379:6379 redis
命名 暴露埠 6379 映象名
docker ps
檢視執行狀態:
docker run -it --link my-redis:my-redis --rm redis redis-cli -h my-redis -p 6379
- -it:interactive
- --link my-redis:連結到 my-redis
- :my-redis:在裡面的名也叫 my-redis
- --rm:容器停止後就刪除容器
- redis:映象是 redis
- redis-cli:執行裡面的 redis-cli 程式
- -h my-redis:hostname 叫 my-redis
- -p 6379:埠 6379
測試 redis:
開啟 NuGet 安裝 Redis:
在 Startup 中配置 Redis:
services.AddDistributedRedisCache(options => { options.Configuration = "localhost"; options.InstanceName = "redis-for-albums"; });
在 AlbumController 中使用 Redis:
private readonly ILogger<AlbumController> _logger; private readonly IDistributedCache _distributedCache; private readonly IAlbumService _albumService; private readonly HtmlEncoder _htmlEncoder; public AlbumController( IAlbumService albumService, HtmlEncoder htmlEncoder, ILogger<AlbumController> logger, IDistributedCache distributedCache) { _albumService = albumService; _htmlEncoder = htmlEncoder; _logger = logger; _distributedCache = distributedCache; } // GET: Album public async Task<ActionResult> Index() { List<Album> cachedAlbums; var cachedAlbumsString = _distributedCache.Get(CacheEntryConstants.AlbumsOfToday); if (cachedAlbumsString == null) { cachedAlbums = await _albumService.GetAllAsync(); var serializedString = JsonConvert.SerializeObject(cachedAlbums); byte[] encodedAlbums = Encoding.UTF8.GetBytes(serializedString); var cacheEntryOptions = new DistributedCacheEntryOptions() .SetSlidingExpiration(TimeSpan.FromSeconds(30)); _distributedCache.Set(CacheEntryConstants.AlbumsOfToday, encodedAlbums, cacheEntryOptions); } else { byte[] encodedAlbums = _distributedCache.Get(CacheEntryConstants.AlbumsOfToday); var serializedString = Encoding.UTF8.GetString(encodedAlbums); cachedAlbums = JsonConvert.DeserializeObject<List<Album>>(serializedString); } return View(cachedAlbums); }
Response 快取
- 基於 Header
- 客戶端快取
- 使用 ResponseCache Attribute
引數:
- Location
- Duration
- NoStore
- VaryByHeader
在配置 MVC 中介軟體時配置 Response 快取:
services.AddMvc(options => { options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()); options.Filters.Add<LogResourceFilter>(); options.CacheProfiles.Add("Default",new CacheProfile { Duration = 60 }); options.CacheProfiles.Add("Never", new CacheProfile { Location = ResponseCacheLocation.None, NoStore = true }); });
Response 快取的使用:
// 手動配置 [ResponseCache(Duration = 30, Location = ResponseCacheLocation.Client)] public IActionResult Index() { _logger.LogInformation(MyLogEventIds.HomePage, "Visiting Home Index ..."); return View(); } // 通過指定 CacheProfile 進行配置 [ResponseCache(CacheProfileName = "Default")] public IActionResult Privacy() { return View(); }
注:
- 必須使用非 VS 除錯啟動的瀏覽器開啟頁面才能測試 Response 快取效果
- 重新整理頁面時 Response 快取不會起效
- Response 快取中介軟體的相關內容請參考官方文件
壓縮
壓縮傳輸的資料。通常針對 1K 以上的資料。
services.AddResponseCompression();//註冊壓縮服務
app.UseResponseCompression();
詳細內容參考官方文件:Response compression in ASP.NET Core。