连接池实现方式

背景:

一次线上问题,发现句柄数非常高,经过定位,发现其实是有方法创建会话,没有关闭导致的。

基于此,在代码里面及时关闭会话,后来想了一下,还是要做一个连接池做管理比较稳妥。

以下是记录了一个方式

 

实现方式

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();
        }
    }
}

 

posted @ 2022-03-11 21:27  aaacarrot  阅读(78)  评论(0编辑  收藏  举报