Я нашел org.apache.commons.pool чрезвычайно полезным и надежным, но недостаточно хорошо задокументированным. Итак, я постараюсь немного помочь, объясняя, как использовать Apache KeyedObjectPool . Что такое KeyedObjectPool ? Это карта, которая содержит пул экземпляров нескольких типов. К каждому типу можно получить доступ с помощью произвольного ключа. В этом примере я создам пул ssh-соединений JSch и в качестве ключа буду использовать простой объект-установщик геттера, называемый ServerDetails. В основном для каждого сервера я хочу иметь пул из 10 повторно используемых соединений SSH. Поэтому первое, что нужно сделать, — это создать Sessionfactory, класс, отвечающий за создание фактического объекта, который вы хотите сохранить в пуле. В нашем примере это было бы соединение ssh.
Sessionfactory необходимо расширить BaseKeyedPoolableObjectFactory <K, V>, где K — это тип ключей в этом пуле, а V — это тип объектов, хранящихся в этом пуле. All you need to do is implement the метод makeObject, в котором вам нужно фактически создать объект в пуле, и destroyObject, где, очевидно, вам нужно реализовать код, когда объект освобождается и помещается обратно в пул.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
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 не освободит его соединение.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
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-соединение из пула, нам просто нужно позвонить:
|
1
|
StackSessionPool.getInstance().getPool().borrowObject(serverDetails) |
где serverDetails — наш ключ (нам нужен пул ssh-соединений на сервер).
Когда соединение больше не нужно, мы помещаем его обратно в пул с помощью:
|
1
|
StackSessionPool.getInstance().getPool().returnObject(serverDetails, session); |
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
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; }} |
Не забудьте закрыть пул, когда он вам больше не нужен, с помощью StackSessionPool.getInstance (). GetPool (). Close ();
Ссылка: пул ssh-соединений с использованием Apache KeyedObjectPool от нашего партнера по JCG Марко Кастильего из блога « Удалить дублирование и исправить дурные имена» .