内容提要
Azure的服务是通过RESTfulAPI提供的。虽然Azure针对很多编程语言都提供了SDK,但这些SDK也只是RESTfulAPI的一层封装。在调用SDK或者RESTfulAPI出错时,我们需要使用调试工具来分析并解决问题。Fiddler是一款功能强大的免费工具,我们可以使用Fiddler来调试Azure的应用程序。本文展示如何用Fiddler调试一个常见的访问Storage的问题。
问题描述
在前面的两篇博客中,我们模拟社交网站定义了一个Account类型。本文我们继续以Account类型作为例子。首先我们用如下代码添加2048个账号:
static async Task TestAddAccountBatch()
{
string connectionString = Constant.connectionString;
var storageAccount = Utilities.GetStorageAccount(connectionString);
var accountsTable = new AccountsTableWrapper(storageAccount);
List<Account> accounts = new List<Account>();
for(int i = 0; i < 2048; ++i)
{
string name = string.Format("Test{0,4:0000}", i);
string email = name + "@hotmail.com";
Account account = new Account(email, name);
accounts.Add(account);
}
await accountsTable.AddAccountBatch(accounts);
}
接着我们用如下代码得到账户的总数:
static void TestRetriveAll()
{
string connectionString = Constant.connectionString;
var storageAccount = Utilities.GetStorageAccount(connectionString);
var accountsTable = new AccountsTableWrapper(storageAccount);
List<Account> accounts = accountsTable.GetAllAccounts();
Console.WriteLine(accounts.Count);
}
public List<Account> GetAllAccounts()
{
TableQuery<Account> query = new TableQuery<Account>()
.Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, Account.AccountsPartitionKey));
List<Account> accounts = new List<Account>();
TableContinuationToken continueToken = null;
var response = this.accountsTable.ExecuteQuerySegmented(query, continueToken);
accounts.AddRange(response);
return accounts;
}
运行代码,我们发现得到的账号总数只有1000,并不是期待的2048。
问题根源
如果我们用Fiddler抓取该应用程序的网络请求以及得到的回复,Fiddler得到的数据如下图所示:
我们注意到在收到的HTTP回复的头中,有一个字段叫x-ms-continuation-NextPartitionKey,还有一个字段叫x-ms-continuation-NextRowKey。这提示我们,查询CloudTable其实并没有结束,我们应该根据这两个字段继续查询CloudTable。CloudTable为了优化性能,每一次相应请求时最多只返回1000个TableEntity。如果TableEntity的总数超过1000个,客户端需要重新发送请求。
解决问题
在两个HTTP头中的字段在SDK中用类型TableContinuationToken封装了。我们可以对代码做如下修改来解决问题:
public List<Account> GetAllAccounts()
{
TableQuery<Account> query = new TableQuery<Account>()
.Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, Account.AccountsPartitionKey));
List<Account> accounts = new List<Account>();
TableContinuationToken continueToken = null;
do
{
var response = this.accountsTable.ExecuteQuerySegmented(query, continueToken);
accounts.AddRange(response);
continueToken = response.ContinuationToken;
}
while(continueToken != null);
return accounts;
}
当TableContinuationToken不为null,表明还有更多的TableEntity,我们还需要执行更多的查询操作。此时运行修改过的代码,将得到正确的账号总数2048。
如果我们用Fiddler抓取该应用程序发送的HTTP请求和收到的回复,我们会注意到实际上一共发送了3个请求:
第三个请求对应的回复如下所示:
我们注意到此时回复的头部,已经没有x-ms-continuation-NextPartitionKey和x-ms-continuation-NextRowKey两个字段,表明所有的TableEntity都已经返回了。
附录
Fiddler是一款免费的软件,可以用来监视网络通讯时的请求与回复,是一个调试网络程序的利器。感兴趣的读者可以到http://www.telerik.com/download/fiddler处下载。