.NET Core ResponseCache【缓存篇(一)】

一、前言

  源码

   1、最近一直在看项目性能优化方式,俗话说的好项目优化第一步那当然是添加缓存,我们的项目之所以卡的和鬼一样,要么就是你的代码循环查询数据库(这个之前在我们的项目中经常出现,现在慢慢在修正)或者代码做了很多不该做的事情。这个时候就可以引入我们的缓存了。(只要你的代码不是写的特别差,比如之前实习的我)。

  2、缓存主要分为两种 客户端(浏览器缓存)、服务端缓存。当我们的数据不需要及时返回的时候,可以考虑将页面缓存到客户的浏览器中进行保存,在一定的时间内访问直接读取浏览器缓存的信息。我们通过设置HTTP的响应头 Cache-Control 来完成页面存储到浏览器缓存中如下所示:

 二、客户端(浏览器缓存)

  1、在老的版本的MVC里面,有一种可以缓存视图的特性(OutputCache),可以保持同一个参数的请求,在N段时间内,直接从mvc的缓存中读取,不去走视图的逻辑。

//老版本的.NET 做法
[OutputCache(Duration =20)]//设置过期时间为20秒public ActionResult ExampleCacheAction(){var  time=DateTime.Now.ToString("yyyy年MM月dd日 HH时mm分ss秒");ViewBag.time= time;return View();}

  2、在.Net core 中就没有(OutputCache)了,使用的是(ResponseCache)特性。官方文档上称:响应缓存可减少客户端或代理对 web 服务器的请求数。 响应缓存还可减少量工作的 web 服务器执行程序生成响应。 响应缓存由标头,指定你希望客户端、 代理和缓存响应的中间件如何控制。

 /*Duration 代表缓存持续时间(秒)至少1秒VaryByHeader 设置vary 请求头信息使用vary头有利于内容服务的动态多样性。例如,使用Vary: User-Agent头,缓存服务器需要通过UA判断是否使用缓存的页面。Location 缓存位置None 报头设置为“no-cache”不使用缓存Client 只缓存在客户端。设置“Cache-control”标题为“private”。Any 缓存在代理和客户端。设置“Cache-control”标题为“public”。NoStore   缓存中不得存储任何关于客户端请求和服务端响应的内容。每次由客户端发起的请求都会下载完整的响应内容。如果设置为False Duration必须大于0VaryByQueryKeys 可以按照相同页面,不同的参数进行相应的存储CacheProfileName 设置缓存配置文件的值,可以通过设置不同的缓存参数*/[ResponseCache(Duration = 50, VaryByQueryKeys = new string[] { "q","name" })]public IActionResult Index(int q,string name){return View(DateTime.Now);}

  3、通过运行我们可以看到,浏览器多了一个cache-control:public,max-age=50 它的意思是public缓存在代理和客户端。max-age=50代表缓存的时间50秒。

  4、还有一种简单粗暴的实现方式,因为我们知道添加了这个特性只是在响应请求头中添加了一个cache-control:public,max-age=50,那么我们可以也可以直接在请求响应中设置这个请求头就完事了,效果都是一样的。

public IActionResult Index()
{//直接一,简单粗暴,不要拼写错了就好~~Response.Headers[Microsoft.Net.Http.Headers.HeaderNames.CacheControl] = "public, max-age=600";//直接二,略微优雅点//Response.GetTypedHeaders().CacheControl = new Microsoft.Net.Http.Headers.CacheControlHeaderValue()//{//    Public = true,//    MaxAge = TimeSpan.FromSeconds(600)//};return View();
}

  5、有时候为了统一管理缓存配置,我们可以将缓存配置提前写到配置中,使用名字进行调用。[ResponseCache(CacheProfileName ="test")],在Startup中注入视图的时候写入。

//设置一些缓存策略services.AddControllersWithViews(options =>{options.CacheProfiles.Add("default", new CacheProfile{Duration = 60});options.CacheProfiles.Add("test", new CacheProfile{Duration = 30,Location=ResponseCacheLocation.Client});});

  6、[ResponseCache] 参数

    •   Any 缓存在代理和客户端。设置“Cache-control”标题为“public”。

    •   Client 只缓存在客户端。设置“Cache-control”标题为“private”。

    •   None 每次有请求发出时,缓存会将请求发到服务器 ,服务器端会验证请求中所描述的缓存是否过期,若未过期(注:实际就是返回304),则缓存才使用本地缓存副本。报头设置为“no-cache”。

    •   Duration 设置缓存的存储时间(以秒为单位)。设置“Cache-control”中的“max-age”。

    •   Location

    •   NoStore 缓存中不得存储任何关于客户端请求和服务端响应的内容。每次由客户端发起的请求都会下载完整的响应内容。

    •   VaryByHeader 使用vary头有利于内容服务的动态多样性。例如,使用Vary: User-Agent头,缓存服务器需要通过UA判断是否使用缓存的页面。

    •   VaryByQueryKeys 可以按照相同页面,不同的参数进行相应的存储

    •   CacheProfileName 设置缓存配置文件的值,可以通过设置不同的缓存参数

三、服务端缓存

  1、ResponseCache也可以设置服务端缓存,将我们返回的数据存储在服务端中在一定的时间内返回存储的数据,这里我先引入一个案例,有时候我们需要传递不同的参数进行缓存。

     案例:当我们访问的数据带分页参数的时候我们怎么做呢?VaryByQueryKeys前面我们讲了这个,可以根据不同的参数进行缓存,那么我们现在使用看看 

        结果:当我们运行的时候,发现报错了,报错的意思大致是说我们没有使用中间件,但是为什么我这个缓存要使用到中间件呢?其实是因为要区分,我们请求的参数,然后会将我们的数据进行缓存起来,就是实现了服务端缓存。这里的我们就要使用微软提供的中间件了。

 2、我们主要是在Startup中注入services.AddResponseCaching();app.UseResponseCaching();中间件。服务端缓存可以缓存页面数据和API数据,同时如果我们服务端存在数据,也就是缓存命中的情况下,会直接从缓存中取,不会再进入我们的方法。

 public void ConfigureServices(IServiceCollection services){services.AddResponseCaching(options =>{options.UseCaseSensitivePaths = false;options.MaximumBodySize = 1024;options.SizeLimit = 100 * 1024*1024;});}public void Configure(IApplicationBuilder app, IWebHostEnvironment env){app.UseResponseCaching();}

服务端缓存配置如下,当我们配置添加了中间件和注入缓存之后,就可以使用VaryByQueryKeys了。当我们访问一次之后就会将结果缓存到我们的客户端缓存中,和服务端缓存各一份。当我们使用同一个浏览器访问的时候访问的就是客户端缓存信息,当我们切换浏览器访问的时候也不会请求我们的方法,会先进入到我们的中间件中查看是否存在服务端缓存,如果存在就是直接拿缓存进行返回,如果没有就会请求方法返回,然后再将结果进行缓存。

属性

描述

MaximumBodySize

响应正文的最大可缓存大小(以字节为单位)。默认值为 64 * 1024 * 1024 (64 MB)。

SizeLimit

响应缓存中间件的大小限制(以字节为单位)。默认值为 100 * 1024 * 1024 (100 MB)。

UseCaseSensitivePaths

确定是否将响应缓存在区分大小写的路径上。默认值是 false。

 3、对于一些常年不变或比较少变的js,css等静态文件,也可以把它们缓存起来,避免让它们总是发起请求到服务器,而且这些静态文件可以缓存更长的时间!如果已经使用了CDN,这一小节的内容就可以暂且忽略掉了。。。对于静态文件,.NET Core有一个单独的StaticFiles中间件,如果想要对它做一些处理,同样需要在管道中进行注册。UseStaticFiles有几个重载方法,这里用的是带StaticFileOptions参数的那个方法。因为StaticFileOptions里面有一个OnPrepareResponse可以让我们修改响应头,以达到HTTP缓存的效果。

app.UseStaticFiles(new StaticFileOptions
{OnPrepareResponse = context =>{context.Context.Response.GetTypedHeaders().CacheControl = new Microsoft.Net.Http.Headers.CacheControlHeaderValue{Public = true,//for 1 yearMaxAge = System.TimeSpan.FromDays(365)};}
});

四、使用前置条件

  • 请求必须导致服务器响应,状态代码为200(正常)。

  • 请求方法必须为 GET 或 HEAD。

  • 在 Startup.Configure中,响应缓存中间件必须置于需要缓存的中间件之前。

  • Authorization 标头不得存在。

  • Cache-Control 标头参数必须是有效的,并且响应必须标记为 “public” 且未标记为 “private”。

  • 如果 Cache-Control 标头不存在,则 Pragma: no-cache 标头不得存在,因为 Cache-Control 标头在存在时将覆盖 Pragma 标头。

  • Set-Cookie 标头不得存在。

  • Vary 标头参数必须有效且不等于 *。

  • Content-Length 标头值(如果已设置)必须与响应正文的大小匹配。

  • 不使用 IHttpSendFileFeature。

  • Expires 标头和 max-age 和 s-maxage 缓存指令指定的响应不能过时。

  • 响应缓冲必须成功。响应的大小必须小于配置的或默认 SizeLimit。响应的正文大小必须小于配置的或默认的 MaximumBodySize。

  • “请求” 或 “响应” 标头字段中不得存在 “no-store” 指令。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/308682.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[Swagger2]分组和接口注释及小结

分组和接口注释及小结 配置API分组 1、如果没有配置分组,默认是default。通过groupName()方法即可配置分组: Bean public Docket docket(Environment environment) {return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).groupName(&qu…

Asp.Net Core 中的“虚拟目录”

写在前面现在部署Asp.Net Core应用已经不再限制于Windows的IIS上,更多的是Docker容器、各种反向代理来部署。也有少部分用IIS部署的,IIS部署确实是又快又简单,图形化操作三下五除二就可以发布好一个系统了。在过去Asp.Net MVC 项目部署的时候…

[mybatis]缓存_缓存有关的设置以及属性

缓存有关的设置以及属性 全局配置中的设置 和缓存有关的设置/属性1.cacheEnabletrue;false;关闭缓存(二级缓存关闭)(一级缓存一直可用的)2.每个select标签都有useCache“true”; false;不使用缓存(一级缓存依然使用,二…

EF批量插入太慢?那是你的姿势不对

大概所有的程序员应该都接触过批量插入的场景,我也相信任何的程序员都能写出可正常运行的批量插入的代码。但怎样实现一个高效、快速插入的批量插入功能呢?由于每个人的工作履历,工作年限的不同,在实现这样的一个需求时&#xff0…

[RabbitMQ]什么是MQ

什么是MQ MQ(message queue),从字面意思上看,本质是个队列,FIFO 先入先出,只不过队列中存放的内容是message 而已,还是一种跨进程的通信机制,用于上下游传递消息。在互联网架构中,MQ 是一种非常…

.NET Core 实现基于Websocket的在线聊天室

什么是Websocket我们在传统的客户端程序要实现实时双工通讯第一想到的技术就是socket通讯,但是在web体系是用不了socket通讯技术的,因为http被设计成无状态,每次跟服务器通讯完成后就会断开连接。在没有websocket之前web系统如果要做双工通讯…

用 Natasha 写个类型调用的架子

一、想法自上篇文章,我一直琢磨整个好点的例子来展示 Natasha 动态编程能力, 于是就写了一个简单的类型调用的架子,耗时40分钟左右, 项目地址:https://github.com/NMSAzulX/TypeCaller二、功能特点a)、简单的注入功能支持无参构造注入支持递…

Natasha v4.0.0.0 动态编程新篇章

一、简介Natasha 基于 Roslyn 的 C# 动态程序集构建库,该库允许开发者在运行时使用 C# 代码构建域 / 程序集 / 类 / 结构体 / 枚举 / 接口 / 方法等,使得程序在运行的时候可以增加新的模块及功能。Natasha 集成了域管理/插件管理,可以实现域隔…

[RabbitMQ]RabbitMQ概念_四大核心概念

RabbitMQ RabbitMQ 的概念 RabbitMQ 是一个消息中间件:它接受并转发消息。你可以把它当做一个快递站点,当你要发送一个包裹时,你把你的包裹放到快递站,快递员最终会把你的快递送到收件人那里,按照这种逻辑 RabbitMQ …

.Net Core in Docker极简入门(下篇)

点击上方蓝字"小黑在哪里"关注我吧Docker-Compose代码修改yml fileup & down镜像仓库前言上一篇【.Net Core in Docker极简入门(上篇)】讲解了docker的一些基本命令和操作,并成功构建了自己的asp.net core web应用的镜像&#…

这么多Apache顶级项目,SkyWalking为何一枝独秀?

吴晟读完需要5分钟速读仅需 2 分钟吴晟Apache基金会会员,Apache SkyWalking创始人、项目VP和PMC成员,Apache孵化器PMC成员,Apache ShardingSphere PMC成员,Apache APISIX (incubating) PPMC成员,Apache ECharts (incub…

[RabbitMQ]工作原理_原理名词解释

RabbitMQ 核心部分 各个名词介绍 RabbitMQ工作原理 Broker: 接收和分发消息的应用,RabbitMQ Server 就是 Message Broker Virtual host: 出于多租户和安全因素设计的,把 AMQP 的基本组件划分到一个虚拟的分组中,类…

Istio 中的授权策略详解

本文节选自 ServiceMesher 社区出品的开源电子书《Istio Handbook——Istio 服务网格进阶实践》,阅读地址:https://www.servicemesher.com/istio-handbook/授权功能是 Istio 中安全体系的一个重要组成部分,它用来实现访问控制的功能&#xff…

[RabbitMQ]创建Java开发环境_消费者_生产者

我们将用 Java 编写两个程序。发送单个消息的生产者和接收消息并打印出来的消费者。我们将介绍 Java API 中的一些细节。 在下图中&#xff0c;“ P”是我们的生产者&#xff0c;“ C”是我们的消费者。中间的框是一个队列-RabbitMQ 代表使用者保留的消息缓冲区 引入依赖 <…

如何利用Gitlab-CI持续部署到远程机器?

长话短说&#xff0c;今天聊一聊使用Gitlab-CI 自动部署到远程服务器。如果看过《基于docker-compose的Gitlab CI/CD实践&排坑指南》这篇文章的朋友&#xff0c;会注意到我是在 Gitlab-Runner服务器上自动部署的站点&#xff0c;本次我们结合ssh部署到远程机器(将CI服务器和…

[RabbitMQ]工作队列原理_代码实现

Work Queues 工作队列(又称任务队列)的主要思想是避免立即执行资源密集型任务&#xff0c;而不得不等待它完成。 相反我们安排任务在之后执行。我们把任务封装为消息并将其发送到队列。在后台运行的工作进程将弹出任务并最终执行作业。当有多个工作线程时&#xff0c;这些工作…

使用ImpromptuInterface反射方便的创建自定义DfaGraphWriter

在本文中&#xff0c;我为创建的自定义的DfaGraphWriter实现奠定了基础。DfaGraphWriter是公开的&#xff0c;因此您可以如上一篇文章《将终结点图添加到你的ASP.NET Core应用程序中》中所示在应用程序中使用它&#xff0c;但它使用的所有类均已标记为internal。这使得创建自己…

[RabbitMQ]消息应答概念_消息手动应答代码

消息应答 概念 消费者完成一个任务可能需要一段时间&#xff0c;如果其中一个消费者处理一个长的任务并仅只完成了部分突然它挂掉了&#xff0c;会发生什么情况。RabbitMQ 一旦向消费者传递了一条消息&#xff0c;便立即将该消 息标记为删除。在这种情况下&#xff0c;突然有…

rust火箭基地主楼开启方法_Rust 为什么能成为 Stack Overflow 最受欢迎的语言?

每年&#xff0c;开发者问答网站 Stack Overflow 都会对程序员社区展开年度调查&#xff0c;包括他们最喜爱的技术到工作偏好的所有内容。 在2017 年和2018 年Stack Overflow 年度开发者调查中&#xff0c;Rust语言已经连续两年成为最受欢迎语言Top 1。2018 年 Stack Overflow …

[RabbitMQ]队列持久化

RabbitMQ持久化 概念 如何保障当 RabbitMQ 服务停掉以后消息生产者发送过来的消息不丢失。默认情况下 RabbitMQ 退出或由于某种原因崩溃时&#xff0c;它忽视队列和消息&#xff0c;除非告知它不要这样做。确保消息不会丢失需要做两件事&#xff1a;我们需要将队列和消息都标…