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>

分布式缓存

 

image.png

 

特点:

  • 无需 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    镜像名

image.png

 

docker ps 查看运行状态:

image.png

 

docker run -it --link my-redis:my-redis --rm redis redis-cli -h my-redis -p 6379

image.png

  • -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:

image.png

 

打开 NuGet 安装 Redis:

image.png

 

在 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

posted @ 2020-07-16 13:24  学做flutter的小菜鸡  阅读(173)  评论(0编辑  收藏  举报