connectTimeOut和readTimeout怎么设置超时都很长

connectTimeOut和readTimeout

网络编程时,经常遇到很多timeout异常,下面是java URLConnection 中经典的2种 timeout参数,这些参数设置不当的话,就会遇到timeout 异常。
 

1. ConnectTimeout , java 是这样解释的。 意思是用来建立连接的时间。如果到了指定的时间,还没建立连接,则报异常。

 

 

Sets a specified timeout value, in milliseconds, to be used when opening a communications link to the resource referenced by this URLConnection. If the timeout expires before the connection can be established, a java.net.SocketTimeoutException is raised. A timeout of zero is interpreted as an infinite timeout. 

Some non-standard implmentation of this method may ignore the specified timeout. To see the connect timeout set, please call getConnectTimeout().

 

 

经典异常如下所示:

 

java.net.SocketTimeoutException: connect timed out
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at sun.net.www.protocol.http.HttpURLConnection$6.run(HttpURLConnection.java:1491)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.net.www.protocol.http.HttpURLConnection.getChainedException(HttpURLConnection.java:1485)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1139)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234)
    at 。。。。。。(Unknown Source)
Caused by: java.net.SocketTimeoutException: connect timed out
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:351)
    at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:213)
    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:200)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)
    at java.net.Socket.connect(Socket.java:529)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:564)
    at sun.net.NetworkClient.doConnect(NetworkClient.java:158)
    at sun.net.www.http.HttpClient.openServer(HttpClient.java:395)
    at sun.net.www.http.HttpClient.openServer(HttpClient.java:530)
    at sun.net.www.protocol.https.HttpsClient.<init>(HttpsClient.java:272)
    at sun.net.www.protocol.https.HttpsClient.New(HttpsClient.java:329)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.getNewHttpClient(AbstractDelegateHttpsURLConnection.java:172)
    at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:911)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:158)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1172)
    at sun.net.www.protocol.http.HttpURLConnection.getHeaderField(HttpURLConnection.java:2300)
    at java.net.URLConnection.getHeaderFieldInt(URLConnection.java:579)
    at java.net.URLConnection.getContentLength(URLConnection.java:474)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getContentLength(HttpsURLConnectionImpl.java:378)
    at 。。。。。。(Unknown Source)

 

 

通过 URLConnection setConnectTimeout 可以设置指定的值。0则指极大值。

        conn = url.openConnection();
                    
        conn.setConnectTimeout(5000);

 

2. ReadTimeout , java 是这样解释的。 意思是已经建立连接,并开始读取服务端资源。如果到了指定的时间,没有可能的数据被客户端读取,则报异常。

 

 

Sets the read timeout to a specified timeout, in milliseconds. A non-zero value specifies the timeout when reading from Input stream when a connection is established to a resource. If the timeout expires before there is data available for read, a java.net.SocketTimeoutException is raised. A timeout of zero is interpreted as an infinite timeout. 

Some non-standard implementation of this method ignores the specified timeout. To see the read timeout set, please call getReadTimeout().

 

 

类似报错信息如下:

 

 

java.net.SocketTimeoutException: Read timed out
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
	at sun.net.www.protocol.http.HttpURLConnection$6.run(HttpURLConnection.java:1491)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.net.www.protocol.http.HttpURLConnection.getChainedException(HttpURLConnection.java:1485)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1139)
	at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234)
	at 。。。。。。(Unknown Source)
Caused by: java.net.SocketTimeoutException: Read timed out
	at java.net.SocketInputStream.socketRead0(Native Method)
	at java.net.SocketInputStream.read(SocketInputStream.java:129)
	at com.sun.net.ssl.internal.ssl.InputRecord.readFully(InputRecord.java:293)
	at com.sun.net.ssl.internal.ssl.InputRecord.read(InputRecord.java:331)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:830)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1170)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1197)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1181)
	at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434)
	at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1172)
	at sun.net.www.protocol.http.HttpURLConnection.getHeaderField(HttpURLConnection.java:2300)
	at java.net.URLConnection.getHeaderFieldInt(URLConnection.java:579)
	at java.net.URLConnection.getContentLength(URLConnection.java:474)
	at sun.net.www.protocol.https.HttpsURLConnectionImpl.getContentLength(HttpsURLConnectionImpl.java:378)
	at 。。。。。。(Unknown Source)

 

 

通过 URLConnection setReadTimeout 可以设置指定的值。0则指极大值。

        conn = url.openConnection();

        conn.setReadTimeout(20000);

 

类似的设置在很多软件都基本相同的,比如 wget.

 

 -T,  --timeout=SECONDS         set all timeout values to SECONDS.
      --dns-timeout=SECS        set the DNS lookup timeout to SECS.
      --connect-timeout=SECS    set the connect timeout to SECS.
      --read-timeout=SECS       set the read timeout to SECS.


 

 

 

 

 

,但是实际的情况是当时专网的时候(不能访问百度)根本不是1.5秒抛出超时的异常,这个问题困扰2天,

也在网上查询很多资料,结果有人说还要设置读取超时conn.setReadTimeout(1500);结果一试还是不行,

就再找发现有人在使用的情况下查看控制台发现访问1500毫秒之后系统会自动的尝试很多次(集体多少次没有算)

导致很长时间才抛出访问超时异常,这样导致我们看到的现象就是我设置了1500毫秒超时结果几分钟才给我超时异常,感觉设置的超时时间没有效果。

 

那么说一下我的解决方法,我个人测试通过,如果有好的方法请指出:

因为系统会自动的尝试很多次超时之后才给你抛出异常,所以我把这个异常超时时间设置短一点如我设置500毫秒,公网的情况下能正常的访问,专网也能很快的抛出异常达到了我的目的。

另外判断公网专网的另一种方法就是用ping ,记得要起一个服务区处理ping,关闭之后要杀死改进程,否则第二次ping可能就阻塞了。

`RestTemplate` 是 Spring Boot 中用于发送 HTTP 请求的一个工具类,它封装了多个与网络通信相关的功能,并且支持异步操作。默认情况下,`RestTemplate` 的连接建立、请求发送和响应接收等操作都有一定的超时限制。这些超时设置包括连接超时、读取超时、写入超时等。 为了进行长连接并调整超时时间,你可以通过以下几种方式之一来进行配置: ### 1. 使用 `HttpClientProperties` 配置 Spring 提供了一个名为 `HttpClientProperties` 的类,可以用来自定义 HttpClient 的配置。对于 RestTemplate 来说,这通常意味着配置的是整个应用级别的超时属性,而不是针对某个具体的 REST API 调用。 ```java @Configuration public class HttpClientConfig { @Bean public ClientHttpRequestFactory clientHttpRequestFactory() { // 创建一个 HttpClientConfigurer 实例,并配置需要的超时属性 HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(); HttpClientBuilder builder = HttpClients.custom(); // 设置全局超时时间(例如,设置总连接超时时间为5秒) int connectionTimeoutMs = 5000; int socketTimeoutMs = 60000; // 设置读取超时时间为60秒 builder.setConnectionManager(new PoolingHttpClientConnectionManager()); builder.setDefaultRequestConfig(RequestConfig.custom() .setConnectTimeout(connectionTimeoutMs) .setSocketTimeout(socketTimeoutMs) .build()); return factory; } } ``` ### 2. 直接在 `RestTemplate` 对象上设置超时 如果你想针对特定的 `RestTemplate` 实例或 API 调用进行超时时间的调整,可以在创建该实例时直接提供一个带有自定义超时属性的 `ClientHttpRequestFactory`。 ```java @Bean public RestTemplate restTemplate(HttpClientProperties properties) { // 获取自定义的 HttpClientConfigurer 实例 ClientHttpRequestFactory requestFactory = httpClientConfigurer(properties).getFactory(); // 创建一个带有自定义超时属性的 RestTemplate 实例 RestTemplate restTemplate = new RestTemplate(requestFactory); // 这样做的效果是仅对这个 restTemplate 的请求应用上述超时配置 return restTemplate; } ``` ### 关联问题: 1. **如何检查`RestTemplate`的超时配置是否生效?** 可以通过模拟一次远程调用,并检查返回的结果或异常信息来验证配置是否按预期工作。如果配置不当,可能会遇到超时导致的异常。 2. **为什么设置长连接超时很重要?** 设置合适的超时时间有助于避免因长时间等待无响应而引起的资源浪费,同时也能提高系统的稳定性及响应速度。过短的时间可能导致系统频繁尝试重建连接,而过长则会增加延迟,影响用户体验和性能。 3. **在高并发场景下,如何优化`RestTemplate`的使用?** 在高并发环境下,合理利用线程池管理连接、适当提升超时阈值、以及采用批处理机制可以有效提高系统的整体吞吐量和效率。同时,考虑使用更高级的功能如 `WebClient` 或者自定义的 HTTP 客户端,这些客户端可能提供了更多的并发控制选项和优化策略。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值