一、缓存

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

二、RFC9111

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

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

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

三、网页端缓存

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

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

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

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:

第二次age:

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

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

四、服务器缓存

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

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

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

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

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

对于浏览器端相当于禁用缓存,如果禁用了缓存,发送的请求头也会带上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

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

六、缓存击穿

缓存击穿是指热点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秒后就过期了,这样数据下次访问也能及时查询最新数据。

八、分布式缓存

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

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

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

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

Configuration: 为连接配置。

InstanceName: 为存储键前缀。

编写测试方法GetStuden3

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

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

.net 温故知新【13】:Asp.Net Core WebAPI 缓存的更多相关文章

  1. Asp.Net Core WebApi学习笔记(四)-- Middleware

    Asp.Net Core WebApi学习笔记(四)-- Middleware 本文记录了Asp.Net管道模型和Asp.Net Core的Middleware模型的对比,并在上一篇的基础上增加Mid ...

  2. Asp.net core WebApi 使用Swagger生成帮助页实例

    最近我们团队一直进行.net core的转型,web开发向着前后端分离的技术架构演进,我们后台主要是采用了asp.net core webapi来进行开发,开始每次调试以及与前端人员的沟通上都存在这效 ...

  3. 零基础ASP.NET Core WebAPI团队协作开发

    零基础ASP.NET Core WebAPI团队协作开发 相信大家对“前后端分离”和“微服务”这两个词应该是耳熟能详了.网上也有很多介绍这方面的文章,写的都很好.我这里提这个是因为接下来我要分享的内容 ...

  4. asp.net core webapi之跨域(Cors)访问

    这里说的跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被当作 ...

  5. ASP.NET Core WebAPI 开发-新建WebAPI项目

    ASP.NET Core WebAPI 开发-新建WebAPI项目, ASP.NET Core 1.0 RC2 即将发布,我们现在来学习一下 ASP.NET Core WebAPI开发. 网上已经有泄 ...

  6. Asp.net Core WebApi 使用Swagger做帮助文档,并且自定义Swagger的UI

    WebApi写好之后,在线帮助文档以及能够在线调试的工具是专业化的表现,而Swagger毫无疑问是做Docs的最佳工具,自动生成每个Controller的接口说明,自动将参数解析成json,并且能够在 ...

  7. Asp.net core WebApi 使用Swagger生成帮助页

    最近我们团队一直进行.net core的转型,web开发向着前后端分离的技术架构演进,我们后台主要是采用了asp.net core webapi来进行开发,开始每次调试以及与前端人员的沟通上都存在这效 ...

  8. ASP.Net Core WebApi几种版本控制对比

    版本控制的好处: (1)助于及时推出功能, 而不会破坏现有系统. (2)它还可以帮助为选定的客户提供额外的功能. API 版本控制可以采用不同的方式进行控制,方法如下: (1)在 URL 中追加版本或 ...

  9. ASP.NET Core WebApi 返回统一格式参数(Json 中 Null 替换为空字符串)

    相关博文:ASP.NET Core WebApi 返回统一格式参数 业务场景: 统一返回格式参数中,如果包含 Null 值,调用方会不太好处理,需要替换为空字符串,示例: { "respon ...

  10. ASP.NET Core WebApi使用Swagger生成api说明文档看这篇就够了

    引言 在使用asp.net core 进行api开发完成后,书写api说明文档对于程序员来说想必是件很痛苦的事情吧,但文档又必须写,而且文档的格式如果没有具体要求的话,最终完成的文档则完全取决于开发者 ...

随机推荐

  1. 三 APPIUM Android自动化 测试初体验(转)

    1.创建一个maven项目 成功新建工程: 编辑pom.xml,在<dependencies></dependencies>下添加appium相关依赖: <depende ...

  2. SpringBoot对接OpenAI

    SpringBoot对接OpenAI 随着人工智能技术的飞速发展,越来越多的开发者希望将智能功能集成到自己的应用中,以提升用户体验和应用的功能.OpenAI作为一家领先的人工智能公司,提供了许多先进的 ...

  3. 从0开始,Cloudreve开源云盘在centos7上部署,并可在外网访问(资料整合)

    全程我在网络上收集这些资料,太零碎了,每一个一看就会,一动手就废,而且很多都不能实现我白嫖的梦想 我一个人折腾了快一周,现在可以正常访问手机电脑多端访问 给个赞再走吧 此处为没有公网IP(回去折腾你家 ...

  4. [Lua] IT技术熟练度生成器 | 根据IT活动记录生成md表格 | 自创

    IT技术熟练度 v1.0 为衡量个人能力水平自创的一套评分机制,根据时间.代码行数.基础理论三个变量生成.最近在学lua,正好练下基本功.效果可见 个人介绍 | 代码统计 - 小能日记 - 博客园 ( ...

  5. 错过这5大AI绘画提示词平台,你会拍大腿!别问,直接收藏!

    如今,AI绘画已经不再是简单的技术展示,而是逐渐转向了商业化的运营. 有的人利用AI生成的图片,再结合ChatGPT产生的文字,然后在平台上发布,这样就可以赚取平台的广告费. 其他一些变现操作参考之前 ...

  6. Codeforces 1254B1 - Send Boxes to Alice (Easy Version)

    题意 有\(n(1\leq n\leq 10^5)\)个盒子,每个盒子有\(a_i(0\leq a_i \leq 1)\)个糖果,你每一次可以将第\(i\)个盒子里的糖果放到第\(i-1\)或\(i+ ...

  7. VMware上安装Centos7

    一.下载Centos镜像 国内镜像网站: 清华大学:清华大学开源软件镜像站 | Tsinghua Open Source Mirror 阿里云:阿里巴巴开源镜像站-OPSX镜像站-阿里云开发者社区 ( ...

  8. 2.14 PE结构:地址之间的转换

    在可执行文件PE文件结构中,通常我们需要用到地址转换相关知识,PE文件针对地址的规范有三种,其中就包括了VA,RVA,FOA三种,这三种该地址之间的灵活转换也是非常有用的,本节将介绍这些地址范围如何通 ...

  9. asp.net mvc Core 网页错误提示:An unhandled exception occurred while processing the request.处理请求时发生未处理的异常。

    网页错误提示: An unhandled exception occurred while processing the request. InvalidOperationException: The ...

  10. C/C++基础——引用与指针有什么区别?C++中输入输出加速

    文章目录 1 引用与指针有什么区别? 2 C++中输入输出加速 tie sync_with_stdio 应用 1 引用与指针有什么区别? 指针和引用都是地址的概念,指针指向一块内存,它的内容是所指内存 ...