前言
项目中使用到了sftp,平时都会用到这个,但是线上也从来没有出现过什么大的问题,但是最近上线了一个流量比较大的项目,也使用到了sftp,在上线的那一刻崩了。。。
正文
项目中使用的JSch,Jsch提供了sftp的各类操作的Java实现
最开始排查只是从日志中发现是sftp这一块的错误,所以大家都把关注点放到了这一块;由于sftp的底层代码是封装好的,我们都是业务直接调用这个工具类,我就去看了这一块的业务代码,就发现了一个流程上的小问题:需要从sftp服务器下载四个文件,但是是用的for循环去下载文件,而每次下载都是要走一遍登录,下载,登出;所以我就把这四次下载合并成一次下载,但是最后的结果却并没有发生好转;所以我走到这里就束手无策了;后来是我们老大发现了问题,原来是在工具类下面,每次下载文件都会在服务器执行ls命令,然后轮询要下载的文件是否存在;问题就是ls命令,在文件少的时执行很快,但是当文件多了呢,成千上万的文件的时候,ls就比较耗时了; 最后就是把判断文件是否存在的这段代码去掉,就可以了(根据自身业务判断,因为这次项目的文件都是必须存在的,不存在业务也不会继续进行,所以就舍去了判断文件是否存在这一部分);然后在后面又出现了一个bug,就是把之前的四个下载文件的流程合并到一起之后,会出现存在的文件无法下载的情况,最后发现是传入的路径问题,原因分析:之前每下载一个文件都会登录一次,登录之后就是在起始目录(默认情况下是),这时不管传入的是相对路径还是绝对路径,都是从起始目录开始的;但是当四个文件和到一个流程里面之后,由于下载第一个文件的时候,已经进入了第一个文件所在的目录,后面的文件如果传入的是相对路径,这时就会以第一个文件所在的目录为起始位置,进行查找,所以文件不存在,就无法下载,最后就是把文件路径修改为绝对路径,或者文件下载完成后退出到起始目录;
最后
总结
- JSch操作sftp服务器执行ls命令是比较耗时的;
- 注意文件是相对路径还是绝对路径的问题
- 注意多线程下调用JSch操作sftp的线程安全问题:例如创建文件或创建文件夹