net操作ftp连接数暴增TIME_WAIT问题解决

德冠谈科技 2024-05-04 06:26:37

本次是2020年在生产环境遇到的问题手稿记录,解决的问题是 ftp 操作导致大量的【TIME_WAIT】,现整理发出,希望帮助到有需要的人。

一、问题描述

这个问题是在生产环境出现的,由于测试环境数据量小,程序很快运行完成,ftp 连接能被快速释放,所以一直没出现这个问题。

运维反馈,在 ftp 服务器监控到大量的连接【TIME_WAIT】,经查是一些 .net 程序导致的,如下前面三个都是部署了 .net 程序的服务器:

后面的是部署在 docker 容器中的 java 程序,数据还比较正常。

这些程序用的工具类可能是同一个(或者大同小异),所以批量出现了。

二、问题分析与解决

由于测试环境没有重现这个问题,那么要解决这个问题需要在测试环境重现一下,好对症下药。

程序伪代码逻辑主要如下:

void Start(){ foreach (int item in list) { ... DownloadFile(...,path); ... UploadPdf(...); }}byte[] DownloadFile(...,string path){ var ftpUtil = new FtpUtil("10.10.60.16", "ftp", "123"); return ftpUtil.DownloadFile(...,path);}int UploadPdf(...,byte[] buffer){ var ftpUtil = new FtpUtil("10.10.60.16", "ftp", "123"); ftpUtil.UploadFile(..., buffer);}

由上可看出代码是有缺陷的,首先一点,由于 ftp 对象初始化都是一样的,没必要每处理一次就 new 一个 FtpUtil 对象实例,这意味着每次都会建立一个新的FTP连接,这样做可能会导致连接池溢出或者频繁地创建和关闭连接,影响性能并增加TIME_WAIT连接的数量。

第一个优化点:将FtpUtil实例创建移到循环外部,以便在整个循环过程中重用同一个实例,从而减少连接建立和关闭的次数。

程序涉及到 ftp 操作是先下载文件,然后上传文件,问题应该是出现在 ftp 工具类中实现下载和上传的两个方法中。

编写了一个单元测试项目用来重现此问题,就是模拟取一定量的订单实现上面的下载和上传逻辑,当只实现下载的时候问题没出现,加了上传逻辑才出现问题,说明上次方法有问题。

基本信息:

本机客户端 ip:10.138.30.229ftp ip :10.138.60.16ftp 端口:21

上传过程中发现:

本次设置了100次,运行完成后统计发现产生了100次 连接:

当程序关闭后一两分钟后终于被释放(公共的 ftp 服务器其它程序也会用):

问题终于复现了。

这到底啥原因呢?

要了解原因,首先要了解 TIME_WAIT 是什么意思?

TIME_WAIT 表示的是客户端在操作 ftp 后进入的等待状态。

那为什么会出现大量的 TIME_WAIT 呢?

经查代码发现 FtpWebRequest 类有个属性【KeepAlive】,指定在请求完成之后是否关闭到 FTP 服务器的控制连接,源码解释如下:

// // 摘要: // 获取或设置一个 System.Boolean 值,该值指定在请求完成之后是否关闭到 FTP 服务器的控制连接。 // // 返回结果: // 如果不应销毁到服务器的连接,则为 true;否则为 false。默认值为 true。 // // 异常: // T:System.InvalidOperationException: // 对于一个已在进行的请求为此属性指定了一个新值。 public bool KeepAlive { get; set; }

默认是 true,但是在上传方法中设置的是 false,则表示客户端在请求完成之后要关闭 FTP 服务器的控制连接,但是由于服务端是在收到客户端发送关闭连接命令之后才会去主动关闭连接,由于有大批量的请求,所以造成服务器上比较容易出现大量的 TIME_WAIT 状态的连接,特别是并发量较大时更易出现。

如果不设置这个属性,那么默认是 true,整个程序生命周期中只有一个连接,请求完成之后不会关闭,一直会处于 ESTABLISHED 状态,直到程序结束才会被释放,如:

0 阅读:25

德冠谈科技

简介:感谢大家的关注