连接池实现方式
背景:
一次线上问题,发现句柄数非常高,经过定位,发现其实是有方法创建会话,没有关闭导致的。
基于此,在代码里面及时关闭会话,后来想了一下,还是要做一个连接池做管理比较稳妥。
以下是记录了一个方式
实现方式
package com.file.service.utils;
import com.jcraft.jsch.ChannelSftp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.integration.file.remote.session.Session;
import org.springframework.integration.file.remote.session.SessionFactory;
import org.springframework.stereotype.Component;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Sftp会话连接池
*
* @author HuangXiaoFeng
* @version $id:SftpSessionPool.java, v 1 2022/3/11 09:58:33, HuangXiaoFeng Exp $
*/
@Component
public class SftpSessionPool {
private SessionFactory<ChannelSftp.LsEntry> sftpSessionFactory;
@Autowired
public void setSftpSessionFactory(SessionFactory<ChannelSftp.LsEntry> sftpSessionFactory) {
this.sftpSessionFactory = sftpSessionFactory;
}
private ConcurrentLinkedQueue<Session> sessionPool = new ConcurrentLinkedQueue<>();
// sftp 连接池大小
@Value("${sftp.poolSize:30}")
private int poolSize;
private AtomicInteger currentSize = new AtomicInteger(0);
/**
* 初如化session连接池
*/
private synchronized void createSession() {
Session session = sftpSessionFactory.getSession();
sessionPool.add(session);
currentSize.incrementAndGet();
}
/**
* 获取一个session
*/
public synchronized Session getSession() {
if (sessionPool.size() > 0) {
Session session = sessionPool.poll();
Object proxyInstance = Proxy.newProxyInstance(SftpSessionPool.class.getClassLoader(), session.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (!"close".equals(method.getName())) {
return method.invoke(session, args);
} else {
sessionPool.add(session);
}
return null;
}
});
return (Session) proxyInstance;
} else {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (sessionPool.size() == 0 && currentSize.intValue() < poolSize) {
createSession();
}
return getSession();
}
}
}