|
@@ -134,6 +134,15 @@ public class AzureNativeFileSystemStore implements NativeFileSystemStore {
|
|
|
private static final String KEY_MAX_BACKOFF_INTERVAL = "fs.azure.io.retry.max.backoff.interval";
|
|
|
private static final String KEY_BACKOFF_INTERVAL = "fs.azure.io.retry.backoff.interval";
|
|
|
private static final String KEY_MAX_IO_RETRIES = "fs.azure.io.retry.max.retries";
|
|
|
+
|
|
|
+ private static final String KEY_COPYBLOB_MIN_BACKOFF_INTERVAL =
|
|
|
+ "fs.azure.io.copyblob.retry.min.backoff.interval";
|
|
|
+ private static final String KEY_COPYBLOB_MAX_BACKOFF_INTERVAL =
|
|
|
+ "fs.azure.io.copyblob.retry.max.backoff.interval";
|
|
|
+ private static final String KEY_COPYBLOB_BACKOFF_INTERVAL =
|
|
|
+ "fs.azure.io.copyblob.retry.backoff.interval";
|
|
|
+ private static final String KEY_COPYBLOB_MAX_IO_RETRIES =
|
|
|
+ "fs.azure.io.copyblob.retry.max.retries";
|
|
|
|
|
|
private static final String KEY_SELF_THROTTLE_ENABLE = "fs.azure.selfthrottling.enable";
|
|
|
private static final String KEY_SELF_THROTTLE_READ_FACTOR = "fs.azure.selfthrottling.read.factor";
|
|
@@ -199,6 +208,11 @@ public class AzureNativeFileSystemStore implements NativeFileSystemStore {
|
|
|
private static final int DEFAULT_MAX_BACKOFF_INTERVAL = 30 * 1000; // 30s
|
|
|
private static final int DEFAULT_BACKOFF_INTERVAL = 1 * 1000; // 1s
|
|
|
private static final int DEFAULT_MAX_RETRY_ATTEMPTS = 15;
|
|
|
+
|
|
|
+ private static final int DEFAULT_COPYBLOB_MIN_BACKOFF_INTERVAL = 3 * 1000;
|
|
|
+ private static final int DEFAULT_COPYBLOB_MAX_BACKOFF_INTERVAL = 90 * 1000;
|
|
|
+ private static final int DEFAULT_COPYBLOB_BACKOFF_INTERVAL = 30 * 1000;
|
|
|
+ private static final int DEFAULT_COPYBLOB_MAX_RETRY_ATTEMPTS = 15;
|
|
|
|
|
|
// Self-throttling defaults. Allowed range = (0,1.0]
|
|
|
// Value of 1.0 means no self-throttling.
|
|
@@ -2435,11 +2449,46 @@ public class AzureNativeFileSystemStore implements NativeFileSystemStore {
|
|
|
// Rename the source blob to the destination blob by copying it to
|
|
|
// the destination blob then deleting it.
|
|
|
//
|
|
|
- dstBlob.startCopyFromBlob(srcUri, getInstrumentedContext());
|
|
|
+ // Copy blob operation in Azure storage is very costly. It will be highly
|
|
|
+ // likely throttled during Azure storage gc. Short term fix will be using
|
|
|
+ // a more intensive exponential retry policy when the cluster is getting
|
|
|
+ // throttled.
|
|
|
+ try {
|
|
|
+ dstBlob.startCopyFromBlob(srcUri, null, getInstrumentedContext());
|
|
|
+ } catch (StorageException se) {
|
|
|
+ if (se.getErrorCode().equals(
|
|
|
+ StorageErrorCode.SERVER_BUSY.toString())) {
|
|
|
+ int copyBlobMinBackoff = sessionConfiguration.getInt(
|
|
|
+ KEY_COPYBLOB_MIN_BACKOFF_INTERVAL,
|
|
|
+ DEFAULT_COPYBLOB_MIN_BACKOFF_INTERVAL);
|
|
|
+
|
|
|
+ int copyBlobMaxBackoff = sessionConfiguration.getInt(
|
|
|
+ KEY_COPYBLOB_MAX_BACKOFF_INTERVAL,
|
|
|
+ DEFAULT_COPYBLOB_MAX_BACKOFF_INTERVAL);
|
|
|
+
|
|
|
+ int copyBlobDeltaBackoff = sessionConfiguration.getInt(
|
|
|
+ KEY_COPYBLOB_BACKOFF_INTERVAL,
|
|
|
+ DEFAULT_COPYBLOB_BACKOFF_INTERVAL);
|
|
|
+
|
|
|
+ int copyBlobMaxRetries = sessionConfiguration.getInt(
|
|
|
+ KEY_COPYBLOB_MAX_IO_RETRIES,
|
|
|
+ DEFAULT_COPYBLOB_MAX_RETRY_ATTEMPTS);
|
|
|
+
|
|
|
+ BlobRequestOptions options = new BlobRequestOptions();
|
|
|
+ options.setRetryPolicyFactory(new RetryExponentialRetry(
|
|
|
+ copyBlobMinBackoff, copyBlobDeltaBackoff, copyBlobMaxBackoff,
|
|
|
+ copyBlobMaxRetries));
|
|
|
+ dstBlob.startCopyFromBlob(srcUri, options, getInstrumentedContext());
|
|
|
+ } else {
|
|
|
+ throw se;
|
|
|
+ }
|
|
|
+ }
|
|
|
waitForCopyToComplete(dstBlob, getInstrumentedContext());
|
|
|
-
|
|
|
safeDelete(srcBlob, lease);
|
|
|
- } catch (Exception e) {
|
|
|
+ } catch (StorageException e) {
|
|
|
+ // Re-throw exception as an Azure storage exception.
|
|
|
+ throw new AzureException(e);
|
|
|
+ } catch (URISyntaxException e) {
|
|
|
// Re-throw exception as an Azure storage exception.
|
|
|
throw new AzureException(e);
|
|
|
}
|