我正在使用最新的Azure。数据表
nuget软件包,版本12.3。0连接到ASP中的Azure表存储。NET核心C#应用程序。
如果主区域出现故障,我的应用程序需要故障切换到辅助区域进行读取。
目前,TableServiceClient
的设置是在启动时完成的。政务司司长答覆如下:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton(new TableServiceClient(new Uri("PrimaryRegionConnectionURL"), new DefaultAzureCredential()));
}
如何使用指向辅助区域的实例更新TableServiceClient
的当前实例?是否有更好的方法来实现此故障切换?
只是想澄清一下:我知道客户端不支持故障转移,团队已经创建了一个票证,以便在将来查看此功能。我意识到我需要一个新的表服务客户端实例。
我只是不确定如何将启动时创建的实例替换为失败时指向次要实例的新实例。
下面是使用表服务客户端的代码
public class TableRepository : ITableStorageRepository
{
readonly TableServiceClient _serviceClient;
public TableRepository(TableServiceClient serviceClient)
{
_serviceClient = serviceClient;
}
public async Task<ICollection<T>> GetPartitionEntities<T>(string partitionKey, string tableName)
where T : class, ITableEntity, new()
{
var listOfEntities = new List<T>();
var tableClient = _serviceClient.GetTableClient(tableName);
var queryResults = tableClient.QueryAsync<T>(filter => filter.PartitionKey == partitionKey);
await foreach (var row in queryResults)
{
listOfEntities.Add(row);
}
return listOfEntities;
}
}
当前不支持使用同一客户端的自动故障转移;要使用次要区域,需要单独的TableServiceClient
。这里有更多的上下文:https://github.com/Azure/azure-sdk-for-net/issues/25456
正在此处跟踪添加支持的工作:https://github.com/Azure/azure-sdk-for-net/issues/25710
不确定这是否是实现它的最佳方式,但考虑到我必须自己处理主endpoint和辅助endpoint之间切换的逻辑,这就是我要做的事情。
首先,我会创建两个TableServiceClient
实例-一个用于主实例,另一个用于辅助实例。
public void ConfigureServices(IServiceCollection services)
{
Dictionary<string, TableServiceClient> tableServiceClients = new Dictionary()
{
"Primary", new TableServiceClient(new Uri("PrimaryRegionConnectionURL"), new DefaultAzureCredential()),
"Secondary", new TableServiceClient(new Uri("SecondaryRegionConnectionURL"), new DefaultAzureCredential())
}
services.AddSingleton(tableServiceClients);
}
接下来,我将提取在一个单独的函数中获取实体的逻辑,并将客户端传递给该函数(让我们称之为GetPARtionEntiesImpl
)。
然后在方法中,我会尝试从主endpoint获取实体并捕获异常。如果异常指示主终结点失败,我会再次调用GetPARtionEntiesImpl
函数,并尝试从辅助终结点获取实体。
public class TableRepository : ITableStorageRepository
{
readonly TableServiceClient _primaryServiceClient, _secondaryServiceClient;
public TableRepository(Dictionary<string, TableServiceClient> tableServiceClients)
{
_primaryServiceClient = tableServiceClients["Primary"];
_secondaryServiceClient = tableServiceClients["Secondary"];
}
public async Task<ICollection<T>> GetPartitionEntities<T>(string partitionKey, string tableName)
where T : class, ITableEntity, new()
{
try
{
return await GetPartitionEntitiesImpl(_primaryServiceClient, partitionKey, tableName);
}
catch (Exception exception)
{
//Check if there is a need for failover
if (shouldTrySecondaryEndpoint)
{
return await GetPartitionEntitiesImpl(_secondaryServiceClient, partitionKey, tableName);
}
}
}
private async Task<ICollection<T>> GetPartitionEntitiesImpl<T>(TableServiceClient serviceClient, string partitionKey, string tableName)
where T : class, ITableEntity, new()
{
var listOfEntities = new List<T>();
var tableClient = serviceClient.GetTableClient(tableName);
var queryResults = tableClient.QueryAsync<T>(filter => filter.PartitionKey == partitionKey);
await foreach (var row in queryResults)
{
listOfEntities.Add(row);
}
return listOfEntities;
}
}
另外,请查看较旧的Azure Storage SDK(9.x版)的代码,了解在主endpoint和辅助endpoint之间切换的逻辑。SDK相当好地处理了这个场景。