Sftp连接池

本文介绍了使用Jsch实现Sftp连接池来提高大量小文件下载效率的情况。通过静态HashMap保持session,但缺乏守护线程管理。在压力测试后,发现在同一目录下文件超过1000个时,下载速度下降,怀疑是文件检索速度变慢。解决方案包括使用线程池接收报文、报文解析、Sftp操作工具类以及维护多个服务器连接的Map。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

由于需要下载大量的小文件,使用Jsch开发了一个小型Sftp连接池。
主要思路是使用类的静态变量HashMap用于保持session,缺少守护线程管理。
压测后效果很明显,但当在同一目录上传的文件超过1000个以后下载速度变慢,将同目录下文件删除以后速度又回升。由此推测出是文件太多导致文件检索变慢

1.main方法,新建一个线程池,用于接收报文
线程池介绍链接:http://www.crazyant.net/2124.html?uwtoli=ohppy

package com.cgb.Main;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.apache.log4j.Logger;

import com.cgb.Util.Log;
import com.cgb.Util.ReadProperties;


public class SocketMain {
	public static Logger logger = Log.getLogger(SocketMain.class);
	public static ExecutorService ex = Executors.newFixedThreadPool(ReadProperties.getThreadPoolSize());
	public static void main(String[] args) throws IOException {
		// 端口号
		final int port = ReadProperties.getServerPort();
		ServerSocket socket = null;
		try {
			// 绑定端口号
			socket = new ServerSocket(port);
			while(true){
				Socket clientSocket = socket.accept();
				logger.info("有一个客户端连接");
				ex.execute(new XmlRecv(clientSocket));
			}
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			socket.close();
			ex.shutdown();
		}
	}
}

2.报文的接收类:

package com.cgb.Main;

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.Socket;

import org.apache.log4j.Logger;

import com.cgb.Util.Log;
import com.cgb.Util.ReadProperties;
import com.cgb.Util.XmlUtil;

public class XmlRecv extends Thread {
	private BufferedOutputStream out;
	private InputStreamReader in;
	private Socket socket;
	private boolean result = false;

	public static Logger logger = Log.getLogger(XmlRecv.class);

	@Override
	public void run() {
		String charSet = ReadProperties.getCharSet();
		try {
			// 保存输入流
			in = new InputStreamReader(socket.getInputStream(), charSet);
			// 准备输出流
			out = new BufferedOutputStream(socket.getOutputStream());
			// 翻译接收到的报文,并执行SFTP操作
			XmlTranslate xmlTranslate = new XmlTranslate(in);
			logger.info("开始进行报文检查");
			result = xmlTranslate.checkXml();
			// 输出应答报文

			out.write(XmlUtil.retrunXml(charSet, result, "0000", "文件传输成功!")
					.getBytes(charSet));

			out.flush();
			socket.close();

		} catch (UnsupportedEncodingException e) {
			logger.info(Log.getTrace(e));
			e.printStackTrace();
		} catch (IOException e) {
			logger.info(Log.getTrace(e));
			e.printStackTrace();
		}
	}

	public XmlRecv(Socket clientSocket) {
		this.socket = clientSocket;
	}
}

3.报文的翻译,解析

package com.cgb.Main;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import com.cgb.Bean.SftpInfo;
import com.cgb.Service.SftpService;
import com.cgb.Util.Log;
import com.cgb.Util.XmlUtil;

public class XmlTranslate {
	private InputStreamReader in;
	public static Logger logger = Log.getLogger(XmlTranslate.class);
	public static ExecutorService ex = Executors.newFixedThreadPool(20);
	
	public InputStreamReader getIn() {
		return in;
	}
	
	public void setIn(InputStreamReader in) {
		this.in = in;
	}
	
	public XmlTranslate(InputStreamReader in) {
		super();
		this.in = in;
	}
	
	public boolean checkXml(){
        BufferedReader bufferedReader = new BufferedReader(this.in);
        

        try {
			/*while((lsStr = bufferedReader.readLine())!=null){
			    //追加到字符串缓冲区存放
				xmlStr.append(lsStr);
			}*/
			// 先读取8位长度
			char[] cha = new char[8];
			bufferedReader.read(cha, 0, 8);
			String xmlLength = String.valueOf(cha);
			// 正则去除字符串中的0
		    xmlLength = xmlLength.replaceAll("^(0+)", "");
		    logger.debug(&#
要在Spring Boot中配置SFTP连接池,可以使用Apache Commons VFS2库。 首先,您需要在pom.xml文件中添加以下依赖项: ```xml <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-vfs2</artifactId> <version>2.7.0</version> </dependency> ``` 然后,您可以配置SFTP连接池。以下是一个例子: ```java @Configuration public class SftpConfig { @Value("${sftp.host}") private String sftpHost; @Value("${sftp.port}") private int sftpPort; @Value("${sftp.username}") private String sftpUsername; @Value("${sftp.password}") private String sftpPassword; @Value("${sftp.poolSize}") private int sftpPoolSize; @Bean public GenericObjectPool<ChannelSftp> sftpPool() throws JSchException { JSch jsch = new JSch(); Session session = jsch.getSession(sftpUsername, sftpHost, sftpPort); session.setPassword(sftpPassword); session.setConfig("StrictHostKeyChecking", "no"); session.connect(); SftpConnectionFactory factory = new SftpConnectionFactory(session); GenericObjectPoolConfig<ChannelSftp> config = new GenericObjectPoolConfig<>(); config.setMaxTotal(sftpPoolSize); config.setTestOnBorrow(true); return new GenericObjectPool<>(factory, config); } } ``` 在这个例子中,我们使用JSch库连接SFTP服务器,并使用Apache Commons Pool库来创建连接池。您需要在application.properties或application.yml文件中设置SFTP连接属性。 ```yaml sftp: host: sftp.example.com port: 22 username: username password: password poolSize: 10 ``` 现在,您可以使用sftpPool bean注入连接池,并使用连接池中的连接执行SFTP操作。例如: ```java @Service public class SftpService { private final GenericObjectPool<ChannelSftp> sftpPool; public SftpService(GenericObjectPool<ChannelSftp> sftpPool) { this.sftpPool = sftpPool; } public void downloadFile(String remotePath, String localPath) throws Exception { ChannelSftp sftp = sftpPool.borrowObject(); try { sftp.get(remotePath, localPath); } finally { sftpPool.returnObject(sftp); } } } ``` 在这个例子中,我们使用borrowObject方法从池中获取一个连接。执行操作后,我们使用returnObject方法将连接返回到池中。 这是一个简单的示例,您可以根据您的需求进行修改。希望对您有所帮助!
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值