Microsoft.Azure.Cosmos.Table LocationMode.SecondaryOnly RA-GRS 异常 此操作只能针对主存储位置执行
Posted
技术标签:
【中文标题】Microsoft.Azure.Cosmos.Table LocationMode.SecondaryOnly RA-GRS 异常 此操作只能针对主存储位置执行【英文标题】:Microsoft.Azure.Cosmos.Table LocationMode.SecondaryOnly RA-GRS Exception This operation can only be executed against the primary storage location 【发布时间】:2020-06-08 05:15:25 【问题描述】:在解析使用 SAS 令牌的连接字符串时,我很难让 Microsoft.Azure.Cosmos.Table 自动初始化 SecondaryUri。
所以我最终在连接字符串中明确指定了 TableSecondaryEndpoint,这可行,但我无法查询辅助节点,因为 SDK 在尝试请求之前就抛出了异常。
在我的测试中,我发现这是 Microsoft.WindowsAzure.Storage.Table 8.7.0 中不存在的回归(Microsoft.Azure.Cosmos.Table 1.0.6 的基础)
非常欢迎高手提出这一点。谢谢。
此异常的项目代码在这里(也复制在下面): https://github.com/golfalot/SOshowAzureTableBug
详细说明这里提出的 SecondaryUri 初始化问题的侧面问题: https://github.com/Azure/azure-cosmos-table-dotnet/issues/36
using System;
using System.Collections.Generic;
using LEGACY_STORAGE = Microsoft.WindowsAzure.Storage;
using LEGACY_RETRY = Microsoft.WindowsAzure.Storage.RetryPolicies;
using LEGACY_TABLE = Microsoft.WindowsAzure.Storage.Table; //8.7.0 because this is the base for 1.0.6
using NEWEST_TABLE = Microsoft.Azure.Cosmos.Table; // version 1.0.6
using Microsoft.Azure.Cosmos.Table; // had to add this to get access CreateCloudTableClient extension method
using System.Diagnostics;
namespace SOshowAzureTableBug
class Program
// the SAS token is immaterial in reproducing the problem
const string connectionTableSAS = "TableSecondaryEndpoint=http://127.0.0.1:10002/devstoreaccount1-secondary;TableEndpoint=http://127.0.0.1:10002/devstoreaccount1;SharedAccessSignature=immaterial";
static void Main(string[] args)
/* Legacy Table SDK */
var storageAccountLegacy = LEGACY_STORAGE.CloudStorageAccount.Parse(connectionTableSAS);
var tableClientLegacy = storageAccountLegacy.CreateCloudTableClient();
Debug.Assert(tableClientLegacy.StorageUri.SecondaryUri != null); // demonstrate SecondaryUri initialised
var tableRequestOptionsLegacy = new LEGACY_TABLE.TableRequestOptions () LocationMode = LEGACY_RETRY.LocationMode.SecondaryOnly ;
tableClientLegacy.DefaultRequestOptions = tableRequestOptionsLegacy;
var tableLegacy = tableClientLegacy.GetTableReference("foo"); // don't need table to exist to show the issue
var retrieveOperation = LEGACY_TABLE.TableOperation.Retrieve(string.Empty, string.Empty, new List<string>() "bar" );
var tableResult = tableLegacy.Execute(retrieveOperation);
Console.WriteLine("Legacy PASS");
/* Newset Table SDK */
var storageAccountNewest = NEWEST_TABLE.CloudStorageAccount.Parse(connectionTableSAS);
var tableClientNewest = storageAccountNewest.CreateCloudTableClient(new TableClientConfiguration());
Debug.Assert(tableClientNewest.StorageUri.SecondaryUri != null); // demonstrate SecondaryUri initialised
var tableRequestOptionsNewest = new NEWEST_TABLE.TableRequestOptions() LocationMode = NEWEST_TABLE.LocationMode.SecondaryOnly ;
tableClientNewest.DefaultRequestOptions = tableRequestOptionsNewest;
var tableNewset = tableClientNewest.GetTableReference("foo"); // don't need table to exist to show the issue
var retrieveOperationNewset = NEWEST_TABLE.TableOperation.Retrieve(string.Empty, string.Empty, new List<string>() "bar" );
/* throws Microsoft.Azure.Cosmos.Table.StorageException
* Exception thrown while initializing request: This operation can only be executed against the primary storage location
*/
var tableResultNewset = tableNewset.Execute(retrieveOperationNewset);
Console.WriteLine("Press any key to exit");
Console.Read();
【问题讨论】:
您可以尝试以下方法:const string connectionTableSAS = "TableSecondaryEndpoint=http://127.0.0.1:10002/devstoreaccount1-secondary;TableEndpoint=http://127.0.0.1:10002/devstoreaccount1;SharedAccessSignature=st=2020-02-24T12%3A47%3A31Z&se=2020-02-25T12%3A47%3A31Z&sp=r&sv=2018-03-28&tn=ratingreflocationa20200217aandmarketvalueb20200217bxml&sig=wc7tW52nstzdGMzlQuaRuakShJ%2BHmpbv8jbMlnn1lug%3D";
?
@GauravMantri 嗨。没有变化,同样的例外。不过谢谢。为了澄清,在针对模拟器创建示例之前,我在真实存储帐户上遇到了同样的问题。我不认为 Secondary 的价值在这个问题上很重要。
我也能重现这个问题。但是我找到了一种解决方法。这可以接受吗?
@GauravMantri 请教育我! :-)
添加了答案。请检查。 HTH。
【参考方案1】:
我相信您遇到了 SDK 的错误。
当我尝试下面的代码时,我得到了和你一样的错误:
var account = CloudStorageAccount.Parse(connectionString);
var requestOptions = new TableRequestOptions()
LocationMode = LocationMode.SecondaryOnly
;
var client = account.CreateCloudTableClient();
client.DefaultRequestOptions = requestOptions;
var table = client.GetTableReference("myTable");
var op = TableOperation.Retrieve("", "");
var result1 = table.Execute(op);
我反编译了库代码,找到了罪魁祸首源代码:
if (commandLocationMode == CommandLocationMode.PrimaryOnly)
if (restCMD.LocationMode == LocationMode.SecondaryOnly)
throw new InvalidOperationException("This operation can only be executed against the primary storage location.");//This is the error that gets thrown.
Logger.LogInformational(executionState.OperationContext, "This operation can only be executed against the primary storage location.", Array.Empty<object>());
executionState.CurrentLocation = StorageLocation.Primary;
restCMD.LocationMode = LocationMode.PrimaryOnly;
但是,如果我没有在客户端级别设置 DefaultRequestOptions
并在下面的 Execute
方法中指定它,我不会收到错误消息,但这是因为命中了主要端点而不是次要端点(我检查了在提琴手)。
var account = CloudStorageAccount.Parse(connectionString);
var requestOptions = new TableRequestOptions()
LocationMode = LocationMode.SecondaryOnly
;
var client = account.CreateCloudTableClient();
var table = client.GetTableReference("myTable");
var op = TableOperation.Retrieve("", "");
var result1 = table.Execute(op, requestOptions);
解决方法
如果您的目标是从辅助位置查询实体,那么您可以在CloudTable
上使用ExecuteQuery
方法,如下所示。这行得通(我再次检查了 Fiddler)。
var account = CloudStorageAccount.Parse(connectionString);
var requestOptions = new TableRequestOptions()
LocationMode = LocationMode.SecondaryOnly
;
var client = account.CreateCloudTableClient();
client.DefaultRequestOptions = requestOptions;
var table = client.GetTableReference("myTable");
TableQuery query = new TableQuery();
var result = table.ExecuteQuery(query).ToList();
【讨论】:
好作品!我强制使用 SecondaryOnly 的最初原因是为了测试地理故障转移(您可能已经猜到了)。你似乎在这个领域很有能力,你建议我向 SDK 所有者提出这个错误的最佳方式是什么?我问是因为github.com/Azure/azure-cosmos-table-dotnet/issues 上似乎没有太多活动@ 如果您在 Twitter 上,只需标记那里的团队。我相信他们的句柄是@AzureCosmosDB。还有一封反馈电子邮件:AskCosmosDB@microsoft.com。我发现它们反应灵敏。 谢谢。只是为了结束循环,电子邮件返回并自动回复说我刚刚完成的 azure-cosmosdb 标记。 是的,我们关闭了该电子邮件。请在这个 github repo 上提出问题。 github.com/Azure/azure-cosmos-table-dotnet/issues 谢谢。 @MarkBrown 谢谢!该问题于 6 天前提交:github.com/Azure/azure-cosmos-table-dotnet/issues/36 :)以上是关于Microsoft.Azure.Cosmos.Table LocationMode.SecondaryOnly RA-GRS 异常 此操作只能针对主存储位置执行的主要内容,如果未能解决你的问题,请参考以下文章