【问题标题】:Using connection pool with JSCH将连接池与 JSCH 一起使用
【发布时间】:2020-06-10 18:32:58
【问题描述】:

我正在使用 JSCH 进行 sftp 文件上传。在当前状态下,每个线程在需要时打开和关闭连接。

是否可以在 JSCH 中使用连接池以避免大量连接打开和关闭造成的开销?

这是一个从线程内部调用的函数示例

 public static void file_upload(String filename) throws IOException {
    JSch jsch = new JSch();
    Session session = null;
    try {
        session = jsch.getSession("user", "server_name", 22);
        session.setConfig("StrictHostKeyChecking", "no");
        session.setPassword("super_secre_password");
        session.connect();

        Channel channel = session.openChannel("sftp");
        channel.connect();
        ChannelSftp sftpChannel = (ChannelSftp) channel;

        FileInputStream inputSrr = new FileInputStream(filename);  
        try {  
            sftpChannel.put(inputSrr, "/var/temp/"+filename);  
        } catch (SftpException e) {  
            e.printStackTrace();  

        } finally {  
            if (inputSrr != null) {  
                inputSrr.close();  
            }  
        }  

        sftpChannel.exit();
        session.disconnect();
    } catch (JSchException e) {
        e.printStackTrace();
    } catch (SftpException e) {
        e.printStackTrace();
    }
}

【问题讨论】:

    标签: java multithreading connection-pooling sftp jsch


    【解决方案1】:

    为此,我更喜欢commons-pool。 ;)

    【讨论】:

    • 对您有帮助吗?我在问你,因为 stackoverflow 是建立在信誉评分系统之上的。
    • 我正忙于其他项目,所以没有时间尝试。我会尽快通知你。
    • 您能分享一下您是如何实现它的吗?
    • @xmlParser 我已经添加了简单的实现,如果您需要更多详细信息,请随时问我。我会添加更多信息如何配置池以及如何使用它
    【解决方案2】:

    这里是 SSH 连接池的一个实现 http://www.javacodegeeks.com/2013/02/pool-of-ssh-connections-using-apache-keyedobjectpool.html

    你可以使用 grep4j 来使用这个池 https://code.google.com/p/grep4j/source/browse/trunk/src/main/java/org/grep4j/core/command/linux/SessionFactory.java?r=354

    还要确保您可以从执行机器访问服务器。例如,如果目标服务器不在您的范围内。它会抛出连接超时。

    【讨论】:

    • 由于不再维护 grep4j,该实现将在较新版本的 java 上导致类路径问题
    【解决方案3】:

    我想与您分享我们的实现,我们使用了Session Managerjsch-extension library

    首先你需要实现负责池对象生命周期的池对象工厂:

    public class ChannelSftpConnectionsFactory extends BasePooledObjectFactory<ChannelSftp> {
        private SessionManager sessionManager;
    
        public ChannelSftpConnectionsFactory(final SessionManager sessionManager) {
            this.sessionManager = sessionManager;
        }
    
        //Create and open channel
        @Override
        public ChannelSftp create() throws JSchException {
            ChannelSftp channelSftp = (ChannelSftp) sessionManager.getSession().openChannel("sftp");
            channelSftp.connect();
    
            return channelSftp;
        }
    
        //wrapping
        @Override
        public PooledObject<ChannelSftp> wrap(final ChannelSftp channelSftp) {
            return new DefaultPooledObject<>(channelSftp);
        }
    
        @Override
        //disconnect channel on destroy
        public void destroyObject(final PooledObject<ChannelSftp> pooledObject) {
            ChannelSftp sftp = pooledObject.getObject();
            disconnectChannel(sftp);
        }
    
        void disconnectChannel(final ChannelSftp sftp) {
            if (sftp.isConnected()) {
                sftp.disconnect();
            }
        }
    
        @Override
        //reset channel current folder to home if someone was walking on another folders
        public void passivateObject(final PooledObject<ChannelSftp> p) {
            ChannelSftp sftp = p.getObject();
            try {
                sftp.cd(sftp.getHome());
            } catch (SftpException ex) {
                log.error("Could not reset channel to home folder, closing it");
                disconnectChannel(sftp);
            }
        }
    
        @Override
        //validate object before it is borrowed from pool. If false object will be removed from pool
        public boolean validateObject(final PooledObject<ChannelSftp> p) {
            ChannelSftp sftp = p.getObject();
            return sftp.isConnected() && !sftp.isClosed();
        }
    }
    

    现在您可以使用配置的工厂创建池:

    ObjectPool<ChannelSftp> createPool(final SessionManager sessionManager, final GenericObjectPoolConfig<ChannelSftp> poolConfig) {
        return PoolUtils.synchronizedPool(new GenericObjectPool<>(buildFactory(sessionManager), poolConfig));
    }
    
    
    PooledObjectFactory<ChannelSftp> buildFactory(final SessionManager sessionManager) {
        return PoolUtils.synchronizedPooledFactory(new ChannelSftpConnectionsFactory(sessionManager));
    }
    

    此 java 文档将帮助您正确配置池:https://commons.apache.org/proper/commons-pool/api-2.6.0/org/apache/commons/pool2/impl/BaseGenericObjectPool.html

    不要忘记正确将对象借入和返回到池中:https://commons.apache.org/proper/commons-pool/api-2.6.0/org/apache/commons/pool2/ObjectPool.html

     Object obj = null;
    
     try {
         obj = pool.borrowObject();
         try {
             //...use the object...
         } catch(Exception e) {
             // invalidate the object
             pool.invalidateObject(obj);
             // do not return the object to the pool twice
             obj = null;
         } finally {
             // make sure the object is returned to the pool
             if(null != obj) {
                 pool.returnObject(obj);
            }
         }
     } catch(Exception e) {
           // failed to borrow an object
     }
    

    【讨论】:

      猜你喜欢
      • 2017-11-18
      • 2018-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多