ReST 低延迟 - 我应该如何在上传挂起时回复 GET?

ReST low latency - how should I reply to a GET while an upload is pending?

我正在设计 ReST API which follows the basic CRUD 模式。

我的 API 可以收到更新资源的请求,这可能需要很短的时间来处理。理想情况下,我想通知客户新版本即将可用,并且我缓存的版本实际到期时间存在一些不确定性。

所以我打算使用这样的过程(欢迎​​改进):

client: GET /some/item
myapi:  200 OK
        last-modified: time-stamp-of-v1
        etag: some-hash-relating-to-v1-of-my-item-in-this-format
        content: json or whatever
         data/for/some/item/v1... 

client: PUT /some/item
        if-match: some-hash-relating-to-v1-of-my-item-in-this-format
        content: json or whatever
         data/for/some/item/v2... 

myapi:  202 ACCEPTED,   
        content: json or whatever
         time-accepted: time-stamp-after-v1-but-before-v2
         your item will be at /some/item
         here is a URI /some/taskid to track progress

上传待处理:

client: GET /some/item
myapi:  200 OK
        some/item ... 
        last-modified: time-stamp-of-v1
        etag: some-hash-relating-to-v1-of-my-item-in-this-format
>>>>    expires: time-stamp-after-v1-but-before-v2 <<<
>>>>    warning: 110 Response is stale    <<<<
        content: json or whatever
         data/for/some/item/v1... 

client: GET /some/task/id
myapi:  200 OK
        content: json or whatever
         time-accepted: time-stamp-after-v1-but-before-v2
         your item will be at /some/item
         status/of/upload/v2... 

任务完成后:

client: GET /some/item
myapi:  200 OKAY
        some/item/v2 ... 
        last-modified: time-stamp-of-v2
        etag: some-hash-relating-to-v2-of-my-item-in-this-format
        content: json or whatever
         data/for/some/item/v2... 

client: GET /some/task/id
myapi:  303 SEE OTHER
         look-here: /some/item

如果您是代理人并且知道您的内容已经过时,您可以将 "warning: 110 - response is stale" 放在 header 中。 但是,在这种情况下,数据实际上还不是无效的。 我想说的是,我可以保证它在我收到并传递上传请求之前一直有效(time-stamp-after-v1-but-before-v2或稍后,就好像我正在与上传服务器联系一样)。在我收到上传请求时它还没有真正过期。我只是希望它会。 (实际上,如果请求失败,它可能根本不会更新)。

现在默认选择只提供旧内容,让客户端自己跟上。这具有高延迟。如果可以的话,我想做得更好。

例如,如果客户端知道文档即将过期,它可能会更频繁地轮询,或者它可能会尝试将连接升级到 web-socket 并在我收到更新时发送更新(会仍然算作 ReST?)

还有另一种情况,必须不惜一切代价避免使用过期数据。对于那种情况我想我想告诉客户资源暂时不可用。使用上面的警告和过期字段似乎是正确的。尽管发送带有合适 retry-after header 的 503 可能会更好。

所以问题是:在等待上传新版本时我应该如何回复 GET?

期待使用消息传递框架(如 AMQP 或 zeroMQ)来代替低延迟的答案,我应该指出这个 API 正在充当 AMQP gateway/proxy 用于客户不愿意直接使用 AMQP。关于使用 webhooks 或 websockets 的信息仍然很有趣。

一些相关有用的内容是:

Tl;博士;

上传待发送时:

client: GET /some/item
myapi:  200 OK
        some/item ... 
        last-modified: time-stamp-of-v1
        etag: some-hash-relating-to-v1-of-my-item-in-this-format
        expires: time-stamp-after-v1-but-before-v2
        stale-while-revalidate: 100
        warning: 110 Response is stale
        content: json or whatever
         data/for/some/item/v1... 

乍一看,使用 Warning 似乎是不正确的。参见 https://www.rfc-editor.org/rfc/rfc7234#section-5.5.0

在这种情况下,服务器充当代理(尽管不是 HTTP 代理)。 它不会与 AMQP 断开连接,除非断开连接,否则“代理不得发送陈旧的响应”。 这很烦人,因为它看起来是正确的做法。

4.2.4. Serving Stale Responses

A "stale" response is one that either has explicit expiry information or is allowed to have heuristic expiry calculated, but is not fresh according to the calculations in Section 4.2.

A cache MUST NOT generate a stale response if it is prohibited by an explicit in-protocol directive (e.g., by a "no-store" or "no-cache" cache directive, a "must-revalidate" cache-response-directive, or an applicable "s-maxage" or "proxy-revalidate" cache-response-directive; see Section 5.2.2).

**> 除非断开连接,否则缓存不得发送过时的响应

(i.e., it cannot contact the origin server or otherwise find a
forward path) or doing so is explicitly allowed (e.g., by the
max-stale request directive; see Section 5.2.1).**

A cache SHOULD generate a Warning header field with the 110 warn-code (see Section 5.5.1) in stale responses. Likewise, a cache SHOULD generate a 112 warn-code (see Section 5.5.3) in stale responses if the cache is disconnected.

A cache SHOULD NOT generate a new Warning header field when
forwarding a response that does not have an Age header field, even if the response is already stale. A cache need not validate a response
that merely became stale in transit.

还有

4.4. Invalidation

Because unsafe request methods (Section 4.2.1 of [RFC7231]) such as PUT, POST or DELETE have the potential for changing state on the
origin server, intervening caches can use them to keep their contents up to date.

**> 缓存必须使有效的请求 URI 无效(

的第 5.5 节

[RFC7230]) as well as the URI(s) in the Location and Content-Location response header fields (if present) when a non-error status code is
received in response to an unsafe request method.**

但是,如果使用 stale-while-revalidate 则需要警告(参见 https://www.rfc-editor.org/rfc/rfc5861

  1. The stale-while-revalidate Cache-Control Extension

When present in an HTTP response, the stale-while-revalidate Cache- Control extension indicates that caches MAY serve the response in
which it appears after it becomes stale, up to the indicated number
of seconds.

 stale-while-revalidate = "stale-while-revalidate" "=" delta-seconds

If a cached response is served stale due to the presence of this
extension, the cache SHOULD attempt to revalidate it while still
serving stale responses (i.e., without blocking).

我认为这还不清楚,所以我提交了 errata。由于 rfc5861 中的缓存控制扩展覆盖了 rfc7234 中的 MUST NOT(“明确允许这样做”见上文),这被拒绝了(尽管在撰写本文时它仍然显示为所报告的)。

可以使用 expires 但它不是很有用,因为它并不意味着任何东西。

5.3. Expires

The "Expires" header field gives the date/time after which the
response is considered stale. See Section 4.2 for further discussion of the freshness model.

**> Expires 字段的存在并不意味着原始

resource will change or cease to exist at, before, or after that
time.**