C# Windows服务-出现FTP提供程序维护窗口时发生不可恢复的FtpWebRequest超时

C# Windows服务-出现FTP提供程序维护窗口时发生不可恢复的FtpWebRequest超时,c#,ftp,timeout,C#,Ftp,Timeout,我有一个windows服务,它每小时定时从FTP服务器下载一个FTP文件。它使用以下代码执行此操作: var _request = (FtpWebRequest)WebRequest.Create(configuration.Url); _request.Method = WebRequestMethods.Ftp.DownloadFile; _request.Timeout = 20000; _request.Credentials = new NetworkCredential("auser

我有一个windows服务,它每小时定时从FTP服务器下载一个FTP文件。它使用以下代码执行此操作:

var _request = (FtpWebRequest)WebRequest.Create(configuration.Url);
_request.Method = WebRequestMethods.Ftp.DownloadFile;
_request.Timeout = 20000;
_request.Credentials = new NetworkCredential("auser", "apassword");

using (var _response = (FtpWebResponse)_request.GetResponse())
using (var _responseStream = _response.GetResponseStream())
using (var _streamReader = new StreamReader(_responseStream))
{
    this.c_fileData = _streamReader.ReadToEnd();
}
通常情况下,下载FTP数据工作正常,但是每隔几个月FTP服务器提供商就会通知我们需要执行一些维护。因此,一旦开始维护(通常只有2或3小时),我们每小时的FTP下载尝试就会失败,即超时,这是意料之中的

问题是,在维护窗口后,我们的windows服务每次尝试下载文件时都会继续超时。我们的windows服务也有重试逻辑,但每次重试都会超时

重新启动windows服务后,应用程序将再次成功下载FTP文件

有人知道为什么我们必须重新启动windows服务才能从该故障中恢复吗?是否可能是网络问题,例如DNS

注1:已经有类似的问题,但它们不涉及维护窗口,也没有任何可信的答案

注意2:我们分析了应用程序的内存,似乎所有ftp对象都被正确处理

注3:我们使用相同的FTP代码在维护窗口后执行了一个控制台应用程序,它工作正常,而windows服务仍在超时


非常感谢任何帮助

我们最终弄清了这个问题的真相,尽管并非所有问题都得到了回答

我们发现,当我们使用不同的内存分析器时,发现两个FtpWebRequest对象在内存中,并且在这个过程中有好几天没有被处理。这些物体是导致问题的原因,即它们没有得到适当处理

从研究来看,为了解决这个问题,我们做了以下工作:

var _request = (FtpWebRequest)WebRequest.Create(configuration.Url);
_request.Method = WebRequestMethods.Ftp.DownloadFile;
_request.Timeout = 20000;
_request.Credentials = new NetworkCredential("auser", "apassword");
_request.KeepAlive = false;
_request.ServicePoint.ConnectionLeaseTimeout = 20000;
_request.ServicePoint.MaxIdleTime = 20000;

try
{
    using (var _response = (FtpWebResponse)_request.GetResponse())
    using (var _responseStream = _response.GetResponseStream())
    using (var _streamReader = new StreamReader(_responseStream))
    {
        this.c_fileData = _streamReader.ReadToEnd();
    }
}
catch (Exception genericException)
{
    throw genericException;
}
finally
{
    _request.Abort();
}
  • 将keep alive设置为false
  • 将连接租约超时设置为有限的超时值
  • 将最大空闲时间设置为有限的超时值
  • 包装在try/catch/finally中,其中请求在finally块中中止
  • 我们将代码更改为以下内容:

    var _request = (FtpWebRequest)WebRequest.Create(configuration.Url);
    _request.Method = WebRequestMethods.Ftp.DownloadFile;
    _request.Timeout = 20000;
    _request.Credentials = new NetworkCredential("auser", "apassword");
    _request.KeepAlive = false;
    _request.ServicePoint.ConnectionLeaseTimeout = 20000;
    _request.ServicePoint.MaxIdleTime = 20000;
    
    try
    {
        using (var _response = (FtpWebResponse)_request.GetResponse())
        using (var _responseStream = _response.GetResponseStream())
        using (var _streamReader = new StreamReader(_responseStream))
        {
            this.c_fileData = _streamReader.ReadToEnd();
        }
    }
    catch (Exception genericException)
    {
        throw genericException;
    }
    finally
    {
        _request.Abort();
    }
    

    老实说,我们不确定是否需要在这里执行所有操作,但问题不再存在,即对象不再挂起,应用程序仍会在维护窗口后运行,因此我们很高兴

    您说过具有相同FTP代码的控制台应用程序不会失败。您是否已经考虑过死锁可能不在此代码范围内?谁调用此代码以及如何调用此代码?我们已经考虑过这一点,但根据堆栈跟踪信息,我们可以确定FTP代码是错误所在。您可以发布堆栈跟踪信息吗?