HTTP中的ETag在移动客户端的应用

标签: http etag ios | 发表时间:2015-11-30 06:37 | 作者:joywek
分享到:
出处:http://segmentfault.com/blogs

绝大多数移动客户端在设计网络模块时,都会选用HTTP作为客户端和服务端通信的网络协议。随着业务的不断发展以及用户量的持续增长,整个客户端的稳定性和性能会逐渐成为关注的焦点,其中网络的性能优化更是重中之重,本文介绍的 ETag 缓存技术,可以在缓存数据的同时做到数据的实时更新,适用于对数据实效性要求较高的业务。

基本原理和概念

相同的两次请求返回的结果相同时,第一次返回的结果缓存在客户端,第二次服务端不再返回结果,仅返回一个特殊的状态码,告诉客户端第二次请求的结果与上次相同,可以直接使用上次返回的数据。

实现中,会用到HTTP头中的两个字段:

  • ETag 返回应答数据的标记,服务端生成发送给客户端

  • If-None-Match 同样的请求,上一次返回的 ETag 值

交互过程

  • 服务端在将数据发送给客户端之前,首先计算应答数据的摘要(通常是MD5),把计算结果作为 ETag 的值,和数据一同发送给客户端。

  • 客户端收到应答数据后,检测 HTTP Header 中是否有 ETag 字段,如有则缓存应答数据和 ETag 的值。

  • 客户端再次发起同一请求时,读取上次缓存的 ETag 值,将其作为 If-None-Match 的值,并与请求数据一同发送给服务端。

  • 服务端收到请求,执行请求,在把应答数据返回给客户端之前计算摘要,并与客户端上报的摘要比较,如果两次摘要相同,说明本次的应答数据与上一次请求的应答数据相同,且客户端已缓存该数据,则简单返回304错误。

  • 客户端收到304错误,直接读取本地缓存的数据返回给调用网络模块的业务方。

交互过程总结如下图:

ETag

代码实现

本文的示例代码使用 NSURLSession 实现,由于 NSURLSession 完善的缓存策略,为了演示 ETag 的用法,需要先关闭缓存。

  let config = NSURLSessionConfiguration.defaultSessionConfiguration()
config.requestCachePolicy = NSURLRequestCachePolicy.ReloadIgnoringCacheData
let session = NSURLSession(configuration: config)

NSURLSessionConfiguration 定义了 NSURLSession 在上传和下载时的行为及策略,我们指定了请求的缓存策略为 ReloadIgnoringCacheData, 意思就是在请求时不使用本地缓存。

创建请求的 NSURLRequest 对象:

  let url = NSURL(string: "http://www.joywek.com/50x.html")!
let request = NSMutableURLRequest(URL: url)

上面会下载指定静态页面的内容,这个页面是放在 Nginx 的服务器上,Nginx 默认会对应答数据计算 ETag。当然,在实际的应用中请求的都是动态数据,服务器要动态计算 ETag 的值。

设置 HTTP Header 中的 If-None-Match 字段:

  if let tag = self.findTagByURL(url) {
    request.addValue(tag, forHTTPHeaderField: "If-None-Match")
}

在发起请求时,先检查相同的请求是否存在 ETag,如果存在就,就意味着上次请求的应答数据已缓存。

发起请求并处理应答数据:

  self.dataTask = session.dataTaskWithRequest(request,
    completionHandler: { (var data, response, error) -> Void in
        data = self.handleResponse(response!, data!, request)
})
self.dataTask?.resume()

如果 HTTP 返回的状态码是 200,说明是服务器正常返回数据,此时记录 ETag 的值并缓存应答数据:

  if (resp.statusCode == 200) {
    self.etags[response.URL!] = resp.allHeaderFields["ETag"] as? String
    let cachedResponse = NSCachedURLResponse(response: resp, data: data)
    NSURLCache.sharedURLCache().storeCachedResponse(cachedResponse, forRequest: request)
    return data
}

如果返回 304,说明应答数据没有变化,与上次请求的一样,则直接返回缓存中的数据:

  else if (resp.statusCode == 304) {
    let cachedResponse = NSURLCache.sharedURLCache().cachedResponseForRequest(request)
    return cachedResponse?.data
}

关于演示 Demo

下载地址: http://www.joywek.com/res/ETagExample.zip

相关 [http etag 移动] 推荐:

HTTP中的ETag在移动客户端的应用

- - SegmentFault 最新的文章
绝大多数移动客户端在设计网络模块时,都会选用HTTP作为客户端和服务端通信的网络协议. 随着业务的不断发展以及用户量的持续增长,整个客户端的稳定性和性能会逐渐成为关注的焦点,其中网络的性能优化更是重中之重,本文介绍的 ETag 缓存技术,可以在缓存数据的同时做到数据的实时更新,适用于对数据实效性要求较高的业务.

YSlow—— 配置ETag

- - Taobao QA Team
实体标签(Entity Tag),是server和browser确认缓存组件的有效性的一种机制.   个人觉得,如果Expires是时间戳,ETag类似版本戳. ETag的问题在于,通常用组件的某些属性(大小、时间、等)来构造它,这些属性对于特定的、寄宿了网站的服务器来说是唯一的. 当浏览器从一台服务器上获取了原始组件,之后,又向另外一台不同的服务器发起请求时,ETag是不会匹配的.

Expires / Cache-Control / Last-Modified / If-Modified-Since / ETag / If-None-Match 区别使用

- - 小彰
本文主要讲解 web缓存的应用.. Expires / Cache-Control / Last-Modified / If-Modified-Since / ETag / If-None-Match 的区别以及使用详解. 为了演示体现缓存的作用,先删除所有的浏览器缓存,然后以如下四种方式访问baidu网站,期间使用 Pagetest作为测试软件,这是一个搭配IE使用的软件,功能上类似HttpWatch,不过它是免费的,有关Pagetest的用法可以参考官方文章提供的 教程:.

expires与ETag控制页面缓存的优先级

- - ITeye博客
我在实际的项目中使用了Etag缓存技术,使Web界面访问速度提升了很多,现在给大家分享相关的经验. expires指令控制HTTP应答中的“Expires”和“Cache-Control”Header头部信息,启动控制页面缓存的作用. time:可以使用正数或负数. “Expires”头标的值将通过当前系统时间加上设定time值来设定.

HTTP Headers 入门

- johnny - Time Machine
非常感谢 @ytzong 同学在twitter上推荐这篇文章,原文在此. 本文系统的对HTTP Headers进行了简明易懂的阐述,我仅稍作笔记. 什么是HTTP Headers. HTTP是“Hypertext Transfer Protocol”的所写,整个万维网都在使用这种协议,几乎你在浏览器里看到的大部分内容都是通过http协议来传输的,比如这篇文章.

HTTP基础

- - ITeye博客
HTTP的结构主要包括下面几个要点:. HTTP的版本主要有1.0,1.1 和更高版本.    1.1 及以上版本允许在一个TCP连接上传送多个HTTP协议,1.0能 .    1.1 及以上版本多个请求和响应可以重叠,1.0不能.    1.1 增加了很多的请求头和响应头.     一个请求行,若干小心头,以及实体内容,其中的一些消息头和实体内容是可选的,消息头和实体内容需要空行隔开.

HTTP Header 详解

- - 博客园_Ruby's Louvre
HTTP(HyperTextTransferProtocol)即超文本传输协议,目前网页传输的的通用协议. HTTP协议采用了请求/响应模型,浏览器或其他客户端发出请求,服务器给与响应. 就整个网络资源传输而言,包括message-header和message-body两部分. 首先传递message- header,即 http header消息.

http-kit 1.2 发布

- - 开源中国社区最新新闻
Http-kit 是主要由Java 和Clojure开发,为Clojure定制的零依赖的Http lib,包括异步的高性能HTTP Server 和 HTTP Client. 在普通的PC上进行性能测试时,http-kit server 每秒能处理数万个请求. 修复处理文件上传时,content-type没能正确处理.

HTTP缓存算法

- - PHP源码阅读,PHP设计模式,PHP学习笔记,项目管理-胖胖的空间
HTTP协议缓存的目标是去除许多情况下对于发送请求的需求和去除许多情况下发送完整请求的需求. 以不发送请求或减少请求传输的数据量来优化整个HTTP架构,此目标的实现可以产生如下好处:. 降低对原始服务器的请求量. 减少了传送距离,降低了因为距离而产生的时延. 缓存基本处理过程包括七个步骤. 接收 – 缓存从网络中读取抵达的请求报文.

HTTP头部详解

- - CSDN博客推荐文章
HTTP(HyperTextTransferProtocol)是超文本传输协议的缩写,它用于传送WWW方式的数据,关于HTTP 协议的详细内容请参考RFC2616. HTTP协议采用了请求/响应模型. 客户端向服务器发送一个请求,请求头包含请求的方法、URI、协议版本、以及包含请求修饰符、客户信息和内容的类似于MIME的消息结构.