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

Spring Webflux+Apache HttpCore5代理隧道连接异常解决咨询

解决Spring WebClient + Apache HttpCore5代理隧道抛出“No tunnel unless connected”异常

问题核心原因

在JDK 1.8_252环境下,Spring 2.3.x的WebClient搭配Apache HttpCore5时,默认的代理隧道建立逻辑存在适配冲突:HttpCore5的连接管理器在隧道初始化前可能提前关闭了与代理的连接,而JDK8u252的网络参数限制又加剧了这个问题,最终触发该异常。

具体解决方案

1. 自定义HttpCore5客户端配置,强制维护隧道连接

手动构建HttpAsyncClient时,显式添加连接拦截逻辑,确保隧道建立前与代理的连接保持存活。

示例代码:

import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager;
import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.nio.AsyncClientEndpoint;
import org.springframework.http.client.reactive.HttpComponentsClientHttpConnector;
import org.springframework.web.reactive.function.client.WebClient;

public class WebClientProxyConfiguration {

    public WebClient buildProxyEnabledWebClient() {
        // 代理服务器地址和端口
        HttpHost proxyServer = new HttpHost("your-proxy-host", 8080);

        // 构建连接管理器,设置连接池参数
        PoolingAsyncClientConnectionManager connManager = PoolingAsyncClientConnectionManagerBuilder.create()
                .setMaxConnTotal(200)
                .setMaxConnPerRoute(50)
                .build();

        // 配置请求参数,绑定代理
        RequestConfig requestConfig = RequestConfig.custom()
                .setProxy(proxyServer)
                .setConnectTimeout(5000)
                .setConnectionRequestTimeout(5000)
                .build();

        // 构建HttpAsyncClient,添加隧道连接拦截器
        CloseableHttpAsyncClient asyncClient = HttpAsyncClients.custom()
                .setConnectionManager(connManager)
                .setDefaultRequestConfig(requestConfig)
                // 关键拦截器:确保隧道建立前端点已连接
                .addInterceptorFirst((request, entity, context) -> {
                    HttpClientContext clientCtx = HttpClientContext.adapt(context);
                    AsyncClientEndpoint endpoint = clientCtx.getEndpoint();
                    if (endpoint != null && !endpoint.isConnected()) {
                        endpoint.connect();
                    }
                })
                .build();

        // 绑定到WebClient
        HttpComponentsClientHttpConnector connector = new HttpComponentsClientHttpConnector(asyncClient);
        return WebClient.builder().clientConnector(connector).build();
    }
}

2. 调整JDK 1.8_252的网络参数

通过JVM启动参数修改默认网络超时和存活策略,避免连接过早关闭:

# 设置默认连接和读取超时
-Dsun.net.client.defaultConnectTimeout=10000
-Dsun.net.client.defaultReadTimeout=30000
# 开启HTTP长连接
-Dhttp.keepAlive=true
# 禁用IPv6优先,避免连接兼容问题
-Djava.net.preferIPv6Addresses=false

3. 补充代理认证(如果需要)

若代理服务器要求认证,需在客户端配置中添加认证信息:

import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
import org.apache.hc.client5.http.auth.AuthScope;

// 在构建AsyncClient前添加认证配置
BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(
        new AuthScope("your-proxy-host", 8080),
        new UsernamePasswordCredentials("proxy-user", "proxy-pass".toCharArray())
);

CloseableHttpAsyncClient asyncClient = HttpAsyncClients.custom()
        // ...其他配置
        .setDefaultCredentialsProvider(credentialsProvider)
        .build();

4. 版本兼容性检查

确保使用的Apache HttpCore5版本与Spring 2.3.x兼容,推荐使用5.1.x版本的HttpCore5依赖,避免版本不匹配导致的逻辑冲突。

5. 开启调试日志定位问题

添加HttpCore5的调试日志,查看隧道建立过程的详细交互,排查具体连接关闭点:

<!-- Logback配置示例 -->
<logger name="org.apache.hc.client5.http" level="DEBUG"/>
<logger name="org.apache.hc.core5.http" level="DEBUG"/>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 06:35:08