7

我和一位同事的任务都是为 Azure 表存储寻找连接重试逻辑。经过一番搜索,我发现了这个非常酷的 Enterprise Library 套件,其中包含Microsoft.Practices.TransientFaultHandling命名空间。

在几个代码示例之后,我最终创建了一个重试策略,并使用的回调处理程序Incremental包装了我们的一个存储调用:retryPolicyExecuteAction

/// <inheritdoc />
public void SaveSetting(int userId, string bookId, string settingId, string itemId, JObject value)
{
    // Define your retry strategy: retry 5 times, starting 1 second apart, adding 2 seconds to the interval each retry.
    var retryStrategy = new Incremental(5, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2));

    var storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting(StorageConnectionStringName));            

    try
    {
        retryPolicy.ExecuteAction(() =>
        {
                var tableClient = storageAccount.CreateCloudTableClient();

                var table = tableClient.GetTableReference(SettingsTableName);

                table.CreateIfNotExists();

                var entity = new Models.Azure.Setting
                {
                    PartitionKey = GetPartitionKey(userId, bookId),
                    RowKey = GetRowKey(settingId, itemId),
                    UserId = userId,
                    BookId = bookId.ToLowerInvariant(),
                    SettingId = settingId.ToLowerInvariant(),
                    ItemId = itemId.ToLowerInvariant(),
                    Value = value.ToString(Formatting.None)
                };

                table.Execute(TableOperation.InsertOrReplace(entity));
            });
        }
        catch (StorageException exception)
        {
            ExceptionHelpers.CheckForPropertyValueTooLargeMessage(exception);

            throw;
        }
    }
}

感觉很棒,我去给我的同事看,他得意地指出我们可以做同样的事情而不必包含企业库,因为CloudTableClient对象已经有一个重试策略的设置器。他的代码最终看起来像:

/// <inheritdoc />
public void SaveSetting(int userId, string bookId, string settingId, string itemId, JObject value)
{
        var storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting(StorageConnectionStringName));
        var tableClient = storageAccount.CreateCloudTableClient();

        // set retry for the connection
        tableClient.RetryPolicy = new ExponentialRetry(TimeSpan.FromSeconds(2), 3);

        var table = tableClient.GetTableReference(SettingsTableName);

        table.CreateIfNotExists();

        var entity = new Models.Azure.Setting
        {
            PartitionKey = GetPartitionKey(userId, bookId),
            RowKey = GetRowKey(settingId, itemId),
            UserId = userId,
            BookId = bookId.ToLowerInvariant(),
            SettingId = settingId.ToLowerInvariant(),
            ItemId = itemId.ToLowerInvariant(),
            Value = value.ToString(Formatting.None)
        };

        try
        {
            table.Execute(TableOperation.InsertOrReplace(entity));
        }
        catch (StorageException exception)
        {
            ExceptionHelpers.CheckForPropertyValueTooLargeMessage(exception);

            throw;
        }
}

我的问题 :

除了实现之外,这两种方法之间是否有任何重大区别?它们似乎都实现了相同的目标,但是在某些情况下使用一个比另一个更好吗?

4

1 回答 1

5

从功能上讲,两者都是相同的——它们都会在出现瞬时错误的情况下重试请求。但是有一些区别:

  • 存储客户端库中的重试策略处理仅处理存储操作的重试,而瞬时故障处理重试不仅处理存储操作,而且在出现瞬时错误时重试 SQL Azure、服务总线和缓存操作。因此,如果您有一个项目使用更多存储,但希望只使用一种方法来处理瞬态错误,您可能希望使用瞬态故障处理应用程序块。
  • 关于瞬态故障处理块,我喜欢的一件事是您可以拦截重试策略无法执行的重试操作。例如,看下面的代码:

        var retryManager = EnterpriseLibraryContainer.Current.GetInstance<RetryManager>();
        var retryPolicy = retryManager.GetRetryPolicy<StorageTransientErrorDetectionStrategy>(ConfigurationHelper.ReadFromServiceConfigFile(Constants.DefaultRetryStrategyForTableStorageOperationsKey));
        retryPolicy.Retrying += (sender, args) =>
        {
            // Log details of the retry.
            var message = string.Format(CultureInfo.InvariantCulture, TableOperationRetryTraceFormat, "TableStorageHelper::CreateTableIfNotExist", storageAccount.Credentials.AccountName,
                tableName, args.CurrentRetryCount, args.Delay);
            TraceHelper.TraceError(message, args.LastException);
        };
        try
        {
            var isTableCreated = retryPolicy.ExecuteAction(() =>
            {
                var table = storageAccount.CreateCloudTableClient().GetTableReference(tableName);
                return table.CreateIfNotExists(requestOptions, operationContext);
            });
            return isTableCreated;
        }
        catch (Exception)
        {
            throw;
        }
    

在上面的代码示例中,我可以拦截重试操作并在那里做一些我想要的事情。这对于存储客户端库是不可能的。

说了这么多,通常建议使用存储客户端库重试策略来重试存储操作,因为它是包的一个组成部分,因此将与库的最新更改保持同步。

于 2013-09-24T03:47:58.623 回答