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

Apache Axis 1.4 SOAP请求SSLSocket握手超时问题求助

问题分析

从你提供的错误栈和描述来看,这个问题的核心是Axis 1.4默认的JSSESocketFactory没有为SSL握手阶段设置超时。你配置的30秒超时只作用于Socket的读写阶段,而SSL握手是在Socket连接建立后单独执行的原生操作,默认会使用JDK的全局SSL超时(通常是15分钟左右,和你遇到的1000秒吻合),导致系统长时间挂起才抛出异常。

下面给你几个可行的解决方案,按推荐优先级排序:


方案1:利用Java 7+的原生SSL握手超时API(最简洁)

如果你的项目已经升级到Java 7或更高版本,SSLSocket类原生提供了setHandshakeTimeout方法,可以直接在握手前设置超时时间。你需要重写Axis的JSSESocketFactory,在创建Socket后、触发握手前插入超时配置:

1.1 自定义SocketFactory类

public class TimeoutEnabledJSSESocketFactory extends JSSESocketFactory {
    // 自定义握手超时时间(毫秒)
    private static final int HANDSHAKE_TIMEOUT_MS = 30000;

    @Override
    public Socket create(Socket tunnel, String host, int port, boolean autoClose) throws IOException {
        // 调用父类方法创建SSLSocket
        Socket socket = super.create(tunnel, host, port, autoClose);
        if (socket instanceof SSLSocket) {
            SSLSocket sslSocket = (SSLSocket) socket;
            // 设置握手超时为30秒
            sslSocket.setHandshakeTimeout(HANDSHAKE_TIMEOUT_MS, TimeUnit.MILLISECONDS);
        }
        return socket;
    }

    // 同时重写不带tunnel的create方法,覆盖所有场景
    @Override
    public Socket create(String host, int port, StringBuffer otherHeaders, Boolean useFullURL) throws IOException {
        Socket socket = super.create(host, port, otherHeaders, useFullURL);
        if (socket instanceof SSLSocket) {
            SSLSocket sslSocket = (SSLSocket) socket;
            sslSocket.setHandshakeTimeout(HANDSHAKE_TIMEOUT_MS, TimeUnit.MILLISECONDS);
        }
        return socket;
    }
}

1.2 替换Axis的默认SocketFactory

在你的Axis客户端配置文件(axis.xml)中,将HTTPS传输的socketFactory替换为自定义类:

<transport name="https" pivot="java:org.apache.axis.transport.http.HTTPSender">
    <parameter name="socketFactory" value="com.yourcompany.TimeoutEnabledJSSESocketFactory"/>
    <!-- 保留你原来的其他超时配置 -->
    <parameter name="http.socket.timeout" value="30000"/>
    <parameter name="http.connection.timeout" value="30000"/>
</transport>

方案2:JDK版本低于7?用线程中断强制超时

如果你的项目还在使用Java 6或更早版本,没有原生的握手超时API,可以通过FutureTask将握手操作放到子线程中,超时后中断线程并关闭Socket:

2.1 封装超时工具方法

public static SSLSocket createSSLSocketWithHandshakeTimeout(
        SocketFactory sslFactory, Socket tunnel, String host, int port, 
        boolean autoClose, int timeoutMs) throws Exception {
    
    FutureTask<SSLSocket> handshakeTask = new FutureTask<>(() -> {
        SSLSocket sslSocket = (SSLSocket) sslFactory.createSocket(tunnel, host, port, autoClose);
        sslSocket.startHandshake(); // 手动触发握手
        return sslSocket;
    });

    Thread handshakeThread = new Thread(handshakeTask);
    handshakeThread.start();

    try {
        // 等待超时时间内完成握手
        return handshakeTask.get(timeoutMs, TimeUnit.MILLISECONDS);
    } catch (TimeoutException e) {
        // 超时后中断线程并关闭Socket
        handshakeThread.interrupt();
        try {
            if (!handshakeTask.isCancelled()) {
                handshakeTask.get().close();
            }
        } catch (Exception ex) {
            // 忽略关闭时的异常
        }
        throw new IOException("SSL handshake timed out after " + timeoutMs + "ms", e);
    }
}

2.2 替换原有的Socket创建逻辑

把你代码中的sslFactory.createSocket(...)调用替换为工具方法:

// 原代码:sslSocket = sslFactory.createSocket(tunnel, host, port, true);
// 替换为:
sslSocket = createSSLSocketWithHandshakeTimeout(sslFactory, tunnel, host, port, true, 30000);

注意:线程中断对原生SSL握手的中断效果可能存在差异,但大多数场景下会触发SocketException,达到超时断开的目的。


方案3:补充Axis的全局超时配置(辅助验证)

确保你已经完整配置了Axis的所有超时参数,避免其他环节的超时遗漏:

  • 在客户端Stub代码中设置:
    YourServiceStub stub = new YourServiceStub();
    stub.setTimeout(30000); // 设置调用超时
    
  • 在axis.xml中补充HTTP传输的超时:
    <transport name="http" pivot="java:org.apache.axis.transport.http.HTTPSender">
        <parameter name="http.socket.timeout" value="30000"/>
        <parameter name="http.connection.timeout" value="30000"/>
    </transport>
    

这些配置主要作用于Socket的读写阶段,无法直接解决SSL握手超时,但能确保整个调用链路的超时一致性。


内容的提问来源于stack exchange,提问作者Eldon Hipolito

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:44:51