文档章节

缓存 HTTP POST请求和响应

zcl那都不是事
 zcl那都不是事
发布于 2016/05/12 21:41
字数 1745
阅读 757
收藏 9
点赞 2
评论 1

HTTP缓存的基本目的就是使应用执行的更快,更易扩展,但是HTTP缓存通常只适用于idempotent request(可以理解为查询请求,也就是不更新服务端数据的请求),这也就导致了在HTTP的世界里,一般都是对Get请求做缓存,Post请求很少有缓存。

然而,我们有的时候也会遇到一些idempotent request并不能通过Get来实现的时候,例如,搜索API通常会需要很多的参数,尤其是那些拥有很多属性的产品,而这些属性都必须通过参数来传递。问题来了,如果请求携带的参数超过了GET请求的限制长度怎么办,下面有一些回答:

  • 当需要非常多的参数的时候,你可能需要重新评估一些接口的设计,减少一些参数来满足Get的限制。

  • 规范中并没有强制性限制,所以我们不应该责备http规范,但是http客户端和服务器会有限制,例如有的支持最大的上限为8k,有的为2k

看到这些,我们发现上面这些回答都不是很满意,他们并没有给出实质的解决方案。

HTTP 缓存基础

在看其他内容之前,让我们来快速看一些http缓存的机制。

HTTP缓存涉及到客户端、代理和服务器。这篇文章我们将讨论的主要是代理服务器,位于客户端和服务器之间。通常情况下,反向代理部署在服务器附近,正向代理通常离客户端比较近。下图展示了基本的拓扑结构,正向代理的高速缓存命中节省带宽,并减少往返时间和延迟,反向代理的高速缓存命中降低服务器的负载。

 

HTTP的协议规范允许满足下列条件中其一的以缓存来响应。

  • 缓存的响应与原始服务器的响应是一致的,简而言之就是说代理可以保证缓存的响应和服务器的响应之间的语义等价。

  • 到客户端的响应的新鲜度是可以接受的

  • 到客户端的响应的新鲜度不可接受,但是附加了合适的警告。

协议中还有更多的关于请求响应头和控制的规范,可以参看:http://tools.ietf.org/html/rfc2616

一个典型的代理服务器缓存idempotent request。该代理获取请求,检查头信息,然后发送到服务器,收到服务器的响应后,检查,如果是可缓存的,则将这个响应以URL为key(会携带一部分头信息)以响应为内容缓存起来。这种办法对已Get请求很有效,因为反复调用相同的URL将会有相同的响应。代理可以利用idempotent request来缓存get请求。但是对于不是idempotent request的post请求来讲,不能使用URL和头信息来作为key进行缓存,因为响应可能是不同的,相同的URL但是得到了不同的结果。

POST内容摘要

解决办法是将POST的内容(附带一部分头信息),做一个摘要,将摘要附在URL后面,使用这个来作为缓存的key。换句话说,缓存主键被修改为包括URL以及一些请求体,后续的拥有相同的请求体的请求将会命中缓存。在实践的过程中我添加了一些头脑保证缓存的唯一性。通常的,虽然我们没有一个标准的推荐算法,如果你使用md5的话,你可以加上Content-MD5作为一个头

 

现在的问题就是该区分idempotent request的post请求和非idempotent request的post请求了。这里有几种方法可以处理这个问题

  • 在代理中配置URL的匹配模式,代理如果匹配到非idempotent request请求就不缓存。

  • 在头中添加context-aware以区分不同的请求

  • 基于缓存逻辑的一些命名约定,例如API的名称以set、add、delete等开头的就不被缓存。

处理非idempotent request请求

下面我们来解决非idempotent request的问题

当出现下面的任何一种情况的时候,将请求发给原服务器

  • 如果URL在“DO NOT CACHE”列表中

  • 如果摘要不匹配

  • 过了缓存的有效时间

  • 任何收到需要重新验证的请求的时候

附加可能已经是过时的内容的警告,以满足规范

允许用户通过客户端的工具关闭代理来直接访问原服务器。

我们使用定制的缓存POST请求的key的方式使用Apache Traffic Server实现了这个解决方案。

优势

这个解决方案提供了下面的好处

  • 加快了重复请求的效率,减少了代理到原服务器之间的往返

  • 一个用户的请求不仅可以用作缓存该用户的后续请求,其他用户也可共享

  • 节省了代理和原服务器之间的带宽

这里有一个请求API响应时间的对比,

无缓存延时:188ms

有缓存延时:90ms

这个解决方案的变种可以用在正向代理和反向代理,甚至两者都用

缓存握手

为了从该解决方案的最大价值,在这个解决方案中,我们在客户端和服务器端部署了正向代理和反向代理。客户端发送请求到正向代理,代理服务器在高速缓存没有命中的情况下发送请求的摘要到反向代理。反响代理在缓存中查找,如果找到则将请求返回,所不同的一点是,我们从正向代理到反向代理并不发送完整的请求。服务器向反向代理发送完整的响应,而反向代理只向正向代理发送响应的摘要。由于反向代理和服务器之间一般是出于同一个局域网中,延迟较小,而正向代理和客户端之间的延迟也比较小,当大量的重复请求发送的时候就能够体会着这种解决方案的优势了

 

总结

HTTP的缓存不仅可以用于Get请求,通过对Post体的摘要、处理非idempotent request请求和区别idempotent request和非idempotent request请求,可以实现对Post的缓存。当然为了进一步提高效率,可以使用缓存握手的方式,在互联网上只发送摘要,在客户端和正向代理以及反向代理和服务端之间的局域网类发送完整的消息体。

© 著作权归作者所有

共有 人打赏支持
zcl那都不是事
粉丝 8
博文 7
码字总数 5474
作品 0
承德
加载中

评论(1)

f逍遥一世
f逍遥一世
说的不错!
缓存 HTTP POST请求和响应

HTTP缓存的基本目的就是使应用执行的更快,更易扩展,但是HTTP缓存通常只适用于idempotent request(可以理解为查询请求,也就是不更新服务端数据的请求),这也就导致了在HTTP的世界里,一般...

王振威
2012/10/13
12.2K
7
金牌信通V8-生意虎信验证码插件

金牌信通V8-生意虎信验证码插件 WebServices 1 接口说明 2 2 发送接口 2 2.1 调用接口 2 2.2 参数说明 2 2.3 请求和响应 3 2.3.1 SOAP 1.2请求 3 2.3.2 SOAP 1.2响应 4 2.3.3 HTTP POST请求 ...

维美金牌信通
2015/06/24
0
0
JavaEE 要懂的小事:一、图解Http协议

Writer :BYSocket(泥沙砖瓦浆木匠) 微 博:BYSocket 豆 瓣:BYSocket FaceBook:BYSocket Twitter :BYSocket 泥瓦匠记得和左潇龙【博客园】上次聊天时,龙哥问了个Session的问题。我当时...

泥沙砖瓦浆木匠
2015/05/19
0
14
html 的 meta 总结,html 标签中 meta 属性使用介绍

引子 之前的我的博客中对于meta有个介绍,例如:http://www.haorooms.com/post/liulanqthinkie 浏览器安全性想到的这篇文章,中间介绍了meta下面IE的一些属性,可以实现页面之间的过渡转换。...

Jack088
2015/11/12
0
0
html的meta总结,html标签中meta属性使用介绍

引子 之前的我的博客中对于meta有个介绍,例如:http://www.haorooms.com/post/liulanqthink_ie 浏览器安全性想到的这篇文章,中间介绍了meta下面IE的一些属性,可以实现页面之间的过渡转换。...

Daniel_s
2016/01/27
9
0
Python学习之urlib模块和urllib2模块学习

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://john88wang.blog.51cto.com/2165294/1441495 一 urlib模块 利用urllib模块...

Airship
2016/03/23
56
0
android与web service 交换,soap协议和HTTP协议有什么区别?

我发现一些web service 开放接口里都有两种接口,一种是基于SOAP的,一种是基于http的。 例如: 一、 SOAP 1.2 以下是 SOAP 1.2 请求和响应示例。所显示的占位符需替换为实际值。 POST /WebS...

剑麟
2013/05/21
2.3K
1
Android开发之OkHttp3.4.x

HTTP是现代应用程序访问网络的一种方式。网络中很多请求就是使用的http方式,来访问网络的。 Android从4.4开始,HttpUrlConnection开始使用okhttp作为底层实现。实现原理如下图: 这篇博客简...

墨宇hz
2016/12/04
0
0
防止表单重复提交的八种简单有效的策略

表单重复提交是在多用户Web应用中最常见、带来很多麻烦的一个问题。有很多的应用场景都会遇到重复提交问题,比如: 点击提交按钮两次。 点击刷新按钮。 使用浏览器后退按钮重复之前的操作,导...

为了美好的明天
04/19
0
0
android 之访问WebService显示手机号码归属地

发送XML 通过URL封装路径打开一个HttpURLConnection 设置请求方式,Content-Type和Content-Length XML文件的Content-Type为:text/xml; charset=UTF-8 使用HttpURLConnection获取输出流输出数...

长平狐
2012/09/03
2.6K
1

没有更多内容

加载失败,请刷新页面

加载更多

下一页

【面试题】盲人坐飞机

有100位乘客乘坐飞机,其中有一位是盲人,每位乘客都按自己的座位号就坐。由于盲人看不见自己的座位号,所以他可能会坐错位置,而自己的座位被占的乘客会随便找个座位就坐。问所有乘客都坐对...

garkey
43分钟前
0
0
谈谈神秘的ES6——(二)ES6的变量

谈谈神秘的ES6——(二)ES6的变量 我们在《零基础入门JavaScript》的时候就说过,在ES5里,变量是有弊端的,我们先来回顾一下。 首先,在ES5中,我们所有的变量都是通过关键字var来定义的。...

JandenMa
今天
1
0
arts-week1

Algorithm 594. Longest Harmonious Subsequence - LeetCode 274. H-Index - LeetCode 219. Contains Duplicate II - LeetCode 217. Contains Duplicate - LeetCode 438. Find All Anagrams ......

yysue
今天
0
0
NNS拍卖合约

前言 关于NNS的介绍,这里就不多做描述,相关的信息可以查看NNS的白皮书http://doc.neons.name/zh_CN/latest/nns_background.html。 首先nns中使用的竞价货币是sgas,关于sgas介绍可以戳htt...

红烧飞鱼
今天
1
0
Java IO类库之管道流PipeInputStream与PipeOutputStream

一、java管道流介绍 在java多线程通信中管道通信是一种重要的通信方式,在java中我们通过配套使用管道输出流PipedOutputStream和管道输入流PipedInputStream完成线程间通信。多线程管道通信的...

老韭菜
今天
0
0
用Python绘制红楼梦词云图,竟然发现了这个!

Python在数据分析中越来越受欢迎,已经达到了统计学家对R的喜爱程度,Python的拥护者们当然不会落后于R,开发了一个个好玩的数据分析工具,下面我们来看看如何使用Python,来读红楼梦,绘制小...

猫咪编程
今天
1
0
Java中 发出请求获取别人的数据(阿里云 查询IP归属地)

1.效果 调用阿里云的接口 去定位IP地址 2. 代码 /** * 1. Java中远程调用方法 * http://localhost:8080/mavenssm20180519/invokingUrl.action * @Title: invokingUrl * @Description: * @ret......

Lucky_Me
今天
1
0
protobuf学习笔记

相关文档 Protocol buffers(protobuf)入门简介及性能分析 Protobuf学习 - 入门

OSC_fly
昨天
0
0
Mybaties入门介绍

Mybaties和Hibernate是我们在Java开发中应用的比较多的两个ORM框架。当然,目前Mybaties正在慢慢取代Hibernate,这是因为相比较Hibernate而言Mybaties性能更好,响应更快,更加灵活。我们在开...

王子城
昨天
2
0
编程学习笔记之python深入之装饰器案例及说明文档[图]

编程学习笔记之python深入之装饰器案例及说明文档[图] 装饰器即在不对一个函数体进行任何修改,以及不改变整体的原本意思的情况下,增加函数功能的新函数,因为这个新函数对旧函数进行了装饰...

原创小博客
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部