系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html

前言

本文将使用一个开源框架CacheCow来实现针对Http请求资源缓存,本文主要介绍服务器端的缓存。

使用缓存技术可以很好的提高Web Api的性能,减小服务器的开销。我们把这种缓存形式称之为:条件化请求(Conditional Requests)。具体表现为:客户端向服务器请求时会附加一个请求头ETag,然后服务器会根据这个信息来决定是否需要把更新过的资源响应给客户端,如果需要,则响应200状态吗以及资源内容,否则响应304状态码(Not modified)以及一个空的响应正文。

什么是ETag?

写了好多,那么什么是ETag呢?ETag是服务器为特定资源生成的一个唯一标识(string类型)。你也可以理解为用来检查服务器资源是否变化。

ETag分2种类型:强类型和弱类型。对于弱类型的ETag包含一个前缀W(例如:W/53fsfsd322),而强类型的ETag不包含任何前缀(例如:53fsfsd322)。通常来说,弱类型ETag代表缓存短时间资源(内存缓存),而强类型的ETag缓存是靠持久化的方式来实现的。

ETag工作原理

先上一张图:

由上图可知:在一开始,客户端发起一个Http Get请求,请求的是id为4的course资源,由于这个资源是第一次被访问,因此服务器在把资源返回的同时附加了一个响应头(ETag)。

现在,客户端发送Http Get请求想要再次请求相同的资源(Course id: 4),考虑到客户端使用缓存,因此Get请求初始化的时候增加一个Header(If-None-Match),内容就是资源的ETag值。当服务器接受到请求的时候,就会读取ETag的值并与服务器内的ETag值做比较,如果完全相同,服务器就会返回304状态码(Not modified)并且正文不含任何内容。这样客户端就知道资源是最新的。

对于Http Get和Delete请求,我们可以使用(If-None-Match)头,但对于更新时我们要使用(If-Match)来匹配Put/Patch请求。请求到达的时候,服务器会校验ETag值,如果不一样,服务器就会响应一个412状态码(Precondition Failed),因此客户端就知道自己的版本不是最新的,在客户端没有获取最新资源之前是不允许更新的。

在Web Api中配置CacheCow

经过了之前的一段简单介绍,我们来实现所谓的“条件化请求”。

我们需要使用NuGet来安装CacheCow,打开NuGet控制台,输入“Install-Package CacheCow.Server -Version 0.4.12”。会安装2个dll:CacheCow.Server和CacheCow.Common。

配置CacheCow也是非常简单的,我们所需要做的是创建一个Cache Handler并把它注入到web api的请求管道中。这个handler就是在请求到达和离开web api的时候检查ETag和生成ETag的。

为了实现这一点,在“WebApiConfig.cs”里做如下配置:

//Configure HTTP Caching using Entity Tags (ETags)
var cacheCowCacheHandler = new CacheCow.Server.CachingHandler();
config.MessageHandlers.Add(cacheCowCacheHandler);

到目前为止,我们的web api已经具有使用本机内存实现缓存的功能了,这也是CacheCow默认的配置,在单机状态(只有一台服务器)的时候可谓是比较完美了。然而,当应用程序走向分布式的时候就出现为题了——由于不同的web服务器需要共享缓存状态,因此我们需要把缓存状态持久化到一个单独的地方(SQL Server, MongoDB, MemCache)。但是在实现持久化之前我们先测试一下内存缓存。

打开我们的测试客户端PostMan(chrome插件),发送Get请求到:http://localhost:{your_port}/api/courses/4

结果:

请求注释:

1.响应Http状态码是200,意昧着服务器把资源一起响应过来了。

2.这次响应增加了2条头信息:ETag和Last-Modified,目前我们只需关心ETag的值,因为下次请求会用到。

3.ETag的类型是弱类型的(带有W前缀),说明这个缓存存在于服务器的内存中,如果重启IIS或切断服务进程的话,缓存就会失效。

对于接受到ETag值的客户端,在下次请求相同资源的时候就需要附加一个“If-None-Match”的请求头,服务器就会比较客户端与自己内存中的ETag值,如果相同,返回304(Not modified),不相同则返回200加上资源内容。

测试:我们再次请求这个资源

结果:

对于这次请求来说:

1.http状态码是304,意味着客户端的资源是最新的,因此响应body是空的

2.客户端得到相同的ETag值

在SQL Server端实现缓存

在SQL Server中做缓存同样很简单,首先我们要确定在哪个持久化介质中实现缓存,我们用的是SQL Server,因此打开NuGet控制台,输入如下命令:Install-Package CacheCow.Server.EntityTagStore.SqlServer -Version 0.4.11。

然后在“WebApiConfig”做如下配置:

//Configure HTTP Caching using Entity Tags (ETags)
var connString = System.Configuration.ConfigurationManager.ConnectionStrings["eLearningConnection"].ConnectionString;
var eTagStore = new CacheCow.Server.EntityTagStore.SqlServer.SqlServerEntityTagStore(connString);
var cacheCowCacheHandler = new CacheCow.Server.CachingHandler(eTagStore);
cacheCowCacheHandler.AddLastModifiedHeader = false;
config.MessageHandlers.Add(cacheCowCacheHandler);

上面的实现很明显,CacheCow需要把缓存信息存到数据库中,因此我们需要制定我们api所用的数据库。然后把eTagStore实例赋给Cache handler。

如果你现在直接请求api的话,等待你的不是资源而是一个500错误码。这是因为之前我们介绍到CacheCow需要把缓存信息存入数据库,那么数据库中就应该有一张对应的表以及操作这张表的存储过程,因此我们需要执行一个sql脚本。这个脚本通常在“{projectpath}\packages\CacheCow.Server.EntityTagStore.SqlServer.0.4.11\script”

执行完这个脚本后,你会发现数据库多了一张表以及5个存储过程:

ok,可以测试了,还是刚刚的例子:

正如上图所示,ETag的值不再是弱类型的了,因此我们存到SQL Server中了,打开SQL Server中的CacheState表,你会发现:

现在,只要没有客户端来更新这个资源,之前访问过这个资源的客户端统统会得到304状态码以及空的body(前提是客户端的请求中包含ETag值,呵呵)。

现在我们实现一下更新,客户端要更新资源就需要包含一个“If-Match”的请求头,如下图所示:

结果:

ETag已经改变:

我们使用老的ETag再次请求服务器:

所以结果:

这个响应告诉客户端:”你手里的资源不是最新的,先拿到最新的资源我才让你修改”。

总结

拖了好久的最后一篇终于和大家见面了,主要都是一些理论,代码也就5行,不过感觉ETag还真的挺强大的。

本次系列到这里也要告一段落了,不过之后还打算介绍一些有其他内容(包括Web Api 2的新特性IHttpActionResult,CORS的支持以及OData的支持等),敬请期待。。。

源码地址:https://github.com/fzrain/WebApi.eLearning

转载于:https://www.cnblogs.com/fzrain/p/3618887.html

使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【十】——使用CacheCow和ETag缓存资源...相关推荐

  1. 使用ASP.NET Web Api构建基于REST风格的服务实战系列教程

    最近发现web api很火,园内也有各种大神已经在研究,本人在asp.net官网上看到一个系列教程,原文地址:http://bitoftech.net/2013/11/25/detailed-tuto ...

  2. ASP.NET Web Api使用CacheCow和ETag缓存资源

    ASP.NET Web Api使用CacheCow和ETag缓存资源 ASP.NET Web Api使用CacheCow和ETag缓存资源 ASP.NET Web Api使用CacheCow和ETag ...

  3. 使用ASP.NET Web API构建Restful API

    目录 介绍 这种方法有什么好处? Restful约定 构建API 测试API 一点困惑: 最佳实践: 数据传输对象(DTO) Automapper IHttpActionResult 使用Web AP ...

  4. ASP.NET Web Api 使用CacheCow和ETag缓存资源(转载)

    转载地址:http://www.cnblogs.com/fzrain/p/3618887.html 前言 本文将使用一个开源框架CacheCow来实现针对Http请求资源缓存,本文主要介绍服务器端的缓 ...

  5. ASP.NET Web Api 教程

    使用ASP.NET Web Api构建基于REST风格的服务实战系列教程[七]--实现资源的分页 摘要: 系列导航地址http://www.cnblogs.com/fzrain/p/3490137.h ...

  6. 我对 ASP.NET Web API 的随想

    其实自己实现一个类似与 ASP.NET Web API 的轻量级 Web 服务(PS:不是说 Web Service 技术)也不是很难的事,就算不用 ASP.NET MVC,用 ASP.ASP.NET ...

  7. Asp.net Web Api开发 性能:使用Jil提升Json序列化性能

    from:http://blog.csdn.net/sqqyq/article/details/51692342 看了几篇网上关于各种序列化工具的性能对比,在这里再粘贴下: 我们使用了ASP.NET ...

  8. Asp.net Web Api开发(第二篇)性能:使用Jil提升Json序列化性能

    看了几篇网上关于各种序列化工具的性能对比,在这里再粘贴下: 我们使用了ASP.NET WEB API来提供RESTfull风格的接口给APP调用,默认序列化库用的是:Newtonsoft.Json 为 ...

  9. ASP.NET Web API与Owin OAuth:使用Access Toke调用受保护的API(二)

    在前一篇博文中,我们使用OAuth的Client Credential Grant授权方式,在服务端通过CNBlogsAuthorizationServerProvider(Authorization ...

最新文章

  1. JFinal 源码导读第八天(1) Db.tx 事物
  2. R语言均匀分布函数uniform Distribution(dunif, punif, qunif runif)实战
  3. 大话设计模式之简单工厂模式
  4. 对于一些手机内存概念的思考、深入理解java的finalize,对于内存优化的小总结...
  5. linux rpm命令 查询包安装与否、包详细信息、包安装位置、文件属于哪个包、包依赖
  6. html复选框对齐文字,input【type=checkbox】标签与字体对齐
  7. linux dmesg命令(显示开机信息)
  8. 低延时直播与RTC融合架构设计③:RTC融合架构设计
  9. IntelliJ IDEA(二) :面板介绍
  10. 如何使用React,TypeScript和React测试库创建出色的用户体验
  11. 用并发队列(ConcurrentQueue)实现多线程任务中随时异步回调进度通知(.Net4.0)
  12. Python [6] IT资产管理(下)
  13. gis数据与cad数据转换之间的关系
  14. WPF的prism框架
  15. 自己封装的一个checkbook工具
  16. WIN7远程桌面连接--“发生身份验证错误。要求的函数不受支持”
  17. mysql对象资源管理器_使用对象资源管理器
  18. 【Flutter之旅】路由管理
  19. 【工程经济学】各章计算题合集
  20. MTK6735 android开发记录 编译配置(一)

热门文章

  1. 启动tomcat发现80端口被ntoskrnl.exe 占用 80 端口
  2. 无法打开项目文件。 无法找到 .NET SDK。请检查确保已安装此项且 global.json 中指定的版本(如有)与所安装的版本相匹配
  3. mobiscroll 插件札记
  4. 「数字电子技术基础」5.组合逻辑电路
  5. 2014安徽二级c语言程序设计,安徽省二级C语言程序设计笔试样题(14页)-原创力文档...
  6. oracle9i的dmp,oracle 9i怎么导入DMP数据库文件?
  7. 现在实现flexbox 的策略和工具(flexbox兼容到IE8的跨浏览器解决方案)
  8. 全方位揭秘!大数据从0到1的完美落地之Hive自定义函数
  9. int最大值,最小值的获取
  10. 一个人的旅行------Dijkstra