当前位置: 首页 > news >正文

.net core 客户端缓存、服务器端响应缓存、服务器内存缓存

前言:什么是缓存
缓存<Caching是系统优化中简单又有效的工具,投入小收效大。数据库中的索引等简单有效的优化功能本质上都是缓存。

一.客户端响应缓存

cache-control
1、RFC7324是HTTP协议中对缓存进行控制的规范,其中重要的是cache-control这个响应报文头。服务器如果返回cache-control:max-age=60,则表示服务器指示浏览器端“可以缓存这个响应内容60秒”。
2、我们只要给需要进行缓存控制的控制器的操作方法添加ResponseCacheAttribute这个Attribute, ASP.NET Core会自动添加cache-control报文头。


 3、验证:编写一个返回当前时间的Action方法。分别加和不加ResponseCacheAttribute看区别。也F12看看Network

  [ResponseCacheAttribute(Duration =60)]
        [HttpGet]
        public string getDatetime()
        {


            return DateTime.Now.ToString();
        }

 写的这个action就是让浏览器帮助缓存60秒,这60秒获取的数据一直都是第一次获取的值。

二.服务器端响应式缓存

Response Caching Middleware
1、如果ASP.NET Core中安装了“响应缓存中间件”,那么ASP.NETCore不仅会继续根据[ResponseCache]设置来生成cache-control响应报文头来设置客户端缓存,而且服务器端也会按照[ResponseCache]的设置来对响应进行服务器端缓存。和客户端端缓存的区别?来自多个不同客户端的相同请求。


2、“响应缓存中间件”的好处:对于来自不同客户端的相同请求或者不支持客户端缓存的客户端,能降低服务器端的压力。

 用法:确保app.UseCors()写在app.UseResponseCaching();之前

app.UseResponseCaching();写在app.MapControllers();

3. 写一个简单的api获取当前时间

  [ResponseCacheAttribute(Duration =60)]
        [HttpGet]
        public string getDatetime()
        {


            return DateTime.Now.ToString();
        }

然后我们打开两个浏览器请求api 

 发现时间居然相同,说明都获取到了服务器缓存的数据。

服务器端响应缓存很鸡肋
1、无法解决恶意请求给服务器带来的压力。
2、服务器端响应缓存还有很多限制,包括但不限于:响应状态码为200的GET或者HEAD响应才可能被缓存;报文头中不能含有Authorization、Set-Cookie等。
3、不怪他,honor RFC7234. It's a feature, not a bug.4、怎么办?采用内存缓存、分布式缓存等。

三、内存缓存(In-memory cache )

简介

  • 1、把缓存数据放到应用程序的内存。内存缓存中保存的是系列的键值对,就像Dictionary类型一样。
  • 2、内存缓存的数据保存在当前运行的网站程序的内存中,是和进程相关的。因为在Web服务器中,多个不同网站是运行在不同的进程中的,因此不同网站的内存缓存是不会互相干扰的,而且网站重启后,内存缓存中的所有数据也就都被清空了。

内存缓存用法
1、启用:builder.Services.AddMemoryCache()


2、注入IMemoryCache接口,查看接口的方法:TryGetValueRemoveSetGetOrCreateGetOrCreateAsync

CreateEntry(Object)

在缓存中创建或覆盖项。

Remove(Object)

删除与给定键关联的对象。

TryGetValue(Object, Object)

获取与此键关联的项(如果存在)。

3、用GetOrCreateAsync讲解

public async Task<Book[]> GetBooks(){
logger.LogInformation("开始执行GetBooks");

var items = await memCache.GetOrCreateAsync("AllBooks", async(e) =>{

logger.LogInformation("从数据库中读取数据");
return await dbCtx.Books.ToArrayAsync();

});

logger.LogInformation("把数据返回给调用者");return items;

}
Hisense

内存缓存过期时间(刷新时间)设置

1、如果只考虑缓存基本的使用的那缓存不会过期,除非重启服务器。

2、解决方法:在数据改变的时候调用Remove或者Set来删除或者修改缓存(优点:及时);

    过期时间(只要过期时间比较短,缓存数据不一致的情况也不会持续很长时间。)

3、两种过期时间策略:绝对过期时间、滑动过期时间。它们分别是什么?

绝对过期时间:AbsoluteExpirationRelativeToNow获取缓存数据后,会随着过期时间过期而过期

滑动过期时间:SlidingExpiration 在获取缓存数据后“的过期时间内”再次获取缓存中的数据的话就会刷新过期时间(延长时间),如果获取缓存数据之后的过期时间中一直没有获取的话,缓存就会被清除掉。

过期策略:

1、GetOrCreateAsync()方法的回调方法中有一个ICacheEntry类型的参数,通过ICacheEntry对当前的缓存项做设置。

2、AbsoluteExpirationRelativeToNow用来设定缓存项的绝对过期时间。SlidingExpiration设置滑动过期时间。

两种过期时间策略混用

使用滑动过期时间策略,如果一个缓存项一直被频繁访问,那么这个缓存项就会一直被续期而不过期。可以对一个缓存项同时设定滑动过期时间和绝对过期时间,并且把绝对过期时间设定的比滑动过期时间长,这样缓存项的内容会在绝对过期时间内随着访问被滑动续期,但是一旦超过了绝对过期时间,缓存项就会被删除。

缓存穿透的问题

普通用户一般不会接口发送一些缓存不存在的数据key,但是有一些恶意用户就不一样了,他们会一直发送缓存没有数据库也没有的数据,这就会造成缓存形同虚设,加大了程序的压力。

string cacheKey = "Book" + id;//缓存键
Book? b = memCache.Get<Book?>(cacheKey);
if(b==null)//如果缓存中没有数据
{
	//查询数据库,然后写入缓存
	b = await dbCtx.Books.FindAsync(id);
	memCache.Set(cacheKey, b);
}

1、解决方法:把“查不到”也当成一个数据放入缓存。

2、我们用GetOrCreateAsync方法即可不使用set,因为它会把null值也当成合法的缓存值。

string cacheKey = "Book" + id;

var book = await memCache.GetOrCreateAsync(cacheKey, async (e) => {

  var b = await dbCtx.Books.FindAsync(id);

  logger.LogInformation("数据库查询:{0}",b==null?"为空":"不为空");

  return b;

});

logger.LogInformation("Demo5执行结束:{0}", book == null ? "为空" : "不为空");

相关文章:

  • python+vue+elementui高校学生成绩补考通知系统django
  • 代码坏味道与重构之霰弹式修改和依恋情结
  • 【web-渗透测试方法】(15.6)测试基于输入的漏洞
  • Java高频面试题【基础篇】
  • meta理解及使用
  • 论语第二篇-为政
  • 50个例子学Python(一)
  • leetcode竞赛:20220904周赛
  • 算法小讲堂之B树和B+树(浅谈)|考研笔记
  • 【02】Camunda系列-扩展案例-用户任务、网关、决策自动化
  • J. Counting Trees (树,卡特兰数)
  • 77-Java的Set系列集合、Collection体系的总结
  • this指哪去了
  • 算法----二维区域和检索 - 矩阵不可变(Kotlin)
  • 向Visual Studio Code导入ST项目
  • CEF与代理
  • Sublime text 3 3103 注册码
  • thinkphp5.1 easywechat4 微信第三方开放平台
  • 给第三方使用接口的 URL 签名实现
  • 规范化安全开发 KOA 手脚架
  • 前嗅ForeSpider教程:创建模板
  • 深入 Nginx 之配置篇
  • 实现菜单下拉伸展折叠效果demo
  • 视频flv转mp4最快的几种方法(就是不用格式工厂)
  • 数据仓库的几种建模方法
  • 微信支付JSAPI,实测!终极方案
  • 一道闭包题引发的思考
  • UI设计初学者应该如何入门?
  • 好程序员大数据教程Hadoop全分布安装(非HA)
  • ​HTTP与HTTPS:网络通信的安全卫士
  • # 20155222 2016-2017-2 《Java程序设计》第5周学习总结
  • # Python csv、xlsx、json、二进制(MP3) 文件读写基本使用
  • #Lua:Lua调用C++生成的DLL库
  • #我与Java虚拟机的故事#连载09:面试大厂逃不过的JVM
  • #我与Java虚拟机的故事#连载19:等我技术变强了,我会去看你的 ​
  • $HTTP_POST_VARS['']和$_POST['']的区别
  • (二)pulsar安装在独立的docker中,python测试
  • (二)Pytorch快速搭建神经网络模型实现气温预测回归(代码+详细注解)
  • (论文阅读40-45)图像描述1
  • (强烈推荐)移动端音视频从零到上手(下)
  • (十二)devops持续集成开发——jenkins的全局工具配置之sonar qube环境安装及配置
  • (转)c++ std::pair 与 std::make
  • (转)重识new
  • (最优化理论与方法)第二章最优化所需基础知识-第三节:重要凸集举例
  • ***汇编语言 实验16 编写包含多个功能子程序的中断例程
  • .NET CORE 2.0发布后没有 VIEWS视图页面文件
  • .NET Core WebAPI中封装Swagger配置
  • .NET Core6.0 MVC+layui+SqlSugar 简单增删改查
  • .Net CoreRabbitMQ消息存储可靠机制
  • .NET 应用启用与禁用自动生成绑定重定向 (bindingRedirect),解决不同版本 dll 的依赖问题
  • .NET(C#、VB)APP开发——Smobiler平台控件介绍:Bluetooth组件
  • .NET开源项目介绍及资源推荐:数据持久层
  • .NET命名规范和开发约定
  • .Net通用分页类(存储过程分页版,可以选择页码的显示样式,且有中英选择)
  • .NET文档生成工具ADB使用图文教程