在非常关键的C#.NET Windows服务中管理SFTP连接时遇到了很大的麻烦,该服务广泛分布在我们的客户中。
发生的事情是,即使连接,断开连接,下载,上传和远程文件夹dir等简单操作有时也会卡住,并且冻结了整个服务,即使“ services.msc”中报告的状态为“正在运行”。这个问题不是很普遍,在重要的网络状态下也不会发生,我根本无法重现,并且可能在服务启动后10分钟甚至1个月内发生。
在我们的案例中,我们使用Renci SSH.NET处理SFTP,但是挂起和冻结似乎也是其他SFTP库(WinSCP .NET API,SharpSSH等。仅在网络上搜索)中一个很普遍的问题。考虑到此服务是一项每隔30分钟运行一次的关键业务服务,如果冻结该服务可能会使客户面临法律问题并处以罚款,因此它绝不能因任何原因而停止。可以有关键的例外,但不允许冻结。
为了避免将来出现类似这样的问题,与所采用的SFTP API无关(我们正在考虑移至WinSCP.NET以查看是否更好),我想知道如何在中管理这些紧急情况。 NET应用程序。我有以下想法,但我有很大的缺点:
在具有Wait()的任务中,在任务中环绕SFTP客户端交互,如下所示:
private SftpClient _client = new SftpClient();
private sub Upload() {
var task = Task.Factory.StartNew(() => {
if(!_client.Connected) _client.Connect(); // Handle SFTP connection
_client.Upload(...); // Handle SFTP upload
});
task.Wait(3600000); // Wait 1 hour. If it fails who cares as long as it won't lock my service's main thread.
}
这可以工作,但是通过这种方式,线程之间共享Sftp客户端对象,并且如果API套接字不是完全线程安全的(谁知道),则可能导致问题。我也无法继续创建SftpClient对象并为每个SFTP交互打开/关闭它们,因为频繁的连接会降低性能,并加剧该问题。而且,Wait()不会中止任务线程,但是会在超时后在调用者线程上引发异常。因此,子线程将永远卡住,并且如果API处于不一致状态(我正在考虑API内的静态内容),则可能导致下一次执行时出现意外行为(连接问题,错误的阅读,错误的写作和等等...)。资源也不会发生处置,因此会发生内存泄漏。
在线程中环绕SFTP客户端交互,并在长时间超时后中止它。这也可以工作,但是MSDN https://docs.microsoft.com/it-it/dotnet/api/system.threading.thread.abort?view=netframework-4.7.2中的免责声明对我来说是个很大的反对。
创建一个Windows计划的任务,该任务定期NET STOP和NET START服务。这样可以减轻问题,但是在每台客户服务器上执行此操作确实很痛苦。
使用的SFTP库不会被卡住,但是会在挂断时间过长的情况下引发异常。 这将是一个梦想,但是在FTP和SFTP API之间挂起相当普遍。
在涉及重大事务(例如人类安全,航空航天或军事装备,财务等)的.NET中,您将如何处理关键服务?带有线程的“看门狗”编程模式在这里似乎不起作用,因为.NET依赖于协作线程停止。
一些想法?