Azure 为每个事务创建CloudTableClient和CloudTable的新实例

Azure 为每个事务创建CloudTableClient和CloudTable的新实例,azure,azure-storage,azure-table-storage,Azure,Azure Storage,Azure Table Storage,在做了一些研究之后,我仍然不确定如何最好地维护到Azure表存储的“连接”。CloudTableClient或CloudTable实例是否应跨请求重用 我们在一个公共的、高流量的API后面使用表存储。我们需要高读可用性和高性能。所有查询都是点查询(分区键和行键都可用),响应支付的大小很小(小于1 KB)。写性能不是一个大问题。API上的每个请求可以跨几个分区读取多达10个点的查询 通过阅读,我了解到以下几点: CloudTableClient不是线程安全的,应该为每个事务创建。显然,在连续重新

在做了一些研究之后,我仍然不确定如何最好地维护到Azure表存储的“连接”。
CloudTableClient
CloudTable
实例是否应跨请求重用

我们在一个公共的、高流量的API后面使用表存储。我们需要高读可用性和高性能。所有查询都是点查询(分区键和行键都可用),响应支付的大小很小(小于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;
    }
}
公共类EntityStorageComponent:EntityComponent
{
私有云存储账户;
公共云表
{
得到
{
var tableClient=storageAccount.CreateCloudTableClient();
ServicePoint tableServicePoint=ServicePointManager.FindServicePoint(storageAccount.TableEndpoint);
tableServicePoint.UseNagleAlgorithm=false;
tableServicePoint.ConnectionLimit=100;
var context=new OperationContext();
context.Retrying+=(发送方,参数)=>
{
Debug.WriteLine(“重试策略已激活”);
};
//尝试延迟:~200ms、~200ms、~200ms
var requestOptions=new TableRequestOptions
{
RetryPolicy==新的线性重试(TimeSpan.From毫秒(200),3),
MaximumExecutionTime=TimeSpan.FromSeconds(60)
};
var table=tableClient.GetTableReference(“farematrix”);
CreateIfNotExists(请求选项、上下文);
返回表;
}
}
公共实体存储组件(IOOptions选项)
{
storageAccount=CloudStorageAccount.Parse(options.Value.TableStorageConnectionString);
}
公共实体查找(Guid分区键、Guid行键)
{
var retrieveOperation=TableOperation.Retrieve(partitionKey,rowKey);
var retrievedResult=Table.Execute(retrieveOperation);
返回retrievedResult.Result作为SomeEntity;
}
}

除了创建对象的常见开销外,我认为创建
CloudTableClient
CloudTable
对象的多个实例没有任何问题。因此,如果您只是执行以下操作,我认为您不会在性能方面受到影响:

        var tableClient = storageAccount.CreateCloudTableClient();
        var table = tableClient.GetTableReference("farematrix");
但是,我确实看到您在代码(
Table
member)中创建
CloudTable
的方式存在问题。本质上,在代码中,只要您从
EntityStorageComponent
获取
Table
属性,您就会尝试在存储帐户中创建一个表

        var table = tableClient.GetTableReference("farematrix");
        table.CreateIfNotExists(requestOptions, context);

这是一个问题,因为
table.CreateIfNotExists(requestOptions,context)
将进行网络呼叫,并会大大降低系统速度。您可能希望移出
table.CreateIfNotExists(requestOptions,context)编码并将其放在启动代码中,以便您始终(大部分)确定表是否存在。

您能解释一下
的意思吗?我仍然不确定如何最好地维护与Azure表存储的连接。
?@GauravMantri:基本上,
CloudTableClient
CloudTable
实例是否应跨请求重用?我担心的是,每次请求时(可能是每分钟1000次)都必须重新创建这些文件,这会对性能造成损失。答案太棒了。ThanksQuick问题:您是否建议将
ServicePoint
修正案也移至启动(Nagles和ConnectionLimit)?是的。这是系统范围的设置,只能定义一次。在单线程非并发代码中使用CreateIfNotExists时要小心。我犯了一个错误,把它放在处理程序风格的代码中——类似于WCF hander或REST APi处理程序。这将导致多个线程同时运行,并且在第一个线程之后的任何线程都将得到如下错误:“远程服务器返回了一个错误:(409)冲突。”