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. 学习资料 数据查询语言DQL

    数据查询语言DQL介绍及其应用: 查询是SQL语言的核心,SQL语言只提供唯一一个用于数据库查询的语句,即SELECT语句.用于表达SQL查询的SELECT语句是功能最强也是最复杂的SQL语句,它提供 ...

  2. LED点阵显示名字

    学习了一周的单片机,然后中途有事打断了两周,现在温习一下之前学的东西,用“普中科技单片机”上的LED点阵显示自己的名字. P1接J19(绿).P2接J20(红),P0接J12(数码管段选):5V电压: ...

  3. leetcode022. Generate Parentheses

    leetcode 022. Generate Parentheses Concise recursive C++ solution class Solution { public: vector< ...

  4. python md5

    import hashlib import os 简单的测试一个字符串的MD5值 src = 'teststring' print (hashlib.md5(src).hexdigest().uppe ...

  5. js设计模式-建造者模式

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. 用verilog模拟DDS产生正弦波信号

    前言: DDS:直接数字频率合成,正弦波0-2pi周期内,相位到幅度是一一对应的(这里我们使用放大后的整数幅度). 主要思路: 个人理解,FPGA不擅长直接做数字信号计算,那样太占用片上逻辑资源,所以 ...

  7. SQL笔记 [长期更新] (-2013.7)

    --IF EXISTS(SELECT * FROM dbo.SysObjects WHERE ID = object_id(N'[TABLEA]') ) DROP TABLE tableA--CREA ...

  8. SQL Server 之登录

    1:SQL Server 是Microsoft 公司推出的关系型数据库管理系统. 安装好后,开始登录. 2:几种登录方式: (1):服务器名称: ①: . :代表本地服务器 ②: local :代表本 ...

  9. 在oracle中通过链接服务器(dblink)访问sql server

    在oracle中通过链接服务器(dblink)访问sql server 2013-10-16 一.   工作环境: <1> Oracle数据库版本:Oracle 11g  运行环境 :IB ...

  10. project 2010 使用技巧

    快捷键 设置任务子任务 ALT+SHIFT+向右方向键 1.工作时间设置 新建一个日历后,可以在 “项目 >> 项目信息 >> 日历” 中进行选择