资讯专栏INFORMATION COLUMN

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

EastWoodYang / 2533人阅读

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

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

基本原理和概念

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

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

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

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

交互过程

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

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

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

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

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

交互过程总结如下图:

代码实现

本文的示例代码使用 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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/15987.html

相关文章

  • 浏览器缓存

    摘要:主要可分为强制缓存字段字段对比缓存字段标识浏览器行为引起的缓存变化移动端的缓存策略其实,在讲述移动端的缓存策略时,并没有分析的特别详细,只是大致的讲解了一下目前大家都在使用的缓存策略。 前言 在前端开发中,缓存有利于加快网页的加载速度,同时缓存能够被反复利用,所以可以减少流量和带宽的开销。 缓存的分类有很多种,CDN缓存、数据库缓存、代理服务器缓存和浏览器缓存。本篇将来讲解一下Web开...

    geekzhou 评论0 收藏0
  • 浏览器缓存

    摘要:主要可分为强制缓存字段字段对比缓存字段标识浏览器行为引起的缓存变化移动端的缓存策略其实,在讲述移动端的缓存策略时,并没有分析的特别详细,只是大致的讲解了一下目前大家都在使用的缓存策略。 前言 在前端开发中,缓存有利于加快网页的加载速度,同时缓存能够被反复利用,所以可以减少流量和带宽的开销。 缓存的分类有很多种,CDN缓存、数据库缓存、代理服务器缓存和浏览器缓存。本篇将来讲解一下Web开...

    geekidentity 评论0 收藏0
  • 性能优化-http缓存

    摘要:整个请求响应链的缓存机制必须遵循的特别指令。基本的缓存机制就是由这些参数形成的。如果此文章中有什么问题的话,烦请一定要指出,谢谢参考资料缓存机制浅析移动端加载性能优化浅谈浏览器的缓存机制 之前对http的缓存知识一知半解,只能说出个大概。和同事交流这块内容时稍一深入探讨就捉襟见肘,自惭形秽。故痛定思痛,花了一两天时间去研究了下这块内容,写下这篇笔记方便以后的查询与修正。 首先介绍下和缓...

    Aceyclee 评论0 收藏0
  • iOS网络缓存扫盲篇 - 使用两行代码就能完成80%的缓存需求

    摘要:缓存已然成为必备。网络请求缓存概述首先要知道,请求不能被缓存,只有请求能被缓存。缓存的思路就是将查询的参数组成的值作为,对应结果作为。的缓存需求两行代码就可满足设置缓存只需要三个步骤第一个步骤请使用请求。客户端通过状态码来决定是否使用缓存。 目录 当我们在谈论缓存的时候,我们在谈论什么? GET网络请求缓存 80%的缓存需求:两行代码就可满足 控制缓存的有效性 文件缓存:借助E...

    edagarli 评论0 收藏0
  • 掌握缓存,不再让你蓝瘦香菇

    摘要:数据库缓存当应用逻辑较为复杂,频繁进行数据库查询,很容易导致数据库不堪重荷。单位为指定设置缓存最大的有效时间,定义的是时间长短。 本文内容概要: 1 Web缓存是什么?为什么要使用它?2 Web缓存的类型3 浏览器缓存的基本知识3.1 Expires3.2 Last-modified3.3 Cache-Control3.4 ETag4 浏览器缓存机制4.1 强缓存应用4.2 协商缓存应...

    Cristic 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<