jsch的sftp在多线程下的问题及处理办法
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jsch的sftp在多线程下的问题及处理办法相关的知识,希望对你有一定的参考价值。
参考技术A SftpUtil2 :测试程序:
该程序使用多线程并发操作sftp,在多线程中共用一个 ChannelSftp ,就会出异常,具体如下:
在 SftpUtil 中使用ThreadLocal包装ChannelSftp、Session保证线程安全。
在 Test3 中使用 parallelStream().forEach 完成多线程并发操作 sftp 。
SftpUtil
Test3 :
使用单线程上传 1458 个文件,每个 500kb ,进行三次测试,平均耗时为: 68732 毫秒
使用多线程上传 1458 个文件,每个 500kb ,进行三次测试,平均耗时为: 67117 毫秒
通过测试,可以看到使用多线程操作确实能提升效率,但是,其提升非常有限,却带来了较高的复杂性,在使用中更加建议通过单线程的方式。如果,需要将sftp封装成工具类供他人使用,需要提醒多线程并发的问题,或为了保险起见,也可以在sftp工具类中使用 ThreadLocal 包装 ChannelSftp 和 Session 。
jsch连接sftp后连接未释放掉问题排查
项目中通过jsch中的sftp实现上传下载文件。代码上了服务器之后,内存飙升,逐渐把swap区也占满,通过top监控未发现占用内存的进程,通过查找sshd进程,发现服务器多了很多sftp的进程没有被关闭。
刚开始以为是sftp公共方法设计的有问题,下面是部分代码片段
@Repository("SftpClient") public class SftpClient private Logger logger = LoggerFactory.getLogger(SftpClient.class); private ThreadLocal<Session> sessionLocal = new ThreadLocal<Session>(); private ThreadLocal<ChannelSftp> channelLocal = new ThreadLocal<ChannelSftp>(); //初始化连接 public SftpClient init() try String host = SFTP_HOST; int port = Integer.valueOf(SFTP_PORT); String userName = SFTP_USER_NAME; String password = SFTP_USER_PASSWORD; Integer timeout = Integer.valueOf(SFTP_TIMEOUT); Integer aliveMax = Integer.valueOf(SFTP_ALIVEMAX); // 创建JSch对象 JSch jsch = new JSch(); Session session = jsch.getSession(userName, host, port); // 根据用户名,主机ip,端口获取一个Session对象 if (password != null) // 设置密码 session.setPassword(password); // 为Session对象设置properties session.setConfig("StrictHostKeyChecking", "no"); if (timeout != null) // 设置timeout时间 session.setTimeout(timeout); if (aliveMax != null) session.setServerAliveCountMax(aliveMax); // 通过Session建立链接 session.connect(); // 打开SFTP通道 ChannelSftp channel = (ChannelSftp) session.openChannel("sftp"); // 建立SFTP通道的连接 channel.connect(); channelLocal.set(channel); sessionLocal.set(session); logger.debug("SSH Channel connected.session=,channel=", session, channel); catch (JSchException e) throw new SystemException(ImageExceptionCode.FTP_SEND_ERROR); return this; //断开连接 public void disconnect() ChannelSftp channel = channelLocal.get(); Session session = sessionLocal.get(); //断开sftp连接 if (channel != null) channel.disconnect(); logger.debug("SSH Channel disconnected.channel=", channel); //断开sftp连接之后,再断开session连接 if (session != null) session.disconnect(); logger.debug("SSH session disconnected.session=", session); channelLocal.remove(); sessionLocal.remove();
以上是关于jsch的sftp在多线程下的问题及处理办法的主要内容,如果未能解决你的问题,请参考以下文章
Java.util.ConcurrentModificationException异常产生及解决办法