【问题标题】:Sometimes HttpURLConnection.getInputStream executes too slowly有时 HttpURLConnection.getInputStream 执行太慢
【发布时间】:2010-12-27 14:19:45
【问题描述】:

我们有下一个代码。
有时我们应该在最后一行等待 10-20-40 秒。
可能是什么问题?

Java 1.4

URL url = ...;
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.connect();
OutputStream out = conn.getOutputStream();
ObjectOutputStream outStream = new ObjectOutputStream(out);
try
{
   outStream.writeObject(objArray);
}
finally
{
   outStream.close();
}

InputStream input = conn.getInputStream();

更新:
下一个代码修复了 ECLIPSE 中的问题。
但它仍然不能通过 Java WebStart 工作:(

HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
conn.setDoInput(true);  
conn.setDoOutput(true);  
conn.setUseCaches(false);  
System.setProperty("http.keepAlive", "false");  //<---------------
conn.connect();  

但是为什么呢?

再更新一次!
错误已修复! :)

我们不是在一个班级而是在两个班级工作。
第二类有以下行:

URL url = ...  
HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
conn.setRequestProperty("Content-Length", "1000");  //<------------
conn.connect();  

注意: setRequestProperty("Content-Length", "1000") 是问题的根本原因。

【问题讨论】:

  • 为什么openConnection被调用了两次?
  • 只是印刷错误。已更正。
  • 为什么是 Content-Length 问题呢?

标签: java http tomcat servlets


【解决方案1】:

尝试使用 IP 地址。看看是不是 DNS 问题。

【讨论】:

  • 我们在不同的计算机和不同的国家解决了这个问题:(
  • 你用 Wireshark 看过了吗?
【解决方案2】:

问题可能来自网络子层......应该很难找到它。

但是,setReadTimeOut() 的价值较低且有一个 while 循环呢?

【讨论】:

    【解决方案3】:

    我猜一件事是您的 DNS 服务器响应不佳。

    您可以在开始之前尝试将符号域名更改为数字 IP 地址吗?或者您可以对每个请求执行两次(仅用于实验)并查看第一个请求是否比第二个慢很多?

    Google 在 8.8.8.8 (其中包括)建立了一个 DNS 服务器。他们声称它比大多数其他 DNS 服务器更快。试试看!

    【讨论】:

    • 我们在不同的计算机和不同的国家解决这个问题:(
    • 在同一家公司?您的专用网络中的 DNS 可以相同吗?
    • 这不是您在哪里进行 DNS 查找的问题,而是由哪个 DNS 服务器处理目标。如果您访问廷巴克图的网站时网络速度较慢,等等,问题可能就在那里。如果不首先查看 DNS 查找的响应时间,我不会排除这种可能性。
    • 生产环境和测试环境不同。
    • 我放弃了——我帮不了你。
    【解决方案4】:

    '我们有一个类似的问题,这是由旧 Java 中的错误保持活动引起的。在连接之前添加它以查看是否有帮助,

    conn.setRequestProperty("Connection", "close");
    

    System.setProperty("http.keepAlive", "false");
    

    【讨论】:

    • 第二种方法怎么样?您确实需要发布 TCP 转储以确切了解问题所在。我不认为它是 DNS,因为它发生在 connect() 调用中。
    • 在我看来 keepAlive=false 有帮助。但为什么呢?
    • 无影无踪,我只是猜测。 HTTP请求有keepalive但没有内容长度,服务器不知道请求的结束在哪里,所以它一直在等待。 Apache 上的默认超时为 30 秒。当keepalive关闭时,OutputStream将被关闭,通知服务器请求完成。
    • wireshark/ethereal、tcpdump、窥探。这真的取决于你的操作系统。
    • 设置connection=close 标头应该可以工作。也许您没有正确设置请求属性。应该在connect() 之前完成。设置系统属性http.keepalive=false 的作用基本相同,但作为一种低级解决方法。当未手动指定时,URLConnection 使用它来设置 connection 标头。它在 webstart 中不起作用只是一个安全限制。但无论如何,setRequestProperty("Connection", "close") 必须工作。重试并验证您是否做对了。
    【解决方案5】:

    遇到同样的问题,发现是IPv6引起的。

    您使用以下代码从代码中禁用它:

    System.setProperty("java.net.preferIPv4Stack" , "true");
    

    您也可以通过命令行禁用它:g-Djava.net.preferIPv4Stack=true

    【讨论】:

      【解决方案6】:

      我也遇到了同样的问题,所以我从 Apache 改成 HTTPClient,下面举个例子:

      HttpClient httpClient = HttpClientBuilder.create().build();
      
      HttpPost request = new HttpPost("www.myurl-to-read");
      
      RequestConfig requestConfig = RequestConfig.custom()
                                    .setSocketTimeout(8000)
                                    .setConnectTimeout(10000)
                                    .setConnectionRequestTimeout(1000)
                                    .build();
      
      request.setConfig(requestConfig);
      
      request.setHeader("Content-type", "application/json");
      
      HttpResponse  response = httpClient.execute(request);
      
      HttpEntity entity = response.getEntity();
      String result = EntityUtils.toString(entity, "UTF-8");
      

      【讨论】:

        猜你喜欢
        • 2013-06-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-22
        • 1970-01-01
        相关资源
        最近更新 更多