ASP.NET Web Api构建基于REST风格的服务实战系列教程
使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【十】——使用CacheCow和ETag缓存资源
系列导航地址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的支持等),敬请期待。。。
ASP.NET Web Api构建基于REST风格的服务实战系列教程的更多相关文章
- 使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【开篇】【持续更新中。。。】
最近发现web api很火,园内也有各种大神已经在研究,本人在asp.net官网上看到一个系列教程,原文地址:http://bitoftech.net/2013/11/25/detailed-tuto ...
- 使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【九】——API变了,客户端怎么办?
系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html 前言 一旦我们将API发布之后,消费者就会开始使用并和其他的一些数据混在一起.然而,当新的需求出现 ...
- 使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【八】——Web Api的安全性
系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html 前言 这一篇文章我们主要来探讨一下Web Api的安全性,到目前为止所有的请求都是走的Http协议 ...
- [转]使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【八】——Web Api的安全性
本文转自:http://www.cnblogs.com/fzrain/p/3552423.html 系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html ...
- 使用ASP.NET WEB API构建基于REST风格的服务实战系列教程(一)——使用EF6构建数据库及模型
系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html 使用Entity Framework Code First模式构建数据库对象 已经决定使用EF C ...
- 使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【二】——使用Repository模式构建数据库访问层
系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html 前言 在数据访问层应用Repository模式来隔离对领域对象的细节操作是很有意义的.它位于映射层 ...
- 使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【三】——Web Api入门
系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html 前言 经过前2节的介绍,我们已经把数据访问层搭建好了,从本章开始就是Web Api部分了.在正式开 ...
- 使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【四】——实现模型工厂,依赖注入以及格式配置
系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html 前言 在上一篇中,我们已经初步开始使用Web Api了,但同时出现了一些很多不足之处,本章我们就着 ...
- 使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【五】——在Web Api中实现Http方法(Put,Post,Delete)
系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html 前言 在Web Api中,我们对资源的CRUD操作都是通过相应的Http方法来实现——Post(新 ...
随机推荐
- HDU 1198 Farm Irrigation (并检查集合 和 dfs两种实现)
Farm Irrigation Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- RSA加密解密(PHP Demo)
$private_key = '-----BEGIN RSA PRIVATE KEY----- MIICXQIBAAKBgQDpoODVtnSztGyb//p+g/Ob36jb3jzWzS2qovOj ...
- 【iOS发展-81】setNeedsDisplay刷新显卡,并CADisplayLink它用来模拟计时器效果
(1)效果 (2)源码下载(假设提示没有小图片的话,自己找一个替换一下即可,看到效果即可) http://download.csdn.net/detail/wsb200514/8176339 (3)总 ...
- Struts1和Struts2对照
最近学习Struts1和Struts2.好多人.提到非常多的信息. Struts2不从Struts1进化. Struts2的前身WebWork. 呢,看了一些资料,下边就来比較比較. 一.架构分析 S ...
- PYTHON单元测试
PYTHON开发入门与实战11-单元测试 1. 单元测试 本章节我们来讲讲django工程中如何实现单元测试,单元测试如何编写以及在可持续项目中单元测试的重要性. 下面是单元测试的定义: 单元测试是开 ...
- Git提交代码的处理流程(转)
Jerry 工作在wchar_support分支.他改变了名称的功能和测试后,他提交他的变化. [jerry@CentOS src]$ git branch master * wchar_suppor ...
- java多线程(同步和死锁,生产者和消费者问题)
首先我们来看看同步与死锁: 所谓死锁.这是A有banana,B有apple. A至B说:你把apple对我来说,,我会banana给你. B至A说:你把banana对我来说,,我会apple给你. 可 ...
- Alice's Chance
id=1698" style="background-color:rgb(51,255,51)">主题链接 意甲冠军: 爱丽丝要拍电影.有n部电影,规定爱丽丝第i部 ...
- 各大oj题目分类(转)
POJ题目分类 | POJ题目分类 | HDU题目分类 | ZOJ题目分类 | SOJ题目分类 | HOJ题目分类 | FOJ题目分类 | 模拟题: POJ1006POJ1008POJ1013POJ1 ...
- T4模版引擎之生成数据库实体类
在通过T4模版引擎之基础入门 对T4有了初步印象后,我们开始实战篇.T4模板引擎可以当做一个代码生成器,代码生成器的职责当然是用来生成代码(这不是废话吗).而这其中我们使用的最普遍的是根据数据库生成实 ...