• 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

  • 相关阅读:
    587 模块化开发 CommonJS规范:exports,module.exports,require细节,模块加载顺序,AMD和CMD规范
    img标签到底是行内元素还是块级元素
    File、Blob、dataURL 和 canvas 的应用与转换
    正则表达式
    什么是AVIF?如何在你的网站上使用AV1格式图像
    前端性能优化之图片懒加载
    padding-top的百分比值参考对象竟是父级元素的宽度
    自动增长Textareas的最干净技巧
    用纯css模拟下雪的效果
    了解CSS基本用法和选择器知识
  • 原文地址:https://www.cnblogs.com/cqqinjie/p/13322148.html
Copyright © 2020-2023  润新知