我正在调用Azure Storage SDK for Java(v4.0.0)中的downloadRange
- 函数来下载Page Blob的部分内容,例如: downloadRange(0, 1000, os, null, null, null)
。另一个进程,一个编写器,写入页面blob的末尾。如果写入与downloadRange
并发 - 调用并且downloadRange
在内部重试(HTTP GET),则会生成带有以下文本的StorageException
:“使用HTTP条件头指定的条件(s)未得到满足。“。
如果不发生这种情况,是否可以执行downloadRange
读取操作?就应用而言,在最后一页之前访问字节是安全的。
伪代码如下(使用scala):
val blob = container.getPageBlobReference(blobName)
val baos = new ByteArrayOutputStream()
blob.downloadRange(0, totalSize, baos, null, null, null)
更新
根据以下评论进行澄清。用例有点特殊,因为已知读取字节范围是安全的,即它只读取blob中未同时写入的字节范围。写入仅附加到blob的末尾。问题是如何使用downloadRange
或Azure存储SDK的任何其他部分来访问具有并发写入的blob,即使在网络问题(丢包,传输速度慢等)的情况下也是如此。
答案 0 :(得分:4)
此答案基于您可以阅读的评论主题。
在这种特殊情况下,错误发生在重试而不是第一次调用。当存储库重试下载时,if-match会被设置,因为在重试时我们必须保证blob没有改变以保持一致性。否则,如果在这些调用之间设置了新的blob,我们将获得旧的一半和新的一半。从图书馆的角度来看,由于我们没有知识,如果blob已经改变,后续的读取将是安全的,我们必须强制执行此操作。没有办法禁用它。
在这种特殊情况下,存在频繁连接失败,并发写入和读取安全性预知的非常独特的组合。这是我一直认为非常罕见的事情。连接失败将是最罕见的部分,因此可能需要更多的调查(也许是另一个问题的主题)。
在这种特殊情况下,我建议尽一切可能减少网络开放的时间。减少此时间意味着首先减少网络故障,降低blob发生更改的可能性,如果重试确实发生,因为小型下载只需要更少的时间。将读取分解为较小的块可能是实现此目的的最佳途径。同样,您可能只想在catch语句中手动重试此部分下载以解决此错误。
答案 1 :(得分:0)
问题StorageException
似乎是由于没有为类AccessCondition
的函数downloadRange
设置参数CloudBlob
而引起的。
关于Azure存储并发,我建议使用官方文档Managing Concurrency in Microsoft Azure Storage。 C#中有一些代码示例作为参考。您可以尝试引用the Javadocs of Azure Storage SDK并在Java中翻译这些代码。
如有任何疑虑,请随时告诉我。