【问题标题】:Why do I get java.net.SocketTimeoutException with OkHttp?为什么我会使用 OkHttp 获得 java.net.SocketTimeoutException?
【发布时间】:2019-12-16 04:07:39
【问题描述】:

这是我的配置:

httpClient = new OkHttpClient.Builder()
        .callTimeout(Duration.ofSeconds(60))
        .connectTimeout(Duration.ofSeconds(60))
        .readTimeout(Duration.ofSeconds(60))
        .writeTimeout(Duration.ofSeconds(60))
        .build();

我有一个使用此客户端的多线程进程。 几秒钟后 跑步后我得到:

java.net.SocketTimeoutException:超时
在 okio.Okio$4.newTimeoutException(Okio.java:232)
在 okio.AsyncTimeout.exit(AsyncTimeout.java:286)
在 okio.AsyncTimeout$2.read(AsyncTimeout.java:241)
在 okio.RealBufferedSource.indexOf(RealBufferedSource.java:358)

如果我将超时设置为 60 秒,怎么可能?

编辑:
即使添加自定义调度程序也无济于事:

Dispatcher dispatcher = new Dispatcher();
dispatcher.setMaxRequests(Integer.MAX_VALUE);
dispatcher.setMaxRequestsPerHost(Integer.MAX_VALUE);

技术细节:
与我所说的相反,我在 Linux 机器上同时运行客户端和服务器:

客户端机器:net.ipv4.tcp_keepalive_time = 7200
服务器的机器:net.ipv4.tcp_keepalive_time = 7200

【问题讨论】:

标签: java http okhttp3


【解决方案1】:

您很可能受到操作系统强加的套接字超时的影响。 Java 不能扩展它们,因为套接字是由系统管理的。根据this great answer, "Changing TCP Timeouts" section

不幸的是,由于 TCP 连接是在操作系统级别管理的,Java 不支持在每个套接字级别配置超时,例如在 java.net.Socket 中。我发现一些尝试使用 Java 本地接口 (JNI) 创建调用本地代码来配置这些选项的 Java 套接字,但似乎没有一个得到广泛的社区采用或支持。

对于 MacOS,您必须查看 sysctl net.inet.tcp 输出并查看系统限制。

【讨论】:

  • 谢谢 Karol(我猜同样的命令也适用于 Linux,对吧?)
  • 总而言之,在应用程序级别(在 Java 中)定义超时是没有意义的,因为套接字超时是在操作系统级别定义的。
  • 在我的 linux 机器上我看到:net.ipv4.tcp_keepalive_time = 7200
  • 您可以减少 Java 中的超时限制,但不能将其增加到超过操作系统超时限制。在这一点上,我不明白您是否在 MacOS 或 Linux 上遇到此超时,限制取决于操作系统。重写您的问题以明确指定导致问题的操作系统和代码,现在很难理解。
【解决方案2】:

我认为问题出在其他地方。超时确实有效。我在我的机器上尝试了以下操作,它工作了 30 秒

package test;

import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 *
 * @author jingged
 */
public class Test {
OkHttpClient httpClient = null;
     void initClient(){
        httpClient = new OkHttpClient.Builder()
        .connectTimeout(30, TimeUnit.SECONDS)
        .readTimeout(30, TimeUnit.SECONDS)
        .writeTimeout(30, TimeUnit.SECONDS)
        .build();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        Test test = new Test();
        test.initClient();
        for(int i = 0;i<10;i++){
            new Thread(new Runnable(){
                @Override
                public void run() {
                   Request request = new Request.Builder().url("https://10.255.255.1").build();
                   Instant start = Instant.now();
                   try (Response response = test.httpClient.newCall(request).execute()) {
                        String s =  response.body().string();
                        System.out.println(s);
                    } catch (IOException ex) {
                        if (ex instanceof java.net.SocketTimeoutException){
                            System.err.print("Socket TimeOut");
                        }else{
                            ex.printStackTrace();
                        }
                    }
                   Instant end = Instant.now();
                    Duration interval = Duration.between(start, end);
                    System.out.println("Execution time " + interval.getSeconds()+" seconds");
                }

            }).start();
        }
    }
}

输出:

Execution time 30 seconds
Execution time 30 seconds
Execution time 30 seconds
Execution time 30 seconds
Execution time 30 seconds
Execution time 30 seconds
Execution time 30 seconds
Execution time 30 seconds
Execution time 30 seconds
Execution time 30 seconds
Socket TimeOutSocket TimeOutSocket TimeOutSocket TimeOutSocket TimeOutSocket TimeOutSocket TimeOutSocket TimeOutSocket TimeOutSocket TimeOut
BUILD SUCCESSFUL (total time: 32 seconds)

试试上面的代码。上面代码中提到的 url 将产生 TimeOut 异常,因为它不存在,但超时时间应该保持 30 秒。 顺便说一句,我在 MAC OS High Sierra 上用 Java 8 和 netbeans 8.2 用 okhttp3 测试了这个

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-09
    • 2019-12-25
    • 1970-01-01
    相关资源
    最近更新 更多