前段时间我问过Incremental updates using browser cache怎么做。 在这里,我简要总结一下这个问题 - 对于更多背景,特别是我想要这样做的原因,请参考旧问题。 我希望您审核并改进我的解决方案想法(只是一个想法,所以不要发送给我code review:D)。
客户端(单页面应用程序)从服务器获取相当大的列表。 这很好,实际上节省了服务器资源
其中一些列表是特定于用户的,另一些列表是一组用户共有的,其他列表是全局的。
所有这些列表可能随时更改,我们永远不想提供过时的数据(Cache-Control
和Expires
HTTP标头在这里没有直接用途。)
我们正在使用304 NOT MODIFIED
,这有助于 nothing 更改时的情况。
当任何变化时,更改通常很小,但HTTP根本不支持这种情况,因此我们必须发送包括未更改部分的整个列表。
我们可以发送delta,但是没有明显的方法如何通过浏览器有效地缓存它(localStorage
中的缓存或类似的远远不如我在链接问题中解释的那样)。
我们列表的一个重要属性是每个项目都有唯一的id
和最后修改的timestamp
。
timestamp
允许我们通过查找最近更改过的项目来轻松计算增量。
id
允许我们仅通过替换相应的项来应用增量(列表在内部为Map<Id, Item>
)。
这对删除不起作用,但我们暂时忽略它们。
我建议使用不同大小的多个列表(任何数字都可以使用),较长的列表可以缓存。 我们假设,一天是一个合适的时间单位,让我们使用以下三个列表:
WEEK
这是包含所有项目的基本列表,因为它们在当前周中的任意时间存在。
DAY
包含本周更改的所有项目的列表,除了今天,因为它们在当天中的某个任意时间存在。
今天更改的项目可能包括也可能不包括在内。
CURRENT
包含所有已更改今天的项目的列表刚刚。
客户端获取所有三个列表。它以WEEK
开头,应用DAY
(即插入新项并替换旧项),最后应用CURRENT
。
假设列表中有1000个项目,每天更改10个项目。
WEEK
列表包含所有1000个项目,但它可以缓存到本周末。
它的确切内容没有指定,不同的客户端可能有不同的版本(只要上面的子句中的条件成立)。
这允许服务器将数据缓存整整一周,但它也允许服务器删除它们,因为服务当前状态也很好。
DAY
列表最多包含70个项目,可以缓存到一天结束。
CURRENT
列表最多包含10个项目,只能在任何更改之前进行缓存。
客户端应该对使用的时间尺度一无所知,但需要知道要求的列表数量。像
这样的“经典”请求GET /api/order/123 // get the whole list with up to date content
将替换为三个请求,例如
GET /api/0,order/123 // get the WEEK list
GET /api/1,order/123 // get the DAY list
GET /api/2,order/123 // get the CURRENT list
通常情况下,更改确实如上所述,但有时所有项目都会立即更改。 当发生这种情况时,所有三个列表都包含所有项目,这意味着我们必须提供三倍的数据。 幸运的是,此类事件非常罕见(例如,当我们添加属性时),但我想看到一种方法可以让我们避免这种爆发?
你认为这个想法还有其他问题吗?
除了将项目标记为已删除并推迟物理删除直到缓存过期(即,在我的示例中直到星期结束)之外,是否有任何删除解决方案。
有任何改进吗?
答案 0 :(得分:2)
是的,我发现这个问题很严重。它是一个很大的列表意味着客户有很多工作要做,以减少它所需的资源。这对绩效有很大影响。
所有这些列表可能随时更改,我们绝不想提供陈旧数据
因此,您应该使用较长的缓存时间和cache-busting urls。
我们正在使用304 NOT MODIFIED
这是解决问题的最糟糕方法。检索的大部分成本都是延迟。如果您回复304响应,那么您已经承担了大部分费用 - 当您处理小块数据时,这将特别明显。 HTTP / 2有帮助(与1.0和1.1相比),但不会消除成本。
我也会质疑你原来问题中的很多假设。