问题
So I have a function that simply downloads text from blob storage every 10 minutes and checks for a result. This function can run for days. But it often (roughly every day) fails before finishing with the following error.
Caused by: com.microsoft.azure.storage.StorageException: The condition specified using HTTP conditional header(s) is not met.
My code is pretty simple.
public String downloadTextBlob(CloudBlobDirectory dir, String filename) {
try {
return dir.getBlockBlobReference(filename).downloadText();
} catch (StorageException | IOException | URISyntaxException e) {
throw new WorkbenchRuntimeException(e.getMessage(), e);
}
}
I the same issue posted here, and I was interested in the answer which talked about using an OperationContext to fix the issue. But the question wasn't on Java, and the answer didn't really explain what it was actually doing.
Here's the proposed solution (non java code)
OperationContext context = new OperationContext();
context.SendingRequest += (sender, e) => {
e.Request.Headers["if-match"] = "*";
};
Can anyone explain what this is actually doing? And maybe how I can replicate this in Java, I notice there is an OperationContext in the Java azure storage sdk, and that I can call the .downloadText() with an operation context as a parameter. I'm just not sure what to do with OperationContext.
回答1:
First, I would encourage you to read about conditional headers in Azure Blob Storage here: https://docs.microsoft.com/en-us/rest/api/storageservices/specifying-conditional-headers-for-blob-service-operations.
I haven't looked at the source code for the Java SDK but my guess is that downloadText()
operation is performing multiple operations behind the scenes. In the first operation, it is getting the properties of the blob (like blob's length etc.) and in the next operation it is actually downloading the blob. As part of the first operation it also gets the blob's etag and it is passing the same etag to the 2nd operation in if-match
header.
Now between the 1st and 2nd operation something changed with the blob that caused etag value to change. Since the 2nd request still used the old etag value and there's a mismatch between the etag, your request is failing with precondition failed
. Presence of etag in if-match
header instructs storage service to perform the operation only if the condition matches (i.e. etag matches). Since the etag doesn't match, you're getting this error.
To fix this, you need to use the following override of downloadText()
method:
downloadText(final String charsetName, final AccessCondition accessCondition, BlobRequestOptions options, OperationContext opContext)
and specify an access condition with "*" value for if-match
which essentially tells storage service to ignore the etag value. You can learn more about access condition here: https://docs.microsoft.com/en-us/java/api/com.microsoft.azure.storage.accesscondition?view=azure-java-legacy.
Your code would be something like (untested code):
AccessCondition accessCondition = AccessCondition.generateIfMatchCondition("*");
and use this access condition in your downloadText() method.
来源:https://stackoverflow.com/questions/62308525/azure-blob-error-storageexception-the-condition-specified-using-http-condition