返回顶部
首页 > 资讯 > 后端开发 > ASP.NET >.NET6开发之实现缓存过程详解
  • 453
分享到

.NET6开发之实现缓存过程详解

2024-04-02 19:04:59 453人浏览 泡泡鱼
摘要

目录需求目标原理与思路实现使用原生ResponseCaching实现缓存使用Marvin.Cache.Headers实现更多缓存功能一点扩展总结参考资料需求 有的时候为了减少客户端请

需求

有的时候为了减少客户端请求相同资源的逻辑重复执行,我们会考虑使用一些缓存的方式,在.NET 6中,我们可以借助框架提供的中间件来实现请求资源的缓存。

目标

实现请求结果的缓存。

原理与思路

对于在.net6中实现缓存,我们可以使用响应缓存中间件ResponseCaching来实现,同时可以使用Marvin.Cache.Headers来为我们提供更多的缓存相关的属性。

实现

使用原生ResponseCaching实现缓存

既然是中间件,我们便在Program中引入:

Program.cs

// 省略其他...
// 配置缓存中间件
builder.Services.AddResponseCaching();
builder.Services.AddControllers();
// ...
// 使用缓存中间件
app.UseResponseCaching();
app.MapControllers();

在使用方法上,有几种方式可以实现配置:1)进行全局的配置,应用于所有添加了相同ProfileNameResponseCache的Controller响应;2)对单个Controller/Action进行配置,应用于当前作用的Controller/Action;3)全局配置后,由单个Controller/Action覆盖全局配置。我们会演示1)和3)的场景。

我们准备使用获取所有TodoLists的接口进行演示。

先看如何进行全局配置:

Program.cs

// 省略其他...
builder.Services.AddControllers(options =>
{
    options.CacheProfiles.Add("60SecondDuration", new CacheProfile { Duration = 60 });
});

验证1: 全局配置Caching

首先给我们要进行验证的Action添加属性:

TodoListController.cs

// 省略其他...
[HttpGet]
[ResponseCache(CacheProfileName = "60SecondDuration")]
public async Task<apiResponse<List<TodoListBriefDto>>> Get()
{
    return ApiResponse<List<TodoListBriefDto>>.Success(await _mediator.Send(new GetTodosQuery()));
}

启动Api项目,第一次执行获取TodoLists的请求:

请求

响应

响应头中多了一个cache-control字段用于指明缓存的类型(public)以及过期时间为60s:

如果你是使用Postman或者Insomia发送的请求,那么在过期前再次发起相同请求的返回头中会再多出一个Age字段,用于表明该资源当前缓存了多少秒(Hoppscotch我没找到可以在哪里设置,所以下面的截图是来自Insomia,如果有哪位老哥知道的可以教一下):

同时如果观察日志的话会发现,第二次请求并没有实际执行sql语句,这也证明了第二次请求的返回来自缓存:

如果间隔60s以上我们再去发送相同的请求,会发现日志中是这样的:

可以看到缓存已经失效了,此时需要重新向数据库查询返回数据,并将这次请求结果缓存起来。

验证2: 单个Action覆盖全局配置

我们还是使用这个接口,但是修改一下属性:

TodoListController.cs

[HttpGet]
[ResponseCache(Duration = 120)]
public async Task<ApiResponse<List<TodoListBriefDto>>> Get()
{
    return ApiResponse<List<TodoListBriefDto>>.Success(await _mediator.Send(new GetTodosQuery()));
}

重新启动Api项目,第一次执行获取TodoLists的请求,请求和验证1相同,我们来看响应中的变化:

响应

可以看到失效时间已经变为120s了,其他不再一一验证。

使用Marvin.Cache.Headers实现更多缓存功能

在缓存中还有一个问题是,如果判断缓存的数据内容已经变化,就需要去获取最新的响应而不是直接从缓存中取值。这是借助缓存校验来完成的,而常使用的方式是通过Etag实现。示意的过程如下:

如果首次请求资源,API会在响应头中添加EtagLast-Modified字段:

当客户端再次请求资源时,由于缓存自身是不知道资源有没有被修改,所以缓存会携带If-None-Match字段(和客户端收到的Etag值相等)和If-Modified-Since字段(和客户端收到的Last-Modified值相等)到API端,如果校验发现资源没有发生修改,那么API端无需重新获取资源,直接返回304字段(NotModifed)给缓存,缓存给客户端返回值。如果校验发现资源发生了修改,那么API将会返回新的结果。

我们给Api项目添加Nuget包Marvin.Cache.Headers,来实现此功能。

首先向Program中添加服务以及引入中间件:

Program.cs

builder.Services.AddResponseCaching();
builder.Services.AddHttpCacheHeaders(
    expirationOptions =>
    {
        expirationOptions.MaxAge = 180;
        expirationOptions.CacheLocation = CacheLocation.Private;
    },
    validateOptions =>
    {
        validateOptions.MustRevalidate = true;
    });
// 省略其他...
app.UseResponseCaching();
app.UseHttpCacheHeaders();

同时我们需要移除之前添加的ResponseCache属性,因为新引入的库已经帮我们完成了,当然我们也可以通过以下方式覆盖全局配置:

[HttpCacheExpiration(CacheLocation = CacheLocation.Public, MaxAge = 60)]
[HttpCacheValidation(MustRevalidate = false)]

覆盖规则和框架内置的规则是一致的,我不会继续演示。

验证3: 缓存校验

请求仍然是获取所有的TodoLists

响应

我们暂时只关注响应头:

如果在缓存失效前我们添加了一个新的TodoList,在请求头中添加If-None-Match=53154EEFAE230D733827DBDE49B42AF9再执行获取请求:

可以看到在失效时间到期之内,Etag值已经发生了变化,校验表明资源已经改变,需要重新获取。

如果我们再次获取相同的资源,会得到304返回:

一点扩展

但是如果我们仔细观察和思考就会发现,框架在实现缓存校验上存在两个问题:

  1. If-None-Match头字段是我们手动添加模拟的,这本应该由缓存中间件来完成;
  2. 在响应304的情况下,实际上是没有返回响应体的,即缓存中未修改的资源没有返回;

这两个问题是由框架内建的ResponseCaching库导致的,可以认为它没有正确地实现缓存校验机制。为此我们有一些替代方案可供参考:

Varnish

Apache Traffic Server

Squid

当然使用专门的CDN来做缓存也是可以的。

总结

在本文中我们主要演示了如何借助框架的缓存机制来实现请求资源的缓存,尽管在缓存校验的实现上,官方提供的库目前来看并没有能很好地完成功能以外,对于我们基本的使用场景来说已经够用了。下一篇文章我们来看怎么实现接口的限流。

参考资料

1.Varnish

2.Apache Traffic Server

3.Squid

到此这篇关于.NET 6开发之实现缓存过程详解的文章就介绍到这了,更多相关.NET 6实现缓存内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: .NET6开发之实现缓存过程详解

本文链接: https://lsjlt.com/news/161939.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • .NET6开发之实现缓存过程详解
    目录需求目标原理与思路实现使用原生ResponseCaching实现缓存使用Marvin.Cache.Headers实现更多缓存功能一点扩展总结参考资料需求 有的时候为了减少客户端请...
    99+
    2024-04-02
  • .NET6开发TodoList应用之实现ActionFilter
    目录需求目标原理与思路实现验证总结需求 Filter在.NET Web API项目开发中也是很重要的一个概念,它运行在执行MVC响应的Pipeline中执行,允许我们将一些可以在多个...
    99+
    2024-04-02
  • SpringBoot开发存储服务器实现过程详解
    目录正文基础环境创建项目添加Rest API接口功能(提供上传服务)启动服务,测试API接口可用性增加下载文件支持文件大小设置打包文件部署正文 今天我们尝试Spring Boot整合...
    99+
    2022-12-08
    SpringBoot 存储服务器 SpringBoot 存储
  • .NET6开发TodoList应用之实现PUT请求
    目录需求目标原理与思路实现PUT请求领域事件的发布和响应验证总结需求 PUT请求本身其实可说的并不多,过程也和创建基本类似。在这篇文章中,重点是填上之前文章里留的一个坑,我们曾经给T...
    99+
    2024-04-02
  • .NET6开发TodoList应用之实现数据塑形
    目录需求目标原理与思路实现定义通用接口和泛型类实现定义扩展方法添加依赖注入修改查询请求和Controller接口验证总结需求 在查询的场景中,还有一类需求不是很常见,就是在前端请求中...
    99+
    2024-04-02
  • .NET6开发TodoList应用之实现查询分页
    目录需求目标原理与思路实现定义分页结果数据结构添加对于分页结果的Mapping Profile创建分页查询请求创建查询Controller验证总结需求 查询中有个非常常见的需求就是后...
    99+
    2024-04-02
  • .NET6开发TodoList应用之实现查询排序
    目录需求目标原理与思路实现验证总结需求 关于查询的另一个需求是要根据前端请求的排序字段进行对结果相应的排序。 目标 实现根据排序要求返回排序后的结果 原理与思路 要实现根据前端请求的...
    99+
    2024-04-02
  • iOS开发之1行代码实现缓存计算及清除缓存
    话不多说,直接撸代码 // // gzhCache.h // cache // // Created by 郭志贺 on 2020/5/27. // Copyright &cop...
    99+
    2022-06-02
    ios 清除 缓存
  • .NET6开发TodoList应用之实现API版本控制
    目录需求目标原理与思路实现添加Nuget Package并配置服务实现API版本控制一点扩展总结需求 API接口版本管理,对于一些规模稍大的企业应用来说,是经常需要关注的一大需求。尽...
    99+
    2024-04-02
  • .NET6开发TodoList应用之实现接口请求验证
    目录需求目标原理与思路实现验证一点扩展总结参考资料需求 在响应请求处理的过程中,我们经常需要对请求参数的合法性进行校验,如果参数不合法,将不继续进行业务逻辑的处理。我们当然可以将每个...
    99+
    2024-04-02
  • .NET6开发TodoList应用之使用AutoMapper实现GET请求
    目录需求目标原理与思路实现引入AutoMapper实现GET请求验证获取所有TodoList列表获取单个TodoList详情填一个POST文章里的坑总结需求 需求很简单:实现GET请...
    99+
    2024-04-02
  • .NET6开发TodoList应用之实现全局异常处理
    目录需求目标原理和思路实现验证总结参考资料需求 因为在项目中,会有各种各样的领域异常或系统异常被抛出来,那么在Controller里就需要进行完整的try-catch捕获,并根据是否...
    99+
    2024-04-02
  • Springboot详解缓存redis实现定时过期方法
    目录前言添加依赖添加配置常规缓存开启缓存设置缓存空间设置缓存增加设置缓存过期时间总结后记前言 使用redis进行缓存数据,是目前比较常用的缓存解决方案。常用的缓存形式有一下几种: 1...
    99+
    2024-04-02
  • Drupal7的cache缓存开发实例教程
    本文实例讲述了Drupal7的cache缓存开发的方法。分享给大家供大家参考。具体方法如下: Drupal是一款非常好用的php开发的开源内容管理框架了,这个框架在缓存方面做得非常的不错,下文一起来学习Drupal7 c...
    99+
    2022-06-12
    Drupal7 cache 缓存 开发 教程
  • .NET 6开发中怎么实现缓存
    小编今天带大家了解.NET 6开发中怎么实现缓存,文中知识点介绍的非常详细。觉得有帮助的朋友可以跟着小编一起浏览文章的内容,希望能够帮助更多想解决这个问题的朋友找到问题的答案,下面跟着小编一起深入学习“.NET 6开发中...
    99+
    2023-06-26
  • javaCV开发详解之收流器实现
    本章基于javaCV实现收流器功能和录制功能 补充:基于本功能可以实现远程流媒体服务器实时视频录制到本地 一、开发所依赖的包 javacv.jar,javacpp.jar,ffmpe...
    99+
    2024-04-02
  • Java实现LRU缓存的实例详解
    Java实现LRU缓存的实例详解1.CacheCache对于代码系统的加速与优化具有极大的作用,对于码农来说是一个很熟悉的概念。可以说,你在内存中new 了一个一段空间(比方说数组,list)存放一些冗余的结果数据,并利用这些数据完成了以空...
    99+
    2023-05-31
    java lru缓存 ava
  • NestJS+Redis实现缓存步骤详解
    NestJS的缓存模块天生支持Redis等缓存机制。以下通过一个示例,说明如何在NestJS中操作Redis。步骤如下: 先安装运行Redis服务,步骤参见链接 新建nestjs项目...
    99+
    2024-04-02
  • mysql存储过程之错误处理实例详解
    本文实例讲述了mysql存储过程之错误处理。分享给大家供大家参考,具体如下: 当存储过程中发生错误时,重要的是适当处理它,例如:继续或退出当前代码块的执行,并发出有意义的错误消息。其中mysql提供了一种简...
    99+
    2024-04-02
  • django开发教程之利用缓存文件进行页面缓存的方法
    前言 由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者Redis中,5分钟内...
    99+
    2022-06-04
    缓存 页面 文件
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作