代理下 Resttemplate 与 HTTPClient 4.5 的连接超时
Connection Timeout for Rest Template with HTTP Client 4.5 under Proxy
如何设置超时?我已经设置了几乎所有的超时配置。通常没有代理它工作正常。当我使用代理连接详细信息进行连接时会出现问题。日志显示正在连接,但没有收到回复。
2020-03-04 19:53:39,751 DEBUG [main] org.springframework.core.log.CompositeLog: HTTP POST https://destinationurl.io/api/agentmanagement/v3/oauth/token
2020-03-04 19:53:39,803 DEBUG [main] org.springframework.core.log.CompositeLog: Accept=[application/json, application/*+json]
2020-03-04 19:53:39,807 DEBUG [main] org.springframework.core.log.CompositeLog: Writing [grant_type=client_credentials&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion=token--cjKRDhVI0OuYo] as "application/x-www-form-urlencoded"
2020-03-04 19:53:39,821 DEBUG [main] org.apache.http.client.protocol.RequestAuthCache: Auth cache not set in the context
2020-03-04 19:53:39,823 DEBUG [main] org.apache.http.impl.conn.PoolingHttpClientConnectionManager: Connection request: [route: {tls}->http://proxyurl:3128->https://destinationurl.io:443][total kept alive: 0; route allocated: 0 of 20; total allocated: 0 of 100]
2020-03-04 19:53:39,838 DEBUG [main] org.apache.http.impl.conn.PoolingHttpClientConnectionManager: Connection leased: [id: 0][route: {tls}->http://proxyurl:3128->https://destinationurl.io:443][total kept alive: 0; route allocated: 1 of 20; total allocated: 1 of 100]
2020-03-04 19:53:39,839 DEBUG [main] org.apache.http.impl.execchain.MainClientExec: Opening connection {tls}->http://proxyurl:3128->https://destinationurl.io:443
2020-03-04 19:53:40,047 DEBUG [main] org.apache.http.impl.conn.DefaultHttpClientConnectionOperator: Connecting to proxyurl/35.158.73.29:3128
2020-03-04 19:53:40,420 DEBUG [main] org.apache.http.impl.conn.DefaultHttpClientConnectionOperator: Connection established 132.186.74.92:65173<->35.158.73.29:3128
2020-03-04 19:53:40,423 DEBUG [main] org.apache.http.impl.conn.LoggingManagedHttpClientConnection: http-outgoing-0 >> CONNECT destinationurl.io:443 HTTP/1.1
2020-03-04 19:53:40,424 DEBUG [main] org.apache.http.impl.conn.LoggingManagedHttpClientConnection: http-outgoing-0 >> Host: destinationurl.io
2020-03-04 19:53:40,424 DEBUG [main] org.apache.http.impl.conn.LoggingManagedHttpClientConnection: http-outgoing-0 >> User-Agent: Apache-HttpClient/4.5.10 (Java/1.8.0_201)
2020-03-04 19:53:40,424 DEBUG [main] org.apache.http.impl.conn.Wire: http-outgoing-0 >> "CONNECT destinationurl.io:443 HTTP/1.1[\r][\n]"
2020-03-04 19:53:40,424 DEBUG [main] org.apache.http.impl.conn.Wire: http-outgoing-0 >> "Host: destinationurl.io[\r][\n]"
2020-03-04 19:53:40,424 DEBUG [main] org.apache.http.impl.conn.Wire: http-outgoing-0 >> "User-Agent: Apache-HttpClient/4.5.10 (Java/1.8.0_201)[\r][\n]"
2020-03-04 19:53:40,424 DEBUG [main] org.apache.http.impl.conn.Wire: http-outgoing-0 >> "[\r][\n]"
附上日志。
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.11</version>
</dependency>
这是我的配置。我正在使用 spring 引导 2.2.
PoolingHttpClientConnectionManager connectionManager;
if (properties.isAllCertificateAllowed()) {
connectionManager =
new PoolingHttpClientConnectionManager(
buildSocketFactoryRegistry(trustAllSslConnectionSocketFactory(trustAllSslContext())));
} else {
connectionManager = new PoolingHttpClientConnectionManager();
}
RequestConfig config = RequestConfig.custom()
.setSocketTimeout(properties.getConnectTimeout())
.setConnectTimeout(properties.getConnectTimeout())
.setConnectionRequestTimeout(properties.getConnectTimeout())
.build();
/* HttpClientBuilder using http client connection connectionManager */
HttpClientBuilder httpClientBuilder =
HttpClientBuilder.create()
.setConnectionManager(connectionManager)
.useSystemProperties()
.disableCookieManagement()
.setDefaultRequestConfig(config);
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
httpRequestFactory.setConnectTimeout(properties.getConnectTimeout()) ;
httpRequestFactory.setReadTimeout(properties.getReadTimeout());
httpRequestFactory.setConnectionRequestTimeout(properties.getConnectionRequestTimeout());
if (properties.isProxyEnabled()) {
log.info(properties.toString());
/* proxy username ,password name setting */
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(
new AuthScope(properties.getProxyAddress(), properties.getProxyPort()),
new UsernamePasswordCredentials(
properties.getProxyUsername(), properties.getProxyPassword()));
httpClientBuilder.setProxy(
new HttpHost(properties.getProxyAddress(), properties.getProxyPort())); //TODO,"https"
httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
CloseableHttpClient httpClient = httpClientBuilder.build();
httpRequestFactory.setHttpClient(httpClient);
}
RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
看起来是代理问题。 HTTP/HTTPS 应使用您给定的代理详细信息检查代理配置架构。您可以在创建 restTemplate 时提供信任所有证书的选项。请参阅下面的示例以信任所有证书:-
参考:Spring RestTemplate Connection Timeout is not working
示例代码:-
@Bean
public RestTemplate restTemplate(AgentManagementProperties properties) {
PoolingHttpClientConnectionManager connectionManager;
if (properties.isAllCertificateAllowed()) {
connectionManager =
new PoolingHttpClientConnectionManager(
buildSocketFactoryRegistry(trustAllSslConnectionSocketFactory(trustAllSslContext())));
} else {
connectionManager = new PoolingHttpClientConnectionManager();
}
connectionManager.setMaxTotal(properties.getMaxPooledHttpConnections());
connectionManager.setDefaultMaxPerRoute(properties.getMaxHttpConnectionsPerRoute());
RequestConfig config =
RequestConfig.custom()
.setSocketTimeout(properties.getConnectTimeout())
.setConnectTimeout(properties.getConnectTimeout())
.setConnectionRequestTimeout(properties.getConnectTimeout())
.build();
/* HttpClientBuilder using http client connection connectionManager */
HttpClientBuilder httpClientBuilder =
HttpClientBuilder.create()
.setConnectionManager(connectionManager)
.useSystemProperties()
.disableCookieManagement()
.setDefaultRequestConfig(config);
HttpComponentsClientHttpRequestFactory httpRequestFactory =
new HttpComponentsClientHttpRequestFactory();
httpRequestFactory.setConnectTimeout(properties.getConnectTimeout());
httpRequestFactory.setReadTimeout(properties.getReadTimeout());
httpRequestFactory.setConnectionRequestTimeout(properties.getConnectionRequestTimeout());
if (properties.isProxyEnabled()) {
// proxy username and password setting
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(
new AuthScope(properties.getProxyAddress(), properties.getProxyPort()),
new UsernamePasswordCredentials(
properties.getProxyUsername(), properties.getProxyPassword()));
// proxy url, port and schema setting
httpClientBuilder.setProxy(
new HttpHost(
properties.getProxyAddress(),
properties.getProxyPort(),
properties.getProxySchema()));
httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
CloseableHttpClient httpClient = httpClientBuilder.build();
httpRequestFactory.setHttpClient(httpClient);
}
return new RestTemplate(httpRequestFactory);
}
private static Registry<ConnectionSocketFactory> buildSocketFactoryRegistry(
SSLConnectionSocketFactory sslConnectionSocketFactory) {
return RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", new PlainConnectionSocketFactory())
.register("https", sslConnectionSocketFactory)
.build();
}
private static SSLConnectionSocketFactory trustAllSslConnectionSocketFactory(
SSLContext sslContext) {
return new SSLConnectionSocketFactory(sslContext);
}
private static SSLContext trustAllSslContext() {
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("TLS");
sslContext.init(
null,
new TrustManager[] {
new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] arg0, String arg1) {
// NOT IMPLEMENTED Please refer SDK Core
}
public void checkServerTrusted(X509Certificate[] arg0, String arg1) {
// NOT IMPLEMENTED Please refer SDK Core
}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
},
new SecureRandom());
} catch (KeyManagementException | NoSuchAlgorithmException e) {
String errorMessage = "An error occured while configuring ssl context: {}";
log.error(errorMessage, e);
}
return sslContext;
}
如何设置超时?我已经设置了几乎所有的超时配置。通常没有代理它工作正常。当我使用代理连接详细信息进行连接时会出现问题。日志显示正在连接,但没有收到回复。
2020-03-04 19:53:39,751 DEBUG [main] org.springframework.core.log.CompositeLog: HTTP POST https://destinationurl.io/api/agentmanagement/v3/oauth/token
2020-03-04 19:53:39,803 DEBUG [main] org.springframework.core.log.CompositeLog: Accept=[application/json, application/*+json]
2020-03-04 19:53:39,807 DEBUG [main] org.springframework.core.log.CompositeLog: Writing [grant_type=client_credentials&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion=token--cjKRDhVI0OuYo] as "application/x-www-form-urlencoded"
2020-03-04 19:53:39,821 DEBUG [main] org.apache.http.client.protocol.RequestAuthCache: Auth cache not set in the context
2020-03-04 19:53:39,823 DEBUG [main] org.apache.http.impl.conn.PoolingHttpClientConnectionManager: Connection request: [route: {tls}->http://proxyurl:3128->https://destinationurl.io:443][total kept alive: 0; route allocated: 0 of 20; total allocated: 0 of 100]
2020-03-04 19:53:39,838 DEBUG [main] org.apache.http.impl.conn.PoolingHttpClientConnectionManager: Connection leased: [id: 0][route: {tls}->http://proxyurl:3128->https://destinationurl.io:443][total kept alive: 0; route allocated: 1 of 20; total allocated: 1 of 100]
2020-03-04 19:53:39,839 DEBUG [main] org.apache.http.impl.execchain.MainClientExec: Opening connection {tls}->http://proxyurl:3128->https://destinationurl.io:443
2020-03-04 19:53:40,047 DEBUG [main] org.apache.http.impl.conn.DefaultHttpClientConnectionOperator: Connecting to proxyurl/35.158.73.29:3128
2020-03-04 19:53:40,420 DEBUG [main] org.apache.http.impl.conn.DefaultHttpClientConnectionOperator: Connection established 132.186.74.92:65173<->35.158.73.29:3128
2020-03-04 19:53:40,423 DEBUG [main] org.apache.http.impl.conn.LoggingManagedHttpClientConnection: http-outgoing-0 >> CONNECT destinationurl.io:443 HTTP/1.1
2020-03-04 19:53:40,424 DEBUG [main] org.apache.http.impl.conn.LoggingManagedHttpClientConnection: http-outgoing-0 >> Host: destinationurl.io
2020-03-04 19:53:40,424 DEBUG [main] org.apache.http.impl.conn.LoggingManagedHttpClientConnection: http-outgoing-0 >> User-Agent: Apache-HttpClient/4.5.10 (Java/1.8.0_201)
2020-03-04 19:53:40,424 DEBUG [main] org.apache.http.impl.conn.Wire: http-outgoing-0 >> "CONNECT destinationurl.io:443 HTTP/1.1[\r][\n]"
2020-03-04 19:53:40,424 DEBUG [main] org.apache.http.impl.conn.Wire: http-outgoing-0 >> "Host: destinationurl.io[\r][\n]"
2020-03-04 19:53:40,424 DEBUG [main] org.apache.http.impl.conn.Wire: http-outgoing-0 >> "User-Agent: Apache-HttpClient/4.5.10 (Java/1.8.0_201)[\r][\n]"
2020-03-04 19:53:40,424 DEBUG [main] org.apache.http.impl.conn.Wire: http-outgoing-0 >> "[\r][\n]"
附上日志。
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.11</version>
</dependency>
这是我的配置。我正在使用 spring 引导 2.2.
PoolingHttpClientConnectionManager connectionManager;
if (properties.isAllCertificateAllowed()) {
connectionManager =
new PoolingHttpClientConnectionManager(
buildSocketFactoryRegistry(trustAllSslConnectionSocketFactory(trustAllSslContext())));
} else {
connectionManager = new PoolingHttpClientConnectionManager();
}
RequestConfig config = RequestConfig.custom()
.setSocketTimeout(properties.getConnectTimeout())
.setConnectTimeout(properties.getConnectTimeout())
.setConnectionRequestTimeout(properties.getConnectTimeout())
.build();
/* HttpClientBuilder using http client connection connectionManager */
HttpClientBuilder httpClientBuilder =
HttpClientBuilder.create()
.setConnectionManager(connectionManager)
.useSystemProperties()
.disableCookieManagement()
.setDefaultRequestConfig(config);
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
httpRequestFactory.setConnectTimeout(properties.getConnectTimeout()) ;
httpRequestFactory.setReadTimeout(properties.getReadTimeout());
httpRequestFactory.setConnectionRequestTimeout(properties.getConnectionRequestTimeout());
if (properties.isProxyEnabled()) {
log.info(properties.toString());
/* proxy username ,password name setting */
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(
new AuthScope(properties.getProxyAddress(), properties.getProxyPort()),
new UsernamePasswordCredentials(
properties.getProxyUsername(), properties.getProxyPassword()));
httpClientBuilder.setProxy(
new HttpHost(properties.getProxyAddress(), properties.getProxyPort())); //TODO,"https"
httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
CloseableHttpClient httpClient = httpClientBuilder.build();
httpRequestFactory.setHttpClient(httpClient);
}
RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
看起来是代理问题。 HTTP/HTTPS 应使用您给定的代理详细信息检查代理配置架构。您可以在创建 restTemplate 时提供信任所有证书的选项。请参阅下面的示例以信任所有证书:-
参考:Spring RestTemplate Connection Timeout is not working
示例代码:-
@Bean
public RestTemplate restTemplate(AgentManagementProperties properties) {
PoolingHttpClientConnectionManager connectionManager;
if (properties.isAllCertificateAllowed()) {
connectionManager =
new PoolingHttpClientConnectionManager(
buildSocketFactoryRegistry(trustAllSslConnectionSocketFactory(trustAllSslContext())));
} else {
connectionManager = new PoolingHttpClientConnectionManager();
}
connectionManager.setMaxTotal(properties.getMaxPooledHttpConnections());
connectionManager.setDefaultMaxPerRoute(properties.getMaxHttpConnectionsPerRoute());
RequestConfig config =
RequestConfig.custom()
.setSocketTimeout(properties.getConnectTimeout())
.setConnectTimeout(properties.getConnectTimeout())
.setConnectionRequestTimeout(properties.getConnectTimeout())
.build();
/* HttpClientBuilder using http client connection connectionManager */
HttpClientBuilder httpClientBuilder =
HttpClientBuilder.create()
.setConnectionManager(connectionManager)
.useSystemProperties()
.disableCookieManagement()
.setDefaultRequestConfig(config);
HttpComponentsClientHttpRequestFactory httpRequestFactory =
new HttpComponentsClientHttpRequestFactory();
httpRequestFactory.setConnectTimeout(properties.getConnectTimeout());
httpRequestFactory.setReadTimeout(properties.getReadTimeout());
httpRequestFactory.setConnectionRequestTimeout(properties.getConnectionRequestTimeout());
if (properties.isProxyEnabled()) {
// proxy username and password setting
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(
new AuthScope(properties.getProxyAddress(), properties.getProxyPort()),
new UsernamePasswordCredentials(
properties.getProxyUsername(), properties.getProxyPassword()));
// proxy url, port and schema setting
httpClientBuilder.setProxy(
new HttpHost(
properties.getProxyAddress(),
properties.getProxyPort(),
properties.getProxySchema()));
httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
CloseableHttpClient httpClient = httpClientBuilder.build();
httpRequestFactory.setHttpClient(httpClient);
}
return new RestTemplate(httpRequestFactory);
}
private static Registry<ConnectionSocketFactory> buildSocketFactoryRegistry(
SSLConnectionSocketFactory sslConnectionSocketFactory) {
return RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", new PlainConnectionSocketFactory())
.register("https", sslConnectionSocketFactory)
.build();
}
private static SSLConnectionSocketFactory trustAllSslConnectionSocketFactory(
SSLContext sslContext) {
return new SSLConnectionSocketFactory(sslContext);
}
private static SSLContext trustAllSslContext() {
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("TLS");
sslContext.init(
null,
new TrustManager[] {
new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] arg0, String arg1) {
// NOT IMPLEMENTED Please refer SDK Core
}
public void checkServerTrusted(X509Certificate[] arg0, String arg1) {
// NOT IMPLEMENTED Please refer SDK Core
}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
},
new SecureRandom());
} catch (KeyManagementException | NoSuchAlgorithmException e) {
String errorMessage = "An error occured while configuring ssl context: {}";
log.error(errorMessage, e);
}
return sslContext;
}