繁体   English   中英

Sftp 重试逻辑 Azure function App

[英]Sftp Retry Logic Inside Azure function App

我面临一个问题,我收到间歇性错误消息

“现有连接被远程主机强行关闭”

在尝试连接 sftp 服务器时。 我正在尝试在 azure function 应用程序中连接 sftp。 我相信在存在连接问题时会发生此错误。

为了处理这个问题,我需要实施重试逻辑,以防万一发生此类错误,以指定的延迟重复连接 sftp 服务器,直到达到配置的最大重试次数。 我相信 function 应用程序允许的最大执行时间是 5 分钟(需要从 azure 专家那里听到)。

谁能帮助我如何在 C# 中实现此重试功能?

我正在使用Renci.SshNet nuget package 来管理 sftp

using (var _sftpCn = new SftpClient(host, port, userName, password))
{
    _sftpCn.Connect();//error happens on this line:"An existing connection was forcibly closed by the remote host"
    log.LogInformation("Successful");
    byte[] byteArray = Encoding.UTF8.GetBytes(datacontent);
    sftpCl.WriteAllBytes("{remotePath}", byteArray);
    log.LogInformation("Sent successfully");
    _sftpCn.Disconnect();
}

我建议在这里使用Polly

Polly 是一个 .NET 弹性和瞬态故障处理库,允许开发人员以流畅和线程安全的方式表达重试、断路器、超时、隔板隔离和回退等策略。

它是免费的库,可以通过以下命令下载为nuget package

do.net add package Polly

它还有很多东西,请参阅此处此处以获取更多详细信息和示例。

如果您查看Connect方法的源代码,那么您会发现它有关于异常的文档注释。 不幸的是,他们都没有提到您所面临的错误信息。

正如您在评论中所述,您不知道引发了哪个异常,因为您的日志记录系统仅捕获异常消息。 您怀疑是SSHExceptionSShConnectionException

对于 Polly,您可以针对这种情况以多种方式定义重试策略

  1. 使用单个Handle生成器方法
var retryPolicy = Policy
      .Handle<Exception>(ex => ex is SSHException || ex is SShConnectionException)
      .WaitAndRetry(...); 
  1. 使用HandleOr构建器方法
var retryPolicy = Policy
      .Handle<SSHException>()
      .Or<SShConnectionException>()
      .WaitAndRetry(...); 
  1. 如果抛出的异常不是任何可疑的异常
    那么你可以用一种类型安全性较低的方式定义你的策略
const string ErrorPrefix = "An existing connection was forcibly closed by the remote host";
var retryPolicy = Policy
      .Handle<Exception>(ex => ex.Message.StartsWith(ErrorPrefix) 
          || (ex.InnerException?.Message.StartsWith(ErrorPrefix) ?? false))
      .WaitAndRetry(...); 

你也提到了

function 应用程序允许的最长执行时间为 5 分钟

Polly 的重试允许您定义最多要执行相同操作的次数:

  • N次:这可以通过使用RetryWaitAndRetry构建器方法来实现
  • 无限次:这可以通过使用RetryForeverWaitAndRetryForever构建器方法来实现

如果您想在给定的时间范围内执行重试尝试,则需要组合重试和超时策略。

var timeoutPolicy = Policy.Timeout(TimeSpan.FromMinutes(4.5));
var retryPolicy = Policy
      .Handle...
      .WaitAndRetryForever(...);
var combinedPolicy = Policy.Wrap(timeoutPolicy, retryPolicy);

请记住Wrap方法参数的顺序很重要:

  • 超时,重试:这里的超时是全局的,这意味着它会覆盖所有重试尝试
  • 重试,超时:这里的超时是本地的,这意味着它分别应用于每次重试尝试

这种灵活性允许您定义每次重试尝试和总体时间限制

var globalTimeoutPolicy = Policy.Timeout(TimeSpan.FromMinutes(4.5));
var perAttemptTimeoutPolicy = Policy.Timeout(TimeSpan.FromSeconds(5));
var retryPolicy = Policy
      .Handle...
      .WaitAndRetryForever(...);
var combinedPolicy = Policy.Wrap(globalTimeoutPolicy, retryPolicy, perAttemptTimeoutPolicy);

我希望这些示例可以帮助您解决问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM