gpt4 book ai didi

c# - transient 故障重试逻辑最佳实践

转载 作者:行者123 更新时间:2023-12-02 03:34:35 25 4
gpt4 key购买 nike

friend 们,我有一个关于围绕 SQL 命令执行实现简单重试策略的问题。

我的问题是:重试循环应该封装连接和事务的构造,还是应该位于连接内部。

例如:

private void RetryLogSave(DynamicParameters parameters, int retries = 3)
{
int tries = 0;

using (var connection = new SqlConnection(_connectionString))
{
connection.Open();

using (var transaction = connection.BeginTransaction())
{
var logItemCommand = new CommandDefinition(commandText: Constants.InsertLogItem,
parameters: parameters, transaction: transaction, commandType: System.Data.CommandType.Text);

do
{
try
{
tries++;
connection.Execute(logItemCommand);
transaction.Commit();
break;
}
catch (Exception exc)
{
if (tries == retries)
{
transaction.Rollback();
throw exc;
}
Task.Delay(100 * tries).Wait();
}
}
while (true);
}
}
}

我在这里所做的是否适当且可以接受,或者重试逻辑是否应该存在于 SqlConnection 构造的外部?

最佳答案

将我的评论正式化为答案。

should the retry logic live on the outside of the SqlConnection construction?

是的。如果在保持连接打开的情况下执行重试逻辑,则会浪费资源。当你等待N秒重试时,其他人可能会使用它。打开/关闭连接通常(对于大多数 ODBC 驱动程序)是在连接池机制之上实现的。您实际上并没有关闭它 - 您允许连接返回到池中以供其他人重用。在重试期间保持连接打开将迫使系统创建越来越多的新物理连接(因为它们不会返回到池中),最终您的 SQL Server 将耗尽。

关于重试机制 - 为了不重新发明轮子,我通常使用 Polly图书馆。

您可以使用策略列表定义某个静态类:

public static class MyPolices
{
// Retry, waiting a specified duration between each retry
public static Policy RetryPolicy = Policy
.Handle<Exception>() // can be more specific like SqlException
.WaitAndRetry(new[]
{
TimeSpan.FromSeconds(1),
TimeSpan.FromSeconds(2),
TimeSpan.FromSeconds(3)
});
}

然后,将您的方法简化为

private void LogSave(DynamicParameters parameters)
{
using (var connection = new SqlConnection(_connectionString))
{
connection.Open();

using (var transaction = connection.BeginTransaction())
{
// make sure to not forget to dispose your command
var logItemCommand = new CommandDefinition(commandText: Constants.InsertLogItem,
parameters: parameters, transaction: transaction, commandType: System.Data.CommandType.Text);

try
{
// not sure if conn.Execute is your extension method?
connection.Execute(logItemCommand);
transaction.Commit();
}
catch (Exception exc)
{
transaction.Rollback();
throw;
}
}
}
}

并这样调用它

MyPolices.RetryPolicy.Execute(() => LogSave(parameters));

这种方法将使您的代码更加可靠,保持重试逻辑的隔离。

关于c# - transient 故障重试逻辑最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50657087/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com