我一直在考虑在RESTful环境中批量读取和写入,我想我已经意识到我对HTTP缓存有更广泛的问题.(下面我使用逗号(",")来分隔多个记录ID,但该细节并不特定于讨论.)
我从这个问题开始:
GET
批量更新失效GET /farms/123 # get info about Old MacDonald's Farm PUT /farms/123,234,345 # update info on Old MacDonald's Farm and some others GET /farms/123
客户端和Farms服务器之间的缓存服务器如何知道/farms/123
在看到缓存时使其缓存无效PUT
?
然后我意识到这也是一个问题:
GET
通过单次(或批量)更新无效GET /farms/123,234,345 # get info about a few farms PUT /farms/123 # update Old MacDonald's Farm GET /farms/123,234,345
当缓存GET
看到PUT经过时,缓存如何知道使多个场无效?
所以我认为问题实际上只是批处理操作.然后我意识到任何关系都可能导致类似的问题.假设一个农场拥有零个或一个所有者,而一个所有者可以拥有零个或一个农场.
GET
通过更新到相关记录而失效GET /farms/123 # get info about Old MacDonald's Farm PUT /farmers/987 # Old MacDonald sells his farm and buys another one GET /farms/123
当缓存看到PUT经过时,缓存如何知道使单个GET无效?
即使您使用关系模型将模型更改为RESTful,也会遇到同样的问题:
GET /farms/123 # get info about Old MacDonald's Farm DELETE /farm_ownerships/456 # Old MacDonald sells his farm... POST /farm_ownerships # and buys another one GET /farms/123
在#3的两个版本中,第一个GET应该返回类似(在JSON中):
farm: { id: 123, name: "Shady Acres", size: "60 acres", farmer_id: 987 }
第二个GET应该返回如下内容:
farm: { id: 123, name: "Shady Acres", size: "60 acres", farmer_id: null }
但它不能!即使你ETag
恰当地使用s也没有.您不能指望缓存服务器检查ETag
s的内容 - 内容可以加密.并且您不能指望服务器通知缓存记录应该无效 - 缓存不会自己注册服务器.
那么我缺少标题吗?指示缓存的事情应该HEAD
在GET
某些资源的任何s 之前执行?如果我可以告诉缓存哪些资源可能经常更新,我想我可以忍受每个资源的双重请求.
那么一个缓存接收PUT
并知道其缓存无效而另一个缓存没有看到它的问题呢?
缓存服务器应该在收到PUT时使URI引用的实体无效(但正如您所注意到的,这并未涵盖所有情况).
除此之外,您可以在响应中使用缓存控制标头来限制或阻止缓存,并尝试处理请求标头,询问自上次提取后URI是否已被修改.
这仍然是一个非常复杂的问题,事实上仍在进行中(例如见http://www.ietf.org/internet-drafts/draft-ietf-httpbis-p6-cache-05.txt)
如果内容是加密的(至少使用SSL),代理中的缓存并不真正适用,因此这不应成为问题(尽管客户端仍然可能存在问题).