使用Apache KeyedObjectPool的ssh连接池

本文介绍了如何使用Apache KeyedObjectPool创建一个JSch SSH连接池。通过创建SessionFactory并扩展BaseKeyedPoolableObjectFactory来管理不同服务器的SSH连接。每个服务器有10个可重用的SSH连接,当超过限制时,新请求会等待。使用PoolSessionPool.getInstance().getPool().close()关闭连接池。
摘要由CSDN通过智能技术生成

我发现org.apache.commons.pool非常有用且健壮,但没有充分记录。 因此,我将在这里帮助您解释如何使用Apache KeyedObjectPool 什么是KeyedObjectPool ? 它是一个映射,其中包含多种类型的实例池。 可以使用任意键访问每种类型。 在此示例中,我将创建一个JSch ssh连接池,并将使用一个名为ServerDetails的简单getter setter对象作为键。 基本上,对于每个服务器,我希望有10个可重用的ssh连接池。 因此,首先要做的是创建一个Sessionfactory,一个负责创建要存储在池中的实际对象的类。 在我们的示例中,这将是ssh连接。

Sessionfactory需要扩展BaseKeyedPoolableObjectFactory <K,V>,其中K是此池中键的类型, V是此池中保存的对象的类型。 All you need to do is implement the makeObject方法, All you need to do is implement the方法需要在池中实际创建对象,而destroyObject显然需要在释放对象并将其放回池中时实现代码。

package org.grep4j.core.command.linux;
import org.apache.commons.pool.BaseKeyedPoolableObjectFactory;
import org.grep4j.core.model.ServerDetails;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.UserInfo;
/**
 * This class is used to handle ssh Session inside the pool.
 * 
 * @author Marco Castigliego
 *
 */
public class SessionFactory extends BaseKeyedPoolableObjectFactory<ServerDetails, Session> {

        /**
         * This creates a Session if not already present in the pool.
         */
        @Override
        public Session makeObject(ServerDetails serverDetails) throws Exception {
                Session session = null;
                try {
                        JSch jsch = new JSch();
                        session = jsch.getSession(serverDetails.getUser(), serverDetails.getHost(), serverDetails.getPort());
                        session.setConfig('StrictHostKeyChecking', 'no'); // 
                        UserInfo userInfo = new JschUserInfo(serverDetails.getUser(), serverDetails.getPassword());
                        session.setUserInfo(userInfo);
                        session.setTimeout(60000);
                        session.setPassword(serverDetails.getPassword());
                        session.connect();
                } catch (Exception e) {
                        throw new RuntimeException(
                                        'ERROR: Unrecoverable error when trying to connect to serverDetails :  ' + serverDetails, e);
                }
                return session;
        }

        /**
         * This is called when closing the pool object
         */
        @Override
        public void destroyObject(ServerDetails serverDetails, Session session) {
                session.disconnect();
        }
}

您需要做的第二件事是创建实际的密钥池对象。 在我们的示例中,我们创建一个拥有StackKeyedObjectPool的单例。 数字10是池中“睡眠”实例数量的上限。 如果11个客户端尝试为同一服务器获取ssh连接,第11个客户端将等待,直到前10个客户端之一释放其连接。

package org.grep4j.core.command.linux;
import org.apache.commons.pool.KeyedObjectPool;
import org.apache.commons.pool.impl.StackKeyedObjectPool;
import org.grep4j.core.model.ServerDetails;
import com.jcraft.jsch.Session;
/**
 * Pool controller. This class exposes the org.apache.commons.pool.KeyedObjectPool class.
 * 
 * @author Marco Castigliego
 *
 */
public class StackSessionPool {

        private KeyedObjectPool<ServerDetails, Session> pool;

        private static class SingletonHolder {
                public static final StackSessionPool INSTANCE = new StackSessionPool();
        }

        public static StackSessionPool getInstance() {
                return SingletonHolder.INSTANCE;
        }

        private StackSessionPool()
        {
                startPool();
        }

        /**
         * 
         * @return the org.apache.commons.pool.KeyedObjectPool class
         */
        public KeyedObjectPool<ServerDetails, Session> getPool() {
                return pool;
        }

        /**
         * 
         * @return the org.apache.commons.pool.KeyedObjectPool class
         */
        public void startPool() {
                pool = new StackKeyedObjectPool<ServerDetails, Session>(new SessionFactory(), 10);
        }
}

如何使用它,简单明了。 要从池中获取ssh连接,我们只需要调用:

StackSessionPool.getInstance().getPool().borrowObject(serverDetails)

其中,serverDetails是我们的关键(我们希望每个服务器有一个ssh连接池)。

当不再需要连接时,我们使用以下命令将其放回池中:

StackSessionPool.getInstance().getPool().returnObject(serverDetails, session);
package org.grep4j.core.command.linux;

import org.grep4j.core.command.ExecutableCommand;
import org.grep4j.core.model.ServerDetails;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.Session;
/**
 * The SshCommandExecutor uses the net.schmizz.sshj library to execute remote
 * commands.
 * 
 * <ol>
 * <li>Establish a connection using the credential in the {@link serverDetails}</li>
 * <li>Opens a session channel</li>
 * <li>Execute a command on the session</li>
 * <li>Closes the session</li>
 * <li>Disconnects</li>
 * </ol>
 * 
 * @author Marco Castigliego
 * 
 */
public class JschCommandExecutor extends CommandExecutor {

        public JschCommandExecutor(ServerDetails serverDetails) {
                super(serverDetails);
        }

        @Override
        public CommandExecutor execute(ExecutableCommand command) {
                Session session = null;
                Channel channel = null;
                try {

                        session = StackSessionPool.getInstance().getPool()
                                        .borrowObject(serverDetails);
                        //...do stuff
                } catch (Exception e) {
                        throw new RuntimeException(
                                        'ERROR: Unrecoverable error when performing remote command '
                                                        + e.getMessage(), e);
                } finally {
                        if (null != channel && channel.isConnected()) {
                                channel.disconnect();
                        }
                        if (null != session) {
                                try {
                                        StackSessionPool.getInstance().getPool()
                                                        .returnObject(serverDetails, session);
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                        }
                }

                return this;
        }
}

请记住,当您不再需要使用PoolSessionPool.getInstance()。getPool()。close()时,关闭该池。

参考: 使用来自我们的JCG合作伙伴 Marco Castigliego的Apache KeyedObjectPool的ssh连接池,位于“ 删除重复和修复不良名称”博客中。

翻译自: https://www.javacodegeeks.com/2013/02/pool-of-ssh-connections-using-apache-keyedobjectpool.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值