ASP.NET Core 缓存技术 及 Nginx 缓存配置

前言

在Asp.Net Core Nginx部署一文中,主要是讲述的如何利用Nginx来实现应用程序的部署,使用Nginx来部署主要有两大好处,第一是利用Nginx的负载均衡功能,第二是使用Nginx的反向代理来降低我们后端应用程序的压力。那除了以上两点之外,其实我们还可以利用代理服务器的缓存功能来进一步的降低后端应用程序的压力,提升系统的吞吐量(tps)。这一篇就来看一下具体应该如何去做吧。

目录

  • WEB 缓存

  • ASP.NET Core 缓存
    内存缓存
    分布式缓存
    Response 缓存

  • Nginx 缓存

  • 总结

WEB 缓存

之所以加这个目录是因为有一部分初学者对缓存的认知不够,特别是WEB中的缓存。

缓存它是一种空间换取时间的一种技术。

Web缓存(或HTTP缓存)是用于Web文档,如HTML页面和图像,减少带宽的使用,服务器的负载的一种信息技术。一个Web缓存系统存储通过Cache来传递的文件的副本;如果满足某些条件,则可以从缓存中得到后续的请求。

WEb缓存有几种方式:

1、服务端缓存
利用 Memcached,Redis,In-Memery 等缓存技术实现对数据的缓存。

2、代理服务器缓存
利用类似nginx的反向代理服务器,对请求的url对应的输出的进行缓存。这个缓存和应用程序实现的动态页面缓存类似,只不过用反向代理充当了应用程序的缓存实现。

3、客户端缓存
浏览器缓存,其实主要就是HTTP协议定义的缓存机制(如: Last-Modified,If-Modified-Since,Expires; Cache-control等)。

ASP.NET Core 缓存

  • 内存缓存

最简单的一种缓存,ASP.NET Core 提供了 IMemoryCache 接口来供我们使用。它存储在本地的 WEB 服务器内容中,注意是单机的 WEB 服务器,如果你需要部署的是一个服务器集群的话,那么你应该用分布式缓存,而不是选择这个。
就不详细介绍了,想了解的可以直接看官方文档。

  • 分布式缓存

随着云应用和服务器集群以及 docker 等技术的成熟,越来越多的应用程序开始考虑集群部署,因为它具有更好的性能和可伸缩可扩展性。那么这个时候就需要用到分布式缓存了。
在 ASP.NET Core应用中,已经对分布式缓存做了抽象,提供了 IDistributedCache 接口,该接口提供了添加,检索,删除等的同步和异步的方法。并且还默认提供了 Redis 和 SQLServer 的分布式缓存实现,我们也可以实现 IDistributedCache 接口来扩展自己的缓存系统。

需要说明的是Get,GetAsyncSet,SetAsync。 这两个接口方法默认是使用的byte[],之所以没有提供直接存储对象的方法是因为微软想把这个默认序列化的选择交给用户,因为每一个团队的偏好是不一样的,有些团队喜欢使用 XML,有些喜欢使用 JSON,有些喜欢使用 Protobuf 等,所以在 项目中,你可以根据自己的偏好来扩展想要的方法。

具体使用方法还是直接看官方文档好了。

关于使用也可以查看我的另外一篇博客: ASP.NET Core 使用 Redis 和 Protobuf 进行 Session 缓存。

  • Response 缓存

在 ASP.NET Core中,有一种缓存叫做Response缓存,这个缓存主要是用来做代理服务器的缓存。它主要原理是在输出的HTTP Response的header里面添加指定的缓存标记。这些缓存标记用来让客户端或者代理服务器来识别需要缓存的内容。然后当客户端有请求到代理服务器的时候,代理服务器可以识别出一部分请求,然后直接把结果返回给浏览器,从而提高后端应用程序的性能和吞吐。

从这个图中看出来,在第一次的时候,一个客户端请求经过代理服务器请求的我们后端的WEB服务器上,然后WEB服务器在返回结果的META上添加了cache-control标签,它的值为public

下面是cache-control标签一些值的说明:

public 指示响应可被任何缓存区缓存。

private 指示对于单个用户的整个或部分响应消息,不能被共享缓存处理。这允许服务器仅仅描述当用户的部分响应消息,此响应消息对于其他用户的请求无效。

no-cache 指示请求或响应消息不能缓存(HTTP/1.0用Pragma的no-cache替换)根据什么能被缓存

max-age 指示客户机可以接收生存期不大于指定时间(以秒为单位)的响应。

min-fresh 指示客户机可以接收响应时间小于当前时间加上指定时间的响应。

max-stale 指示客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值,那么客户机可以接收超出超时期指定值之内的响应消息。

Expires 表示存在时间,允许客户端在这个时间之前不去检查(发请求),等同max-age的
效果。但是如果同时存在,则被Cache-Control的max-age覆盖。

格式:
Expires = "Expires" ":" HTTP-date

通过HTTP的META设置expires和cache-control

<meta http-equiv="Cache-Control" content="max-age=7200" /><meta http-equiv="Expires" content="Mon, 20 Jul 2016 23:00:00 GMT" />

在 ASP.NET Core MVC 中,提供了ResponseCache这个特性用来做上面这些事情。它被作为一个Attribute添加的Controller的Action上。

Duration 指示缓存的过期时间,对应到Cache-Control 的 max-age 。

Location 有三个值Any,Client,None分别对应到Cache-Control的 public,private,no-cache。

NoStore 设置值是否被存储。如果是true,它将设置Cache-Control为no-store

VaryByHeader 将在header中添加Vary标记。

CacheProfileName 使用的策略,在startup.cs中设置。

Order 在过滤器中的排序。

现在,我们已经知道了如果在Action中设置缓存标记了。

Nginx 缓存

对于一些静态文件,比如程序用到的图片,css,js等,Nginx是可以直接处理的,只需要配置一下。
如果使用Nginx来处理静态文件的话,那么程序中startup.cs就可以不用添加app.UseStaticFiles();中间件了。

  • 配置
    打开nginx.conf文件,在ubuntu系统下位于/etc/nginx/conf.d/nginx.conf没有的话就新建一个。内容如下:

proxy_temp_path   /usr/local/nginx/proxy_temp_dir 1 2; #注:proxy_temp_path和proxy_cache_path指定的路径必须在同一分区

#keys_zone=cache1:100m 表示这个zone(缓存区域)名称为cache1,分配的内存大小为100MB

#/usr/local/nginx/proxy_cache_dir/cache1 表示cache1这个zone的文件要存放的目录

#levels=1:2 表示缓存目录的第一级目录是1个字符,第二级目录是2个字符,即/usr/local/nginx/proxy_cache_dir/cache1/a/1b这种形式

#inactive=1d 表示这个zone中的缓存文件如果在1天内都没有被访问,那么文件会被cache manager进程删除掉#max_size=10g 表示这个zone的硬盘容量为10GB

proxy_cache_path  /usr/local/nginx/proxy_cache_dir/cache1  levels=1:2 keys_zone=cache1:100m inactive=1d max_size=10g;

#upstream web-app {

#    server webapp1:5090;#    server webapp2:5090;#}

server {    

listen 80;  

 server_name *.example.com;    #在日志格式中加入$upstream_cache_status    log_format format1 '$remote_addr - $remote_user [$time_local]  '        '"$request" $status $body_bytes_sent '        '"$http_referer" "$http_user_agent" $upstream_cache_status';    #访问日志    access_log log/access.log fomat1;    #$upstream_cache_status表示资源缓存的状态,有HIT MISS EXPIRED三种状态    add_header X-Cache $upstream_cache_status;        #命中的正则表达式    location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|js|css|html)$ {        proxy_pass http://127.0.0.1:5000;        #proxy_pass http://web-app;                  #proxy_set_header Host $host;        #proxy_set_header X-Real-IP $remote_addr;        #proxy_set_header X-Forwarded-For $remote_addr;        #proxy_set_header Accept-Encoding "none";        #设定proxy_set_header Accept-Encoding '';(或是后台服务器关闭gzip),这样这台机器才不会缓存被压缩的文件,造成乱码        #proxy_set_header Accept-Encoding ""; 这个也可                #如果后端的服务器返回502、504、执行超时等错误,自动将请求转发到upstream负载均衡池中的另一台服务器,实现故障转移。        #proxy_next_upstream http_502 http_504 error timeout invalid_header;        #设置资源缓存的zone        proxy_cache cache1;        #设置缓存的key        proxy_cache_key $host$uri$is_args$args;        #设置状态码为200和304的响应可以进行缓存,并且缓存时间为10分钟        proxy_cache_valid 200 304 10m;                # **!!!重要!!!** 这段配置加上后,proxy_cache就能支持后台设定的Cache-Control,Expires。        proxy_ignore_headers "Cache-Control" "Expires";        expires 30d;    } }

上面有一个配置项在 ASP.NET Core 程序中比较重要,就是proxy_ignore_headers这个配置项,它代表支持后台设定Cache-Control,Expires等。

其中upstream节点是用来配置负载均衡的服务器的,proxy_pass用来设置代理到upstream节点,proxy_next_upstream是用来配置故障转移。

  • 应用配置

使用sudo nginx -s reload命令来重新加载配置。

总结

关于缓存

缓存确实是提升应用程序性能最快也是效果最明显的方式之一,ASP.NET Core也为提供了很多种缓存方法。但是,在使用之前一定要了解每一种缓存的技术实现,切不可盲目使用。

关于部署

个人认为,在 ASP.NET Core 理想的分布式部署环境有两种:

第一种是基于云的部署,比如使用Azure,AWS,阿里云等,那么我们可以使用他们提供的负载均衡器来帮助我们拦截洪水般的请求,然后借助于云提供的高可用的实例集群或者Docker集群来降低应用程序的压力,提升吞吐。

比如我们项目现在使用的AWS的部署环境,借助于AWS来实现企业的私有云,包括高可用的Redis集群,弹性EC2集群,RDS集群,S3等,这个时候只需要专注于业务。

第二种是自己搭建集群环境,可以在服务器前端使用Nginx的负载均衡和缓存来拦截大部分的HTTP请求,然后后端使用Docker集群来做部署。

Docker部署可以参见本人的另外一篇文章:http://mp.weixin.qq.com/s?__biz=MzAwNTMxMzg1MA==&mid=2654067746&idx=1&sn=5038e9ab3460066e736894c7ac8846ea&scene=21#wechat_redirect

在版本的快速迭代过程中,你还需要做的工作有如何提高部署的工作效率,那么可以使用一些Docker集群管理工具,后面会写一篇文章专门介绍Docker的集群管理和 ASP.NET Core的一键发布。


原文地址:http://www.cnblogs.com/savorboard/p/dotnetcore-nginx-cache.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

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

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

相关文章

localStorage、sessionStorage、Cookie的区别及用法

localStorage、sessionStorage、Cookie https://segmentfault.com/a/1190000012057010 localStorage、sessionStorage、Cookie的区别及用法 webstorage webstorage是本地存储&#xff0c;存储在客户端&#xff0c;包括localStorage和sessionStorage。 localStorage localSto…

shiro入门

一、身份认证 基本流程 流程如下&#xff1a; shiro把用户的数据封装成标识token&#xff0c;token一般封装着用户名&#xff0c;密码等信息使用Subject获取到封装着用户的数据标识tokenSubject将token交给SecurityManager&#xff0c;在SecurityManager安全中心中&#xff…

前后端分离开发模式下后端质量的保证 —— 单元测试

概述 在今天&#xff0c; 前后端分离已经是首选的一个开发模式。这对于后端团队来说其实是一个好消息&#xff0c;减轻任务并且更专注。在测试方面&#xff0c;就更加依赖于单元测试对于API以及后端业务逻辑的较验。当然单元测试并非在前后端分离流行之后才有&#xff0c;它很早…

查询近12个月的数据,没有数据的月份补零

可以有两种方法实现&#xff0c;一种是纯sql的方式&#xff0c;一种是sql和代码共用的形式 一、纯sql的形式 前半部分用于一个近12个月的表&#xff0c;然后再将查出来的数据和月份表相结合&#xff0c;就是想要的结果 select v.month,b.price price,ifnull(b.count,0) cou…

java图形验证码生成工具类

转载自 java图形验证码生成工具类生成验证码效果 ValidateCode.java 验证码生成类 package cn.dsna.util.images; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.FileOutput…

.NET Core中的认证管理解析

0x00 问题来源 在新建.NET Core的Web项目时选择“使用个人用户账户”就可以创建一个带有用户和权限管理的项目&#xff0c;已经准备好了用户注册、登录等很多页面&#xff0c;也可以使用AuthorizeAttribute进行各种权限管理&#xff0c;看起来似乎十分方便。不过生成的代码都替…

散列算法,Remal使用散列算法

一、散列算法 散列算法让其保证不可逆&#xff0c;安全。这里举一个例子sh1的摘要算法。上代码 /*** 散列算法* author Administrator*/ public class HashRsaUtil {/*** 加密方式*/public static final String SHA1"SHA-1";/*** 加密次数*/public static final In…

简化得最没道理的6个汉字,让人大跌眼镜

文章来源于网络&#xff0c;侵删&#xff01;&#xff01;&#xff01; 1、“進”被简化为“进”&#xff0c;“進”字是让人“越走越佳”。 简化字却把它改成了“进”字&#xff0c;让你越走越走到“井”里去了&#xff0c;井底之蛙自生自灭。 2、“廠”被简化为“厂”字&…

c++

#include <iostream> #include<cmath> using namespace std; int main() { int x; double a; double b; while(cin >> x ){//注意while处理多个case for(int i 0 ;i < x ; i ){ cin>>a; …

在docker中运行ASP.NET Core Web API应用程序

本文是一篇指导快速演练的文章&#xff0c;将介绍在docker中运行一个ASP.NET Core Web API应用程序的基本步骤&#xff0c;在介绍的过程中&#xff0c;也会对docker的使用进行一些简单的描述。对于.NET Core以及docker的基本概念&#xff0c;网上已经有很多文章对其进行介绍了&…

谈谈 Java 的克隆

转载自 谈谈 Java 的克隆为什么要克隆对象 做开发很少用到克隆的。我能想得到的是用于调用方法时作为参数传递&#xff0c;为了保证方法调用前后对象的内部结构不被破坏&#xff0c;可以克隆一个对象作为参数传递。 使类具有克隆能力 有人可能注意到 Object 类中有一个 native…

android启调支付宝

网上找了一个可以起吊支付宝的appdemo &#xff0c;它集成了服务器端&#xff0c;我先将其分离为app和服务器端&#xff0c;保证app在接收参数后可以启调支付宝 &#xff08;保证app这边是正确的 不然出错都不知道是服务器出错还是app出错&#xff09;&#xff0c;在 找网上资…

shiro-身份授权流程、案例

一、身份授权流程 首先调用Subject.isPermitted/hasRole接口&#xff0c;委托给SecurityManager.SecurityManager接着会委托给内部组件Authorizer.Authorizer再将其请求委托给我们的Realm去做&#xff0c;Realm才是真正干活的.realm将用户请求的参数封装成权限对象&#xff0c…

对Java的URL类支持的协议进行扩展的方法

转载自 对Java的URL类支持的协议进行扩展的方法JAVA默认提供了对file,ftp,gopher,http,https,jar,mailto,netdoc协议的支持。当我们要利用这些协议来创建应用时&#xff0c;主要会涉及到如下几个类&#xff1a;java.net.URL、java.net.URLConnection、InputStream。URL类默认…

在.Net项目中使用Redis作为缓存服务

最近由于项目需要&#xff0c;在系统缓存服务部分上了redis&#xff0c;终于有机会在实际开发中玩一下&#xff0c;之前都是自己随便看看写写&#xff0c;很零碎也没沉淀下来什么&#xff0c;这次算是一个系统学习和实践过程的总结。 和Redis有关的基础知识 Redis是一个开源的分…

中国的程序员培训是不是有问题?

内容来源于&#xff0c;看最下面的出处&#xff0c;侵删 中国技术开放日的出海团对日本进行了为期一周的访问。笔者随行了头两天&#xff0c;参加Slush Asia大会&#xff0c;并访问了Gungho和Deloitte两家企业。虽然已经在日本生活了四年&#xff0c;但这样的体验却甚少&#x…

后台回调支付宝

https://blog.csdn.net/u012552275/article/details/78320051 网上找了一个可以起吊支付宝的appdemo &#xff0c;它集成了服务器端&#xff0c;我先将其分离为app和服务器端&#xff0c;保证app在接收参数后可以启调支付宝 &#xff08;保证app这边是正确的 不然出错都不知道…

解决高版本SpringBoot整合swagger时启动报错:Failed to start bean ‘documentationPluginsBootstrapper‘ 问题

一、控制台的报错信息 2021-12-29 15:15:04 [main] ERROR org.springframework.boot.SpringApplication - Application run failed org.springframework.context.ApplicationContextException: Failed to start bean documentationPluginsBootstrapper; nested exception is j…

java图片格式转化(例如jpg格式转化png)

转载自 java图片格式转化&#xff08;例如jpg格式转化png&#xff09; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.Scanner;import javax.imageio.*; public class FormatConversion {public static final Str…

微软开源PowerShell并支持Linux

建议在Wifi 环境下观看视频 class"video_iframe" data-vidtype"1" style" z-index:1; " height"375" width"500" frameborder"0" data-src"https://v.qq.com/iframe/preview.html?vidv0322g7kd3f&width…