为每个事务创建 CloudTableClient 和 CloudTable 的新实例
Creating new instances of CloudTableClient and CloudTable per transaction
经过一些研究,我仍然不确定如何最好地维护 'connection' 到 Azure Table 存储。 CloudTableClient
或 CloudTable
实例应该跨请求重用吗?
我们正在使用 Table 存储在 public、高流量 API 后面。我们需要高读取可用性和性能。所有查询均为 POINT 查询(partition key 和 row key 均可用),响应支付体积小(小于 1 KB)。写入性能不是一个大问题。 API 上的每个请求最多可以跨几个分区读取 10 个点查询。
通过阅读,我明白了以下几点:
CloudTableClient
不是线程安全的,应该为每个事务创建。 显然这在连续重新创建时不应该影响性能。
因此还必须为每个事务创建一个 CloudTable
实例。
做出这些假设是否正确?
因此,我为每个请求重新初始化 CloudTableClient
和 CloudTable
。感觉很浪费。
查看实现:
public class EntityStorageComponent : IEntityComponent
{
private CloudStorageAccount storageAccount;
public CloudTable Table
{
get
{
var tableClient = storageAccount.CreateCloudTableClient();
ServicePoint tableServicePoint = ServicePointManager.FindServicePoint(storageAccount.TableEndpoint);
tableServicePoint.UseNagleAlgorithm = false;
tableServicePoint.ConnectionLimit = 100;
var context = new OperationContext();
context.Retrying += (sender, args) =>
{
Debug.WriteLine("Retry policy activated");
};
// Attempt delays: ~200ms, ~200ms, ~200ms
var requestOptions = new TableRequestOptions
{
RetryPolicy = = new LinearRetry(TimeSpan.FromMilliseconds(200), 3),
MaximumExecutionTime = TimeSpan.FromSeconds(60)
};
var table = tableClient.GetTableReference("farematrix");
table.CreateIfNotExists(requestOptions, context);
return table;
}
}
public EntityStorageComponent(IOptions<ConfigurationOptions> options)
{
storageAccount = CloudStorageAccount.Parse(options.Value.TableStorageConnectionString);
}
public SomeEntity Find(Guid partitionKey, Guid rowKey)
{
var retrieveOperation = TableOperation.Retrieve<SomeEntity>(partitionKey, rowKey);
var retrievedResult = Table.Execute(retrieveOperation);
return retrievedResult.Result as SomeEntity;
}
}
除了创建对象的通常开销外,我没有发现创建 CloudTableClient
和 CloudTable
对象的多个实例有任何问题。因此,如果您只是执行以下操作,我认为您不会在性能方面受到影响:
var tableClient = storageAccount.CreateCloudTableClient();
var table = tableClient.GetTableReference("farematrix");
但是我发现您在代码中创建 CloudTable
的方式存在问题(Table
成员)。基本上在您的代码中,只要您从 EntityStorageComponent
获得 Table
属性,您就在尝试在您的存储帐户中创建一个 table。
var table = tableClient.GetTableReference("farematrix");
table.CreateIfNotExists(requestOptions, context);
这是一个问题,因为 table.CreateIfNotExists(requestOptions, context);
将进行网络调用并显着降低您的系统速度。您可能想要移出 table.CreateIfNotExists(requestOptions, context);
代码并将其放入您的启动代码中,以便您始终(主要)确定 table 存在。
经过一些研究,我仍然不确定如何最好地维护 'connection' 到 Azure Table 存储。 CloudTableClient
或 CloudTable
实例应该跨请求重用吗?
我们正在使用 Table 存储在 public、高流量 API 后面。我们需要高读取可用性和性能。所有查询均为 POINT 查询(partition key 和 row key 均可用),响应支付体积小(小于 1 KB)。写入性能不是一个大问题。 API 上的每个请求最多可以跨几个分区读取 10 个点查询。
通过阅读,我明白了以下几点:
CloudTableClient
不是线程安全的,应该为每个事务创建。 显然这在连续重新创建时不应该影响性能。因此还必须为每个事务创建一个
CloudTable
实例。
做出这些假设是否正确?
因此,我为每个请求重新初始化 CloudTableClient
和 CloudTable
。感觉很浪费。
查看实现:
public class EntityStorageComponent : IEntityComponent
{
private CloudStorageAccount storageAccount;
public CloudTable Table
{
get
{
var tableClient = storageAccount.CreateCloudTableClient();
ServicePoint tableServicePoint = ServicePointManager.FindServicePoint(storageAccount.TableEndpoint);
tableServicePoint.UseNagleAlgorithm = false;
tableServicePoint.ConnectionLimit = 100;
var context = new OperationContext();
context.Retrying += (sender, args) =>
{
Debug.WriteLine("Retry policy activated");
};
// Attempt delays: ~200ms, ~200ms, ~200ms
var requestOptions = new TableRequestOptions
{
RetryPolicy = = new LinearRetry(TimeSpan.FromMilliseconds(200), 3),
MaximumExecutionTime = TimeSpan.FromSeconds(60)
};
var table = tableClient.GetTableReference("farematrix");
table.CreateIfNotExists(requestOptions, context);
return table;
}
}
public EntityStorageComponent(IOptions<ConfigurationOptions> options)
{
storageAccount = CloudStorageAccount.Parse(options.Value.TableStorageConnectionString);
}
public SomeEntity Find(Guid partitionKey, Guid rowKey)
{
var retrieveOperation = TableOperation.Retrieve<SomeEntity>(partitionKey, rowKey);
var retrievedResult = Table.Execute(retrieveOperation);
return retrievedResult.Result as SomeEntity;
}
}
除了创建对象的通常开销外,我没有发现创建 CloudTableClient
和 CloudTable
对象的多个实例有任何问题。因此,如果您只是执行以下操作,我认为您不会在性能方面受到影响:
var tableClient = storageAccount.CreateCloudTableClient();
var table = tableClient.GetTableReference("farematrix");
但是我发现您在代码中创建 CloudTable
的方式存在问题(Table
成员)。基本上在您的代码中,只要您从 EntityStorageComponent
获得 Table
属性,您就在尝试在您的存储帐户中创建一个 table。
var table = tableClient.GetTableReference("farematrix");
table.CreateIfNotExists(requestOptions, context);
这是一个问题,因为 table.CreateIfNotExists(requestOptions, context);
将进行网络调用并显着降低您的系统速度。您可能想要移出 table.CreateIfNotExists(requestOptions, context);
代码并将其放入您的启动代码中,以便您始终(主要)确定 table 存在。