是否可以对空 HTTP 实体使用(最好是空的)范围规范?
Is it possible to use (preferably empty) range specification with empty HTTP entity?
情况:
- HTTP 实体(在我的例子中是 S3 对象)
- GET 请求 return 我需要的额外信息 (
x-amz-tagging-count
)
- 注意:不幸的是,等效的 HEAD 请求没有return那个信息
- 获取该信息 GET 请求发送时带有小范围规范(例如
Range:0-0
)
问题:
- 我们检索不必要的数据(性能受到影响:服务器读取该字节所花费的时间)
- 对于零大小的实体(S3 对象)失败
来自HTTP 1.1 standard的相关部分:
first-byte-pos = 1*DIGIT
last-byte-pos = 1*DIGIT
byte-range-spec = first-byte-pos "-" [ last-byte-pos ]
...
A byte-range-spec is invalid if the last-byte-pos value is present
and less than the first-byte-pos.
...
suffix-length = 1*DIGIT
suffix-byte-range-spec = "-" suffix-length
...
If the selected representation is shorter than the specified
suffix-length, the entire representation is used.
...
If a valid byte-range-set includes at least one byte-range-spec with
a first-byte-pos that is less(!!) than the current length of the
representation, or at least one suffix-byte-range-spec with a
non-zero(!!) suffix-length, then the byte-range-set is satisfiable.
Otherwise, the byte-range-set is unsatisfiable.
在我看来:
- 根本不可能指定空范围(即
1-0
和-0
都是invalid
或unsatisfiable
)
- 如果实体长度为零——
Range:-1
应该根据标准工作(和return0字节),但我试过的每个服务器(包括 AWS S3) 失败并显示“无效范围”消息
问题:
处理这种情况的最佳方法是什么? (理想情况下,我想指定一个空范围)
备注:
- 我可以省略空实体的范围说明符,但这会产生竞争条件——实体可能会在我的 GET 请求之前更新,我最终可能会下载大量数据
根据标准,为空实体范围指定 可满足 的唯一方法是使用具有非零值 suffix-length
的 suffix-byte-range-spec
(即 Range:-1
、Range:-2
、等等)。
不幸的是,none 我检查过的服务器(AWS、StorageGrid、Dell ECS)支持这个。
因此,要避免竞争,唯一的解决办法是:
- 在时间戳
上使用条件 GET
- 以忽略时间戳太早的实体的方式构建您的逻辑
- 即有一个“死”window(X-seconds-ago,+inf),其中对象(在 window 中带有时间戳)被忽略
- 你的逻辑是否被反复执行(增量?)直到最终 运行
- 确保final 运行在保证数据不变的环境中执行
- 确保服务器的时钟与客户端“合理”同步(即偏差完全在上述时间内 window)
或者,条件可以使用etag
,但我不会这样做以避免在 md5 冲突的情况下发生竞争。其中isn't particularly hard实现...
在 S3 的情况下,另一种选择是使用版本控制的存储桶并在特定对象版本上执行 GET。
情况:
- HTTP 实体(在我的例子中是 S3 对象)
- GET 请求 return 我需要的额外信息 (
x-amz-tagging-count
)- 注意:不幸的是,等效的 HEAD 请求没有return那个信息
- 获取该信息 GET 请求发送时带有小范围规范(例如
Range:0-0
)
问题:
- 我们检索不必要的数据(性能受到影响:服务器读取该字节所花费的时间)
- 对于零大小的实体(S3 对象)失败
来自HTTP 1.1 standard的相关部分:
first-byte-pos = 1*DIGIT
last-byte-pos = 1*DIGIT
byte-range-spec = first-byte-pos "-" [ last-byte-pos ]
...
A byte-range-spec is invalid if the last-byte-pos value is present
and less than the first-byte-pos.
...
suffix-length = 1*DIGIT
suffix-byte-range-spec = "-" suffix-length
...
If the selected representation is shorter than the specified
suffix-length, the entire representation is used.
...
If a valid byte-range-set includes at least one byte-range-spec with
a first-byte-pos that is less(!!) than the current length of the
representation, or at least one suffix-byte-range-spec with a
non-zero(!!) suffix-length, then the byte-range-set is satisfiable.
Otherwise, the byte-range-set is unsatisfiable.
在我看来:
- 根本不可能指定空范围(即
1-0
和-0
都是invalid
或unsatisfiable
) - 如果实体长度为零——
Range:-1
应该根据标准工作(和return0字节),但我试过的每个服务器(包括 AWS S3) 失败并显示“无效范围”消息
问题:
处理这种情况的最佳方法是什么? (理想情况下,我想指定一个空范围)
备注:
- 我可以省略空实体的范围说明符,但这会产生竞争条件——实体可能会在我的 GET 请求之前更新,我最终可能会下载大量数据
根据标准,为空实体范围指定 可满足 的唯一方法是使用具有非零值 suffix-length
的 suffix-byte-range-spec
(即 Range:-1
、Range:-2
、等等)。
不幸的是,none 我检查过的服务器(AWS、StorageGrid、Dell ECS)支持这个。
因此,要避免竞争,唯一的解决办法是:
- 在时间戳 上使用条件 GET
- 以忽略时间戳太早的实体的方式构建您的逻辑
- 即有一个“死”window(X-seconds-ago,+inf),其中对象(在 window 中带有时间戳)被忽略
- 你的逻辑是否被反复执行(增量?)直到最终 运行
- 确保final 运行在保证数据不变的环境中执行
- 确保服务器的时钟与客户端“合理”同步(即偏差完全在上述时间内 window)
或者,条件可以使用etag
,但我不会这样做以避免在 md5 冲突的情况下发生竞争。其中isn't particularly hard实现...
在 S3 的情况下,另一种选择是使用版本控制的存储桶并在特定对象版本上执行 GET。