zoukankan      html  css  js  c++  java
  • [翻译]创建ASP.NET WebApi RESTful 服务(11)

    本章介绍通过使用Ali Kheyrollahi开发的CacheCow来实现服务器端的缓存。所有代码现在都可以在GitHub上下载。

    我们将要实现的缓存方式叫做Conditional Requests,实现方式其实很简单。客户端通过在请求Header中包含ETag信息,实现和服务器的交互,确认当前客户端包含的部分数据是否已经被修改,有则拉取,没有服务器端就返回304(Not Modified)和空的消息体。通过Conditional Requests,客户端不断的发起请求,但只有客户端数据过期时才会返回200和对应的数据信息。

    什么是ETag(Entity Tag)?

    ETag有一个基于String的惟一键,服务端为每种类型的资源单独生成,可以看做是资源的校验位,用来控制对应的资源是否被修改。

    ETag有强标识和弱标识两种,弱标识以W开头,形如“W/53fsfsd322”;强标识一般形如“534928jhfr4”。弱标识一般标明缓存的资源只会被使用一小段时间(In Momory Caching)。而强标识则意味着资源会被持久化,资源在客户端和服务端都是完全相同(字节相等,byte-per-byte identical)的。(注:留待查明,作者的说法可能有问题,文章最后提到了一些不同的观点)

    ETag的原理

    下图展示了一个过程,当客户端通过HTTP GET请求Id为4的course资源时,如果该资源从未被请求,那么服务端直接返回该资源并在Response Header中添加了一个ETag标识。

    如果客户端再次请求统一资源,可以再GET请求中包含一个叫做If-None-Match的Header,其值为对应的ETag。当服务器收到时,就会进行匹配。如果未改动,返回304和空的消息体。否则,返回最新的记录。

    GET和DELETE都可以使用这个If-None-Match的Header,但是更新资源时如果要用到ETag,需要在对应的PUT或者PATCH请求中使用If-Match的Header,服务器同样会对ETag进行检查。如果服务端资源信息已被更新,就会返回412(Precondition Failed),客户端需要进行必要的提示和处理,本次修改将不能被服务端接受。

    WebApiCachingETag

    配置CacheCow

    从Nuget控制台可以通过命令Install-Package CacheCow.Server -Version 0.4.12获取到CacheCow的最新版本。包含两个dll文件。

    配置的过程就是创建一个CacheHandler实例,并将其诸如到Web API的处理管线中,这个Handler将用来对每个请求进行拦截,并对Response进行必要的处理。

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

    到目前为止,我们的API可以实现基于内存的缓存,这也是CacheCow的默认配置。对于单个服务器或者演示,而言已经足够。但是如果要处于负载均衡或WebFarm状态时,缓存状态必须单独存储,并在不同的服务器间进行共享,因此需要配置额外的存储介质,如SQL Server,MongoDB,MemCache等。

    基于内存的缓存测试

    进行后续操作前,先对请求进行一个测试。打开Fiddler,选择Composer选项卡,构造一个GET请求,类似于:http://localhost:{your_port}/api/courses/4 ,请求的结果如下:

    CacheCowGet-WeakeTag

    你应该注意到这些:

    1. 返回状态码为200,表示服务端在消息体返回了资源的内容;
    2. 有两个新的Header被添加到Response中;注意,后续我将介绍将Last-Modified头去掉以免互相影响;
    3. 图中的ETag是弱标识类型(以W开头),标示数据缓存在内存中,一旦IIS重启,缓存会丢失

    接下来,对请求进行模拟。在Headers中添加If-None-Match,执行后的结果如下:

    CacheCow-WeakeTag-Response

    值得注意的是,返回的ETag标识和传入的标识是相同的。

    通过SQL Server进行缓存

    这种方式需要安装必要的dll,在NuGet控制台中通过“Install-Package CacheCow.Server.EntityTagStore.SqlServer -Version 0.4.11”进行安装,然后修改WebApiConfig文件如下:

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

    我们向CacheHandler中传递了数据库的信息,并去掉了LastModifiedHeader。如果你在这个时候测试请求,会接收到一个500错误(Internal Server Error),因为我们还需要创建必要的存储过程和表。定位到NuGet包的位置,一般类似于“{projectpath}packagesCacheCow.Server.EntityTagStore.SqlServer.0.4.11scripts”,然后再数据库中执行即可。

    进行上文类似的测试后,检索CacheState表,可以看到如下信息:

    CacheCow-CacheStateTable

    接下来再发生的GET请求都会直接返回304,知道数据被修改。现在我们接着对数据进行Update,返回情况如下图。

    CacheCow-PUT-StrongETag

    这个PUT请求分析如下:

    1. 返回状态码为200,意味着客户端的数据是最新的,并且更新也被正确的执行了;
    2. 返回了新的ETag,因为服务端的数据已经被修改;客户端接下来的访问都必须使用新的ETag;
    3. CacheStore记录了新的ETag值和Last Modified Date。

    如果再次执行刚才的请求,将会直接返回412错误。

    CacheCow-If-Match-PreconditionFailed

    来自评论和思考

    简单说,这种缓存方式对单个或少量的API十分有效。但是,如果存在拉取一个大的列表如/api/courses这样,就会比较难以处理。特别的,请求返回时,对逐个对象进行判断也是十分费事的。作者建议对此类的API关闭缓存,然后通过AttributeBasedCancheControlPolicy对单一的请求进行标识。

    另外,有个人提到W/其实并不标识缓存的存储介质类型,他用来标识数据是语义相等,而强标识则意味着字节相等。这个人还提出了一套基于ActionFilter的解决方案

    系列到此结束,完整代码现在都可以在GitHub上下载。

    来源:http://bitoftech.net/2014/02/08/asp-net-web-api-resource-caching-etag-cachecow/

  • 相关阅读:
    Java抓取网页数据(原网页+Javascript返回数据)
    jvm调优
    Windows系统下nodejs安装及配置
    《学习opencv》笔记——矩阵和图像操作——cvCalcCovarMatrix,cvCmp and cvCmpS
    数据结构与算法一
    Oracle Hints具体解释
    hibernate-4.3.5安装配置
    linux-多线程
    利用JasperReport+iReport进行Web报表开发
    linux下tar.xz 文件解压
  • 原文地址:https://www.cnblogs.com/tukzer/p/3665114.html
Copyright © 2011-2022 走看看