[英]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.