使用浏览器缓存进行增量更新的解决方案

时间:2018-05-04 00:44:37

标签: http caching client-server single-page-application

前段时间我问过Incremental updates using browser cache怎么做。 在这里,我简要总结一下这个问题 - 对于更多背景,特别是我想要这样做的原因,请参考旧问题。 我希望您审核并改进我的解决方案想法(只是一个想法,所以不要发送给我code review:D)。

问题

客户端(单页面应用程序)从服务器获取相当大的列表。 这很好,实际上节省了服务器资源

  • 可以向多个客户提供相同的列表
  • 并且客户端进行过滤和排序,而不会一次又一次地打扰服务器。

其中一些列表是特定于用户的,另一些列表是一组用户共有的,其他列表是全局的。 所有这些列表可能随时更改,我们永远不想提供过时的数据(Cache-ControlExpires HTTP标头在这里没有直接用途。)

我们正在使用304 NOT MODIFIED,这有助于 nothing 更改时的情况。 当任何变化时,更改通常很小,但HTTP根本不支持这种情况,因此我们必须发送包括未更改部分的整个列表。 我们可以发送delta,但是没有明显的方法如何通过浏览器有效地缓存它(localStorage中的缓存或类似的远远不如我在链接问题中解释的那样)。

我们列表的一个重要属性是每个项目都有唯一的id和最后修改的timestamptimestamp允许我们通过查找最近更改过的项目来轻松计算增量。 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

问题

通常情况下,更改确实如上所述,但有时所有项目都会立即更改。 当发生这种情况时,所有三个列表都包含所有项目,这意味着我们必须提供三倍的数据。 幸运的是,此类事件非常罕见(例如,当我们添加属性时),但我想看到一种方法可以让我们避免这种爆发?

你认为这个想法还有其他问题吗?

除了将项目标记为已删除并推迟物理删除直到缓存过期(即,在我的示例中直到星期结束)之外,是否有任何删除解决方案。

有任何改进吗?

1 个答案:

答案 0 :(得分:2)

是的,我发现这个问题很严重。它是一个很大的列表意味着客户有很多工作要做,以减少它所需的资源。这对绩效有很大影响。

  

所有这些列表可能随时更改,我们绝不想提供陈旧数据

因此,您应该使用较长的缓存时间和cache-busting urls

  

我们正在使用304 NOT MODIFIED

这是解决问题的最糟糕方法。检索的大部分成本都是延迟。如果您回复304响应,那么您已经承担了大部分费用 - 当您处理小块数据时,这将特别明显。 HTTP / 2有帮助(与1.0和1.1相比),但不会消除成本。

我也会质疑你原来问题中的很多假设。