问题 RESTful数据同步方法


假设以下场景 Web应用程序通过RESTful API提供资源。许多客户端使用此API。目标是使客户端上的数据与Web应用程序保持同步(在两个方向上)。

最简单的方法是询问API自客户端上次与API同步以来是否有任何资源发生了变化。这意味着客户端需要向API请求伴随时间戳的适当资源(以查看是否需要更新数据)。在我看来,这就像在不必要的带宽消耗方面开销最小的方法一样。

但是,我觉得这种方法在设计和责任方面有一些缺点。例如,API不应该处理检查资源是否过期的问题。似乎API的唯一责任应该是在被要求时提供资源而不必处理更新方面。通过遵循第二种方法,客户端每次想要更新其数据时都会要求大量数据,以使其与Web应用程序保持同步。换句话说,客户端将检查它返回的数据是否比本地存储的数据更新。如果此过程每隔几分钟发生一次,这可能会成为系统的重大负担。

我是否正确地看到了这个或者是否有一条我正在俯瞰的中间道路?


11332
2017-08-01 15:43


起源



答案:


这是一个非常常见的问题,RESTful方法可以帮助您解决问题。 HTTP(通常用于构建RESTful服务的应用程序协议)支持各种技术,可用于使API客户端与服务器端的数据保持同步。

如果客户收到了 Last-Modified 要么 E-Tag 在HTTP响应中的标头,它可以使用该信息来进行 有条件的GET 将来打电话。这允许服务器快速指示一个 304 – Not Modified 响应客户端先前存储的资源表示仍然有效且准确。这将允许服务器(或甚至更好的中间代理或缓存服务器)在响应客户端请求时尽可能高效,从而可能减少到后端数据存储的昂贵往返。

如果响应包含 Last-Modified 标题和客户希望利用它提供的性能优化,它们必须包含一个 If-Modified-Since 指令在后续GET调用同一URI时,传入它收到的相同时间戳值。这指示服务器只知道来自权威后端源的信息,如果它知道自那时以来它已经发生了变化。当然,您的服务器必须构建为支持这种技术。

类似的原则适用于 E-Tag 头。一个 E-Tag 是一个简单的哈希码,表示特定时间点资源的特定状态。如果资源以任何方式发生变化,那么它也会发生变化 E-Tag值。如果客户看到了 E-Tag 在响应中,它应该在后续GET请求中将其传递给相同的URI,从而允许服务器快速确定客户端是否具有资源的最新表示。

最后,你应该看看 长轮询技术 减少客户端向服务器发出的重复GET请求数。实质上,诀窍是向服务器发出非常长的GET请求以监视服务器数据的变化。在数据发生更改或超时超时之前,GET不会返回响应。如果是后者,客户端只需重新发出相同的长期请求以再次观察更改。另见主题 Comet和Web套接字 方法相似。


15
2017-08-01 17:12



这家伙说的是什么(使用标准HTTP功能),但不要使用 GET 为此,使用 HEAD,因为你不关心实际的数据,而是(据我所知),你关心数据是否有效。如果数据无效,则执行a GET-request检索新数据。 - Anders
^好点。 HEAD绝对更轻巧,适合这种事情。 - Brian Kelly
我有一个问题:如果客户端为某种类型的记录(例如Person.findAll())发出findAll,并假设某些记录由本地数据存储返回。客户端如何知道服务器上是否还有其他人员?或者反过来说,服务器如何判断客户端已经有哪些记录? - Panagiotis Panagi
同步是一个复杂的主题,特别是涉及多个节点时。冲突,陈旧数据,已删除数据是REST约定未直接处理的一些问题。 - Rajiv
@PanagiotisPanagi我认为你可以通过从这些记录获取所有主键或所有哈希并通过crc32进行哈希来实现。 - EThaizone Jo


答案:


这是一个非常常见的问题,RESTful方法可以帮助您解决问题。 HTTP(通常用于构建RESTful服务的应用程序协议)支持各种技术,可用于使API客户端与服务器端的数据保持同步。

如果客户收到了 Last-Modified 要么 E-Tag 在HTTP响应中的标头,它可以使用该信息来进行 有条件的GET 将来打电话。这允许服务器快速指示一个 304 – Not Modified 响应客户端先前存储的资源表示仍然有效且准确。这将允许服务器(或甚至更好的中间代理或缓存服务器)在响应客户端请求时尽可能高效,从而可能减少到后端数据存储的昂贵往返。

如果响应包含 Last-Modified 标题和客户希望利用它提供的性能优化,它们必须包含一个 If-Modified-Since 指令在后续GET调用同一URI时,传入它收到的相同时间戳值。这指示服务器只知道来自权威后端源的信息,如果它知道自那时以来它已经发生了变化。当然,您的服务器必须构建为支持这种技术。

类似的原则适用于 E-Tag 头。一个 E-Tag 是一个简单的哈希码,表示特定时间点资源的特定状态。如果资源以任何方式发生变化,那么它也会发生变化 E-Tag值。如果客户看到了 E-Tag 在响应中,它应该在后续GET请求中将其传递给相同的URI,从而允许服务器快速确定客户端是否具有资源的最新表示。

最后,你应该看看 长轮询技术 减少客户端向服务器发出的重复GET请求数。实质上,诀窍是向服务器发出非常长的GET请求以监视服务器数据的变化。在数据发生更改或超时超时之前,GET不会返回响应。如果是后者,客户端只需重新发出相同的长期请求以再次观察更改。另见主题 Comet和Web套接字 方法相似。


15
2017-08-01 17:12



这家伙说的是什么(使用标准HTTP功能),但不要使用 GET 为此,使用 HEAD,因为你不关心实际的数据,而是(据我所知),你关心数据是否有效。如果数据无效,则执行a GET-request检索新数据。 - Anders
^好点。 HEAD绝对更轻巧,适合这种事情。 - Brian Kelly
我有一个问题:如果客户端为某种类型的记录(例如Person.findAll())发出findAll,并假设某些记录由本地数据存储返回。客户端如何知道服务器上是否还有其他人员?或者反过来说,服务器如何判断客户端已经有哪些记录? - Panagiotis Panagi
同步是一个复杂的主题,特别是涉及多个节点时。冲突,陈旧数据,已删除数据是REST约定未直接处理的一些问题。 - Rajiv
@PanagiotisPanagi我认为你可以通过从这些记录获取所有主键或所有哈希并通过crc32进行哈希来实现。 - EThaizone Jo