You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java应用SSH连接远程服务器收发请求性能优化及替代API咨询

优化SSH+端口访问的高性能替代方案

现有实现的性能瓶颈分析

你的代码耗时主要来自这几个核心问题:

  1. 每次请求通过shell通道执行远程telnet命令,shell环境初始化、命令执行本身就有额外开销
  2. 硬编码的sleep 2强制等待,无意义地增加了请求耗时
  3. 通过BufferedReader解析shell交互式输出,处理逻辑复杂且容易出错,还会引入额外的IO等待

即使缓存了SSH会话,每次创建shell通道并执行telnet命令的开销依然无法避免,这是导致性能差、扩展性不足的根本原因。

推荐的优化方案:SSH端口转发

不需要在远程执行telnet命令,直接利用SSH的本地端口转发功能,把本地端口的请求通过SSH隧道转发到远程服务器的目标端口。这样你可以直接在本地用Socket连接转发后的端口,发送请求并接收响应,性能会大幅提升。

方案一:基于JSch的优化实现

复用SSH会话并建立端口转发,避免每次执行远程命令:

import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import java.io.*;
import java.net.Socket;

public class OptimizedSshPortForward {
    private static Session cachedSession;
    private static int localForwardPort;

    // 初始化并缓存SSH会话,建立端口转发
    private static void initSession(String userName, String password, String host, int targetPort) throws Exception {
        if (cachedSession == null || !cachedSession.isConnected()) {
            JSch jsch = new JSch();
            cachedSession = jsch.getSession(userName, host, 22);
            cachedSession.setPassword(password);
            cachedSession.setConfig("StrictHostKeyChecking", "no");
            // 调整保活间隔,减少不必要的网络包
            cachedSession.setServerAliveInterval(30000);
            cachedSession.connect(30000);
            // 绑定本地随机端口,转发到远程的targetPort
            localForwardPort = cachedSession.setPortForwardingL(0, "localhost", targetPort);
        }
    }

    public static void sendRequest(String payload, int targetPort) throws Exception {
        initSession(userName, password, HOST, targetPort);
        
        Socket socket = null;
        OutputStream out = null;
        InputStream in = null;
        BufferedReader reader = null;
        
        try {
            // 连接本地转发端口,等价于直接连接远程目标端口
            socket = new Socket("localhost", localForwardPort);
            out = socket.getOutputStream();
            in = socket.getInputStream();
            reader = new BufferedReader(new InputStreamReader(in));

            // 发送请求 payload
            out.write((payload + "\n").getBytes());
            out.flush();

            // 读取响应(根据实际响应结束逻辑调整判断条件)
            StringBuilder result = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                if (line.contains("Connection closed by foreign host")) {
                    break;
                }
                result.append(line).append("\n");
            }

            handleResponse(result.toString());
        } finally {
            // 仅关闭本地Socket和流,保留SSH会话复用
            if (reader != null) reader.close();
            if (in != null) in.close();
            if (out != null) out.close();
            if (socket != null) socket.close();
        }
    }

    // 程序退出时统一关闭缓存的会话
    public static void shutdown() {
        if (cachedSession != null && cachedSession.isConnected()) {
            cachedSession.disconnect();
        }
    }

    private static void handleResponse(String result) {
        // 替换为你的响应处理逻辑
        System.out.println("Response received:\n" + result);
    }

    // 替换为实际的配置信息
    private static final String userName = "your_username";
    private static final String password = "your_password";
    private static final String HOST = "remote_server_host";
}

方案二:使用更现代的SSH库——Apache MINA SSHD

如果想替换JSch,Apache MINA SSHD是更现代的选择,API更友好,支持异步操作,扩展性更好:

import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.forward.LocalPortForwardingTracker;
import java.io.*;
import java.net.Socket;

public class MinaSshdPortForwardExample {
    private static SshClient sshClient;
    private static ClientSession cachedSession;
    private static LocalPortForwardingTracker forwardingTracker;

    private static void initSession(String userName, String password, String host, int targetPort) throws Exception {
        if (sshClient == null) {
            sshClient = SshClient.setUpDefaultClient();
            sshClient.start();
        }
        if (cachedSession == null || !cachedSession.isOpen()) {
            cachedSession = sshClient.connect(userName, host, 22)
                    .verify(30000)
                    .getSession();
            cachedSession.addPasswordIdentity(password);
            cachedSession.auth().verify(30000);
            // 配置会话保活
            cachedSession.setKeepAliveCountMax(5);
            cachedSession.setKeepAliveInterval(30000);
            // 建立本地端口转发
            forwardingTracker = cachedSession.createLocalPortForwardingTracker(0, "localhost", targetPort);
            forwardingTracker.start();
        }
    }

    public static void sendRequest(String payload, int targetPort) throws Exception {
        initSession(userName, password, HOST, targetPort);
        int localPort = forwardingTracker.getBoundPort();
        
        Socket socket = null;
        OutputStream out = null;
        InputStream in = null;
        BufferedReader reader = null;
        
        try {
            socket = new Socket("localhost", localPort);
            out = socket.getOutputStream();
            in = socket.getInputStream();
            reader = new BufferedReader(new InputStreamReader(in));

            out.write((payload + "\n").getBytes());
            out.flush();

            StringBuilder result = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                if (line.contains("Connection closed by foreign host")) {
                    break;
                }
                result.append(line).append("\n");
            }

            handleResponse(result.toString());
        } finally {
            if (reader != null) reader.close();
            if (in != null) in.close();
            if (out != null) out.close();
            if (socket != null) socket.close();
        }
    }

    public static void shutdown() throws Exception {
        if (forwardingTracker != null) forwardingTracker.close();
        if (cachedSession != null && cachedSession.isOpen()) cachedSession.close();
        if (sshClient != null && sshClient.isStarted()) sshClient.stop();
    }

    private static void handleResponse(String result) {
        System.out.println("Response received:\n" + result);
    }

    // 替换为实际配置
    private static final String userName = "your_username";
    private static final String password = "your_password";
    private static final String HOST = "remote_server_host";
}

性能与扩展性提升要点

  1. 移除远程命令执行开销:直接通过SSH隧道传输数据,避免shell环境初始化、telnet命令执行的额外耗时
  2. 会话复用最大化:缓存SSH会话和端口转发,每次请求仅建立本地Socket连接,开销极低
  3. 异步支持:Apache MINA SSHD支持异步操作,可轻松实现高并发请求处理
  4. 灵活的连接管理:可扩展为会话池,应对多租户或高并发场景
  5. 移除硬编码等待:基于实际响应结束条件判断,避免无意义的等待时间

内容的提问来源于stack exchange,提问作者Balaji Podapati

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 11:45:44