踩坑背景
最近有个项目使用到了Sftp,部署的时候发现了一个奇怪的现象,当sftp通过ip直接连接的时候,程序是一切正常的,在使用运维给的LB地址时,老是会出现下面这个报错
cn.hutool.extra.ssh.JschRuntimeException: JschException: Session.connect: java.net.SocketException: Connection reset at cn.hutool.extra.ssh.JschUtil.openSession(JschUtil.java:116) at cn.hutool.extra.ssh.JschUtil.openSession(JschUtil.java:97) at cn.hutool.extra.ssh.JschSessionPool.lambda$getSession$64b21fc$1(JschSessionPool.java:45) at cn.hutool.core.lang.SimpleCache.get(SimpleCache.java:112) at cn.hutool.extra.ssh.JschUtil.getSession(JschUtil.java:55) at cn.hutool.extra.ssh.Sftp.init(Sftp.java:166) at cn.hutool.extra.ssh.Sftp.init(Sftp.java:93) at cn.hutool.extra.ssh.Sftp.init(Sftp.java:80) at cn.hutool.extra.ssh.Sftp.init(Sftp.java:70) at cn.hutool.extra.ssh.Sftp.init(Sftp.java:56) at
报错的同时,在服务器上尝试使用命令行LB地址连接Sftp却是一切正常的!!!同时经过排查发现,当程序刚启动尝试第一次连接的时候并没有出现这个奇怪的问题,正当我看这个奇怪的堆栈百思不得其解的时候,突然注意到了一个奇怪的打印
at cn.hutool.core.lang.SimpleCache.get(SimpleCache.java:112)
经过排查发现,hutool的Sftp工具类是默认开启了一个JschSessionPool的连接池,默认的直接使用 new Sftp(…) 或者 JschUtil.getSession(…) 都会把新建立的连接放到 JschSessionPool 这个连接池中,而恰恰就是这个连接池导致的问题!!!
修改方案
如果你也是使用的hutool Sftp工具类且涉及一些比较复杂的网络场景,建议跳过Hutool的Sftp自带的连接池逻辑,改成直接使用 JschUtil.createSession(…) 手动建立连接并且手动释放,这种场景反而更好做一些细粒度的控制
教训总结
在使用一个工具类前,必须要大致了解其底层实现逻辑以及相关issue,避免老是踩前辈们踩过的坑!!!!!!!!!!