HttpURLConnection的变态事: Keep-Alive

JDK自带的HttpURLConnection默认启动Keep-Alive, 使用后的HttpURLConnection会放入池里重用. 相关描述:

What does the current JDK do for Keep-Alive?

The JDK supports both HTTP/1.1 and HTTP/1.0 persistent connections.

When the application finishes reading the response body or when the application calls close() on the InputStream returned by URLConnection.getInputStream(), the JDK's HTTP protocol handler will try to clean up the connection and if successful, put the connection into a connection cache for reuse by future HTTP requests.

The support for HTTP keep-Alive is done transparently. However, it can be controlled by system properties http.keepAlive, and http.maxConnections, as well as by HTTP/1.1 specified request and response headers.

The system properties that control the behavior of Keep-Alive are:

http.keepAlive=<boolean>
default: true

Indicates if keep alive (persistent) connections should be supported.

http.maxConnections=<int>
default: 5

Indicates the maximum number of connections per destination to be kept alive at any given time

HTTP header that influences connection persistence is:

Connection: close

If the "Connection" header is specified with the value "close" in either the request or the response header fields, it indicates that the connection should not be considered 'persistent' after the current request/response is complete.

The current implementation doesn't buffer the response body. Which means that the application has to finish reading the response body or call close() to abandon the rest of the response body, in order for that connection to be reused. Furthermore, current implementation will not try block-reading when cleaning up the connection, meaning if the whole response body is not available, the connection will not be reused.

如果服务端不支持Keep-Alive, 这种默认行为就会带来很多蛋疼的事, 举个例子:

mogilefs服务端默认没有启用Keep-Alive. 使用HttpURLConnection上传多个文件时, 由于Keep-Alive这种重用特性,导致for循环中第一个文件后的其实PUT请求卡死! 直到Socket Request Timeout! 这种行为实在很变态!

解决办法在上面描述已经提及, 经测试, 完成可行:
(1)System.setProperty("http.keepAlive", String.valueOf(false));
(2)conn.setRequestProperty("Connection", "close");
根据个人兴趣选择其一即可.

以下是mogilefs上传多个文件的实现(其实就是HttpURLConnection的PUT请求):

public static String upload(String uri, int size, InputStream content) throws DfsClientException, MalformedURLException, IOException {

HttpURLConnection conn = null;
  try {
   conn = (HttpURLConnection) new URL(uri).openConnection();
   System.out.println(conn.hashCode());
   conn.setFixedLengthStreamingMode(size);

conn.setUseCaches(false);
   conn.setDoInput(true);
   conn.setDoOutput(true);
   conn.setConnectTimeout(1000);
   conn.setReadTimeout(2000);
   conn.setRequestMethod("PUT");
   //System.setProperty("http.keepAlive", String.valueOf(false));
   conn.setRequestProperty("Connection", "close");

conn.connect();

System.out.println(conn.usingProxy());
   OutputStream out = conn.getOutputStream();
   for (int bt = 0; (bt = content.read()) != -1;) {
    out.write(bt);
   }
   out.close();

int code = conn.getResponseCode();
   StringBuilder sb = new StringBuilder();
   InputStream in = conn.getErrorStream();
   if (in == null) {
    in = conn.getInputStream();
   }
   if (in != null) {
    BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
    for (String line = null; (line = reader.readLine()) != null;) {
     sb.append(line);
    }
    reader.close();
   }

System.out.format("RESP[%d] %s", code, sb);
   System.out.println(uri);
  } finally {
   if (conn != null) {
    conn.disconnect();
   }
  }

return uri.replace("/upload", "/download");
}

Java之HttpURLConnection的变态事: Keep-Alive的更多相关文章

  1. Java 利用HttpURLConnection发送http请求

    写了一个简单的 Http 请求的Class,实现了 get, post ,postfile package com.asus.uts.util; import org.json.JSONExcepti ...

  2. Java你可能不知道的事(3)HashMap

    概述 HashMap对于做Java的小伙伴来说太熟悉了.估计你们每天都在使用它.它为什么叫做HashMap?它的内部是怎么实现的呢?为什么我们使用的时候很多情况都是用String作为它的key呢?带着 ...

  3. java你可能不知道的事(2)--堆和栈

    在java语言的学习和使用当中你可能已经了解或者知道堆和栈,但是你可能没有完全的理解它们.今天我们就一起来学习堆.栈的特点以及它们的区别.认识了这个之后,你可能对java有更深的理解. Java堆内存 ...

  4. Java使用HttpURLConnection上传文件

    从普通Web页面上传文件非常easy.仅仅须要在form标签叫上enctype="multipart/form-data"就可以,剩余工作便都交给浏览器去完毕数据收集并发送Http ...

  5. java 通过HttpURLConnection与servlet通信

    研究了一天才搞清楚,其实挺简单的,在这里记录下,以便以后参考. 一.创建一个servlet项目 主要包括(WEB-INF)里面有classes文件夹.lib文件夹.web.xml文件. 将写好的ser ...

  6. Java Socket/HttpURLConnection读取HTTP网页

    以读取百度的http网页为例.如果知道了IP地址和端口,然后新建一个Socket,就直接去读百度的首页,根本没反应,原因是www.baidu.com是以http协议传输的,而现在要以Socket原始的 ...

  7. java 利用HttpURLConnection方式获取restful格式的服务数据

    /** * @Author: * @Description:利用HttpURLConnection方式获取restful格式的服务数据 * @Date: */ private static List& ...

  8. java你可能不知道的事(2)--堆和栈<转>

    在java语言的学习和使用当中你可能已经了解或者知道堆和栈,但是你可能没有完全的理解它们.今天我们就一起来学习堆.栈的特点以及它们的区别.认识了这个之后,你可能对java有更深的理解. Java堆内存 ...

  9. Android(或者Java)通过HttpUrlConnection向SpringMVC请求数据(数据绑定)

    问题描写叙述 当我们使用SpringMVC作为服务端的框架时,有时不仅仅要应对web前端(jsp.javascript.Jquery等)的訪问请求,有时还可能须要响应Android和JavaSE(桌面 ...

随机推荐

  1. 查看Eclipse版本号的方法

    查看Eclipse版本号的方法如下所示: 1:假设Eclipse已打开Eclipse的菜单栏: Help-->About Eclipse弹出框中会显示一排logo,点击eclipse的那个log ...

  2. 学习练习 java 输入输出流练习2

     编写IoDemo.java的Java应用程序,程序完成的功能是:首先读取text.txt文件内容,再通过键盘输入文件的名称为iodemo.txt,把text.txt的内容存入iodemo.txt p ...

  3. [转]回答--python django学的很迷茫怎么办?

    作者:王一链接:http://www.zhihu.com/question/26235428/answer/36568428来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处 ...

  4. java jdbc 封装。。

    JDBC工具类...package it.cast.jdbcutils; import java.io.InputStream; import java.sql.Connection; import ...

  5. meta基础知识

    H5页面窗口自动调整到设备宽度,并禁止用户缩放页面 <meta name="viewport" content="width=device-width,initia ...

  6. C# 反射操作方法

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.R ...

  7. iOS 平台开发OpenGL ES程序注意事项

    本人最近从Android平台的OpenGL ES开发转到iOS平台的OpenGL ES开发,由于平台不同,所以开发中会有一些区别,再次列出需要注意的几点. 1.首先需要了解iOS主要开发框架,再次仅介 ...

  8. 阿里 Java面试 知识点

    摘自: http://blog.csdn.net/wtyvhreal/article/details/45291835 =================================== 基础知识 ...

  9. 比较合并工具vimdiff的主要用法归纳

    参考:https://www.ibm.com/developerworks/cn/linux/l-vimdiff/ vimdiff主要用法归纳如下:   1.打开文件 vimdiff file1 fi ...

  10. VMware vSphere Client的简单使用教程

    1.首先登陆进去ESXI管理   实验VMware VS6.0版本 2新建虚拟机 确认信息 点击完成 2.开启虚拟机 右键打开控制台 加载光驱 选择虚拟机 Ctrl+Alt+delete重启 安装 来 ...