1. 程式人生 > 實用技巧 >asp.net core2 mvc 基礎教程--快取

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();
}

注:

  1. 必須使用非 VS 除錯啟動的瀏覽器開啟頁面才能測試 Response 快取效果
  2. 重新整理頁面時 Response 快取不會起效
  3. Response 快取中介軟體的相關內容請參考官方文件

壓縮

壓縮傳輸的資料。通常針對 1K 以上的資料。

services.AddResponseCompression();//註冊壓縮服務
app.UseResponseCompression();

詳細內容參考官方文件:Response compression in ASP.NET Core