首页 > 其他分享 >.Net Core WebAPI 缓存

.Net Core WebAPI 缓存

时间:2023-12-29 23:11:22浏览次数:48  
标签:WebAPI Core 缓存 浏览器 请求 过期 查询 Net public

Asp.Net Core WebAPI 缓存

 

一、缓存

缓存指在中间层中存储数据的行为,该行为可使后续数据检索更快。 从概念上讲,缓存是一种性能优化策略和设计考虑因素。 缓存可以显著提高应用性能,方法是提高不常更改(或检索成本高)的数据的就绪性。

二、RFC9111

在最新的缓存控制规范文件RFC9111中,详细描述了浏览器缓存和服务器缓存控制的规范,其中有一个最重要的响应报文头Cache-Control

该报文头的设置会影响我们的缓存,包括浏览器端和服务端。

RFC911:https://www.rfc-editor.org/rfc/rfc9111#name-cache-control

image

三、网页端缓存

Cache-Control中,如果设置max-age=10,则表示告诉浏览器缓存10s,而为什么浏览器要认这个表示呢,就是上面我们说的前后端都要根据RFC标准规范去实现,就是硬件的统一插口,不然其他生成出来的就用不了。

那么在Asp.net Core 中只需要在接口上打上ResponseCacheAttribute并设置max-age的时间即可。

首先建一个Asp.Net Core WebAPI 项目,写一个获取学生的Get接口。

image

namespace WebAPI_Cache.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class CacheController : ControllerBase
    {

        public CacheController()
        {

        }

        [HttpGet]
        public ActionResult<Student> GetStudent()
        {

            return new Student()
            {
                Id = 1,
                Name = "Test",
                Age = Random.Shared.Next(0, 100),
            };
        }
    }
}
namespace WebAPI_Cache.Model
{
    public class Student
    {
        public int Id { get; set; }
        public string? Name { get; set; }
        public int Age { get; set; }
    }
}

在接口中我返回Studentage为1-100的随机数。启动项目测试,短时间内两次调用返回的age不一样

第一次age:

image

第二次age:

image

当我在接口方法打上[ResponseCache(Duration = 10)],再次调用接口返回的信息可以看到已经有了cache-control: public,max-age=10的Header。

image

并且我在10秒内的请求,只有第一次请求过服务器,其他都是从缓存中取的,查看edge浏览器网络访问如下:

image

四、服务器缓存

网页端缓存是放在浏览器端的,对于单点请求会有用,但是如果是多个不同前端请求呢。这个时候我们可以将缓存放置在后端服务中,在ASP.NET Core 中配置响应缓存中间件。

在 Program.cs中,将响应缓存中间件服务 AddResponseCaching 添加到服务集合,并配置应用,如果使用 CORS 中间件时,必须在 UseResponseCaching 之前调用 UseCors。

如果header包含 Authorization,Set-Cookie 标头,也不会缓存,因为这些用户信息缓存会引起数据混乱。

image

然后对于我们需要服务器缓存的接口打上ResponseCache属性,和设置浏览器缓存一样,还有其他参数可设置。我们通过两个进程来测试,一个用浏览器swagger,一个用postman,可以看到两个请求的age都是等于18的。所以可以确定服务器端确实存在缓存。

image

但是在用postman测试的时候记得在settings里面把Send no-cache header勾掉,如果不去掉,发送的时候就会在请求头里面包含Cache-Control:no-cache,这样服务端即便有缓存也不会使用缓存。

image

对于浏览器端相当于禁用缓存,如果禁用了缓存,发送的请求头也会带上Cache-Control:no-cache,服务端看到no-cache 后便不会再使用缓存进行响应。

而这个约定就是RFC9111的规范,所以这个后端缓存策略比较鸡肋,如果用户禁用缓存就没用了,因此我们还可以使用内存缓存。

五、内存缓存

内存缓存基于 IMemoryCache。 IMemoryCache 表示存储在 Web 服务器内存中的缓存。

  • 首先Nuget安装包
Install-Package Microsoft.Extensions.Caching.Memory
  • 在Program.cs中添加依赖
builder.Services.AddMemoryCache();
  • 缓存数据
    我添加一个Post方法模拟id查询Student

image

这样我就将数据缓存到了内存,可以设置缓存的绝对过期时间,也可以设置滑动过期,稍后我们会看到过期策略的使用。

六、缓存击穿

缓存击穿是指热点key在某个时间点过期的时候,而恰好在这个时间点对这个Key有大量的并发请求过来,或者是查询了不存在的数据,缓存里面没有,从而大量的请求打到数据库上形成数据库压力。

上面内存缓存中的写法我们可以看到,如果查询缓存等于null就会再去查询数据(我这里只是模拟,没有去写真的数据库查询),如果这样暴力请求攻击就会有问题。

对于这个问题我们可以使用ImemoryCacheGetOrCreate方法,当然它还有异步方式。通过该方法传入缓存的key和func 委托方法返回值来进行查询并缓存,如果没查询到返回的null也会存储在缓存中,防止恶意查询不存在的数据。

        [HttpPost]
        public ActionResult<Student> GetStudent2(int id)
        {
            //查询并创建缓存
            var student = _memoryCache.GetOrCreate("student_" + id, t =>
            {
                t.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(20);
                //模拟只有id=1有数据
                if (id == 1)
                {
                    return new Student()
                    {
                        Id = 1,
                        Name = "Test",
                        Age = Random.Shared.Next(0, 100),
                    };
                }
                else
                {
                    //其他的返回空,但是空值也会缓存,比如查询 id=2,id=3 都会缓存
                    return null;
                }

            });
            if (student == null)
            {
                return NotFound("未找到");
            }
            else
            {
                return student;
            }
        }

七、缓存雪崩

缓存雪崩是指缓存中数据大批量到过期时间,导致所有请求都会去查数据库,而查询数据量巨大,引起数据库压力过大甚至down机。

对于雪崩情况我们对缓存的策略主要是设置过期时间,部分不重要的站点,比如新闻网站我们将绝对过期时间AbsoluteExpiration设置的久一点。

对于要一定灵活性,能在请求不频繁的时候进行失效以更新数据的,我们可以用滑动过期时间,就是如果频繁请求就一值滑动过期时间。

当然为了避免滑动时间一直不过期,还可以两种方式混合使用。上面的例子,我们设置绝对过期时间是20秒,我们将滑动过期设置5秒,在5秒内有持续访问就一直续命,直到20秒绝对过期。

那么如果没人访问,在5秒后就过期了,这样数据下次访问也能及时查询最新数据。

image

八、分布式缓存

有了上面的缓存方案,对付一些小的简单业务系统完全够用了,但是如果你是分布式部署服务,那么像内存缓存访问的数据就是单个服务器的缓存。

你可能需要多个服务器的请求之间保持一致、在进行服务器重启和应用部署后仍然有效、不使用本地内存等情况。

这个时候我们可以使用第三方缓存,比如memecache,Redis等。Asp.Net Core 使用 IDistributedCache 接口与缓存进行交互。

  • NuGet安装包
Install-Package Microsoft.Extensions.Caching.StackExchangeRedis
  • 在 Program.cs 中注册 IDistributedCache 实现
    image

Configuration: 为连接配置。
InstanceName: 为存储键前缀。

编写测试方法GetStuden3

image

IDistributedCache 接受字符串键并以 byte[] 数组的形式添加或检索缓存项,所以数据是以byte[]形式访问,但是扩展了一个string类型的方法可以进行使用,我这里用字符串进行操作。

以上这些就是关于asp.net core 当中使用缓存的重要点和基础使用方法,详细参数和文档可参看官方文档:ASP.NET Core 中的缓存概述

标签:WebAPI,Core,缓存,浏览器,请求,过期,查询,Net,public
From: https://www.cnblogs.com/Leo_wl/p/17935844.html

相关文章

  • ASP.NET Core 6(.NET 6) Program.cs中使用读取appsettings.json配置文件
    ​ 在ASP.NETCore6(.NET6)中,可以使用Json格式的appsettings.json配置文件来配置应用程序,用于存储应用程序的配置信息,方便我们灵活的配置应用程序。本文主要介绍Program.cs中,使用读取appsettings.json配置文件的方法,以及相关的示例代码。1、通过配置实体类的方式1)配置实体......
  • JMU-net-security-lesson-design WriteUp
    0.内网信息主机名(域名)IP端口www.qianxin.com172.10.10.10080news.qianxin.com172.10.10.10280blog.qianxin.com172.10.10.10180mysql192.168.100.403306redis192.168.100.1016379oa-web192.168.100.10022、801.登录www.qianxin.co......
  • 使用Jenkins和单个模板部署多个Kubernetes组件
    前言在持续集成和部署中,我们通常需要部署多个实例或组件到Kubernetes集群中。通过Jenkins的管道脚本,我们可以自动化这个过程。在本文中,我将演示如何使用JenkinsPipeline及单个YAML模板文件(.tpl)来部署多个类似的Kubernetes组件,而不需要为每个组件提供单独的模板文件。问题背景参......
  • Kubernetes-集群Rook-Ceph快照
    部署条件Rookofficiallysupportsv1snapshotsforKubernetesv1.20+.Installthesnapshotcontrollerandsnapshotv1CRDasrequired.Moreinfocanbefoundhere.安装快照控制器和CRD:安装快照CRD:gitclonehttps://github.com/kubernetes-csi/external-snapshotter.git......
  • .net core 单元测试项目搭建
    背景和目的为了提高系统稳定性,通常我们有两方面的计划:黑盒测试:自动化测试,以接口来主体,通过控制入参的形式,检验出参,来模拟用户在线上的实际业务;(可以覆盖绝大部分的业务)白盒测试:单元测试,以关键逻辑方法为主体,通过控制入参的形式,检验数据变化,站在开发的角度上来模拟实际调用(可以......
  • MMGCN: Multi-modal Graph Convolution Network for Personalized Recommendation of
    目录概符号说明MMGCN代码WeiY.,WangX.,NieL.,HeX.,HongR.andChuaT.MMGCN:Multi-modalgraphconvolutionnetworkforpersonalizedrecommendationofmicro-video.MM,2019.概推荐领域里比较早的多模态方法.符号说明\(\mathcal{U}\),userset;\(\mathc......
  • Taurus .Net Core 微服务开源框架:Admin 插件【4-8】 - 配置管理-Mvc【Plugin-Limit 接
    前言:继上篇:Taurus.NetCore微服务开源框架:Admin插件【4-7】-配置管理-Mvc【Plugin-Metric接口调用次数统计】本篇继续介绍下一个内容:1、系统配置节点:Mvc- Plugin-Limit接口访问限制、IP限制、Ack限制:配置界面如下:限制目前提供以下三个类别的限制:1、Rate访......
  • .NET批量更新两种方式性能对比
    数据库MySql,.NET7,ORMEF使用新的批量更新:publicasyncTaskUpdateManyAsync(stringurl,stringdata){await_dbContext.TestDb.Where(a=>a.Url!=null&&a.Url.Equals(url)).ExecuteUpdateAsync(a=>a.SetProperty(u=>u.TestDate,data));returntrue......
  • 在不受支持的 Mac 上安装 macOS Sonoma (OpenCore Legacy Patcher)
    在不受支持的Mac上安装macOSSonoma、Ventura、Monterey、BigSur(OpenCoreLegacyPatcher)InstallmacOSonunsupportedMacs作者主页:sysin.orgmacOSSonoma正式版已发布,OpenCoreLegacyPatcherv1.0.0版本已支持。随着OpenCoreLegacyPatcher1.0.0的发布,OLP项目组......
  • linux下java调用netcore程序
    代码备份仅供参考自述文件#JavaCallCSharpJavacallC#libbuildwith.NETCORE2.0viaC++aswraperThecodeisbasedon[examplefromcoreCLR](https://github.com/dotnet/coreclr/tree/master/src/coreclr/hosts/unixcoreruncommon)JavausingJNItocallC++......