![](/img/trans.png)
[英]Microsoft.Azure.Cosmos.Table LocationMode.SecondaryOnly RA-GRS Exception This operation can only be executed against the primary storage location
[英]How do you update TableServiceClient in ASP.NET Core, to point to a secondary region, when using Azure geo redundant (RA-GRS) table storage?
I am using the latest Azure.Data.Tables
nuget package, version 12.3.0
to connect to Azure table storage in an ASP.NET Core C# Application.
如果主要区域发生故障,我的应用程序需要故障转移到次要区域进行读取。
目前TableServiceClient
的设置是在 Startup.cs 中完成的,如下所示:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton(new TableServiceClient(new Uri("PrimaryRegionConnectionURL"), new DefaultAzureCredential()));
}
如何使用指向次要区域的实例更新TableServiceClient
的当前实例? 是否有更好的方法来实现此故障转移?
澄清一下:我知道客户端不支持故障转移,并且团队已经创建了一张票以在将来查看此功能。 我意识到我需要有一个TableServiceClient
的新实例。
我只是不确定如何将启动时创建的替换为失败时指向辅助实例的新实例。
这是使用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
不确定这是否是实现它的最佳方法,但考虑到我必须自己处理在主要和次要端点之间切换的逻辑,我会这样做。
首先,我将创建两个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);
}
接下来,我将提取用于在单独的 function 中获取实体的逻辑,并将客户端传递给该 function(我们称之为GetPartitionEntitiesImpl
)。
然后在GetPartitionEntities
方法中,我会尝试从主端点获取实体并捕获异常。 如果异常表明主端点失败,我会再次调用GetPartitionEntitiesImpl
function 并尝试从辅助端点获取实体。
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)的代码,了解在主要和次要端点之间切换的逻辑。 SDK 很好地处理了这种情况。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.