`

HTTP持久连接

阅读更多

Persistent Connections

What is HTTP Persistent Connections?

HTTP persistent connections, also called HTTP keep-alive, or HTTP connection reuse, is the idea of using the same TCP connection to send and receive multiple HTTP requests/responses, as opposed to opening a new one for every single request/response pair. Using persistent connections is very important for improving HTTP performance.

There are several advantages of using persistent connections, including:

HTTP持久连接也称为HTTP keep-alive,或者叫HTTP连接重用,意思是指使用同一个TCP连接来处理多个HTTP requests/responses,与每个request/response pair open一个连接的方式相反。持久连接对于提高HTTP performance非常重要。

  • Network friendly. Less network traffic due to fewer setting up and tearing down of TCP connections.
  • Reduced latency on subsequent request. Due to avoidance of initial TCP handshake
  • Long lasting connections allowing TCP sufficient time to determine the congestion state of the network, thus to react appropriately.网络接口友好的:通过减少TCP连接的初始化和清理操作(握手),降低了网络传输
    为后续请求提高响应时间:通过避免TCP握手
    长连接允许TCP有足够的时间来测定网络连接状态,并做适当优化。

 

The advantages are even more obvious with HTTPS or HTTP over SSL/TLS. There, persistent connections may reduce the number of costly SSL/TLS handshake to establish security associations, in addition to the initial TCP connection set up.

这些优点在使用HTTPS或者基于SSL/TLS的HTTP协议时尤为明显。因为持久连接可以减少TCP连接的初始化设置及SSL/TLS握手的次数。

 

In HTTP/1.1, persistent connections are the default behavior of any connection. That is, unless otherwise indicated, the client SHOULD assume that the server will maintain a persistent connection, even after error responses from the server. However, the protocol provides means for a client and a server to signal the closing of a TCP connection.

HTTP/1.1规范中,默认使用持久连接。也就是说,在没有明确指定的情况下,客户端是(应该)假设服务端可以维持一个持久连接的,即使返回了错误的应答消息。然而,协议规定客户端与服务端均可以主动关闭这个持久的TCP连接。

 

What makes a connection reusable?

Since TCP by its nature is a stream based protocol, in order to reuse an existing connection, the HTTP protocol has to have a way to indicate the end of the previous response and the beginning of the next one. Thus, it is required that all messages on the connection MUST have a self-defined message length (i.e., one not defined by closure of the connection). Self demarcation is achieved by either setting the Content-Length header, or in the case of chunked transfer encoded entity body, each chunk starts with a size, and the response body ends with a special last chunk.

TCP协议本质上基于流的协议,为了重用已经打开的连接,HTTP协议必须能够识别前一个应答的结束和下一个请求的开始。因此呢,这就要求所有通过这个连接传递的消息必须有一个自定义的(message length)消息段(也就是,one not defined by closure of the connection)。Self demarcation is achieved by either setting the Content-Length header, or in the case of chunked transfer encoded entity body,each chunk starts with a size, and the response body ends with a special last chunk.(大概就是在应答和请求中添加标识)

 

What happens if there are proxy servers in between?

Since persistent connections applies to only one transport link, it is important that proxy servers correctly signal persistent/or-non-persistent connections separately with its clients and the origin servers (or to other proxy servers). From a HTTP client or server's perspective, as far as persistence connection is concerned, the presence or absence of proxy servers is transparent.

(代理应该可以正确的标识持久连接/非持久连接,代理对客户端和服务端均是透明的)

 

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.

What's new in Tiger?

When the application encounters a HTTP 400 or 500 response, it may ignore the IOException and then may issue another HTTP request. In this case, the underlying TCP connection won't be Kept-Alive because the response body is still there to be consumed, so the socket connection is not cleared, therefore not available for reuse. What the application needs to do is call HttpURLConnection.getErrorStream() after catching the IOException , read the response body, then close the stream. However, some existing applications are not doing this. As a result, they do not benefit from persistent connections. To address this problem, we have introduced a workaround.

The workaround involves buffering the response body if the response is >=400, up to a certain amount and within a time limit, thus freeing up the underlying socket connection for reuse. The rationale behind this is that when the server responds with a >=400 error (client error or server error. One example is "404: File Not Found" error), the server usually sends a small response body to explain whom to contact and what to do to recover.

Several new Sun implementation specific properties are introduced to help clean up the connections after error response from the server.

The major one is:

sun.net.http.errorstream.enableBuffering=<boolean>
default: false

With the above system property set to true (default is false), when the response code is >=400, the HTTP handler will try to buffer the response body. Thus freeing up the underlying socket connection for reuse. Thus, even if the application doesn't call getErrorStream(), read the response body, and then call close(), the underlying socket connection may still be kept-alive and reused.

The following two system properties provide further control to the error stream buffering behavior:

sun.net.http.errorstream.timeout=<int> in millisecond
default: 300 millisecond

sun.net.http.errorstream.bufferSize=<int> in bytes
default: 4096 bytes

What can you do to help with Keep-Alive?

Do not abandon a connection by ignoring the response body. Doing so may results in idle TCP connections. That needs to be garbage collected when they are no longer referenced.

If getInputStream() successfully returns, read the entire response body.

When calling getInputStream() from HttpURLConnection, if an IOException occurs, catch the exception and call getErrorStream() to get the response body (if there is any).

Reading the response body cleans up the connection even if you are not interested in the response content itself. But if the response body is long and you are not interested in the rest of it after seeing the beginning, you can close the InputStream. But you need to be aware that more data could be on its way. Thus the connection may not be cleared for reuse.

Here's a code example that complies to the above recommendation:

try {
	URL a = new URL(args[0]);
	URLConnection urlc = a.openConnection();
	is = conn.getInputStream();
	int ret = 0;
	while ((ret = is.read(buf)) > 0) {
	  processBuf(buf);
	}
	// close the inputstream
	is.close();
} catch (IOException e) {
	try {
		respCode = ((HttpURLConnection)conn).getResponseCode();
		es = ((HttpURLConnection)conn).getErrorStream();
		int ret = 0;
		// read the response body
		while ((ret = es.read(buf)) > 0) {
			processBuf(buf);
		}
		// close the errorstream
		es.close();
	} catch(IOException ex) {
		// deal with the exception
	}
}

If you know ahead of time that you won't be interested in the response body, you should issue a HEAD request instead of a GET request. For example when you are only interested in the meta info of the web resource or when testing for its validity, accessibility and recent modification. Here's a code snippet:

URL a = new URL(args[0]);
URLConnection urlc = a.openConnection();
HttpURLConnection httpc = (HttpURLConnection)urlc;
// only interested in the length of the resource
httpc.setRequestMethod("HEAD");
int len = httpc.getContentLength();

Future directions in the JDK?

  • More aggressive clean-up. An example is measured blocking read when application calls close before finish reading the response body
  • pipelining requests to further increase the network bandwidth utilization and reduce latency

 

 

分享到:
评论

相关推荐

    论文研究-一种TCP连接的延迟多次迁移技术.pdf

    现有的基于内容的Web交换技术不能很好地支持HTTP持久连接(P-HTTP)和流水线请求。提出了一种TCP连接的延迟多次迁移方法(DM-TCPHA),前端FE根据第一个请求将连接迁移到选中的BE,该连接上的后续请求报文由BE来调度...

    【ASP.NET编程知识】页面间隔半秒钟更新时间 Asp.net使用Comet开发http长连接示例分享.docx

    Comet是一种优化的HTTP持久连接技术,允许服务器向客户端推送数据,而不是等待客户端发送请求。这种方法相比于传统的AJAX轮询,能够更有效地节省资源,减少延迟,同时也比WebSocket更适合某些不支持WebSocket或对...

    TestWebServer_httppost_kepthsp_C++httpserver_c++mong_c++post_

    3. **Keep-Alive与HTTP持久连接**:"kepthsp"可能是"Keep-Alive"的缩写,指的是HTTP协议中的持久连接特性。HTTP/1.1默认开启持久连接,允许客户端和服务器在处理完一个请求后保持连接状态,而不是关闭连接,从而减少...

    计算机网络_自顶向下方法与Internet特色(第二章)课后习题答案中文版

    计算机网络是一个复杂的系统,涉及到网络体系结构、应用层协议、客户机/服务器模式、P2P 模式、网络安全、Web 缓存、FTP 和 SMTP 协议、POP3 协议、cookie 的应用和 HTTP 持久连接等方面。理解这些概念和协议对于...

    《计算机网络自顶向下》课后习题答案(第二章中文版).docx

    《计算机网络自顶向下》第二章中文版课后习题答案涵盖了计算机网络的多个方面,包括网络体系结构、客户机/服务器模式、网络应用协议、可靠的数据传输服务、握手协议、Cookie、HTTP 持久连接、Web 缓存、FTP 协议和...

    哈工大计算机网络作业2

    相比之下,HTTP持久连接避免了SYN和SYNACK交换的时间(约2秒),但在每个对象传输101秒的情况下,使用管道化的增益仅为2%。 6. **HTTP与安全**: - 提及HTTP不提供加密服务,意味着HTTP通信是明文的,不安全。为了...

    php开发客服系统(持久连接+轮询+反向ajax) - php严程序

    真正的实时聊天,使用持久连接+轮询+反向ajax实现 用户端(可直接给客户发送消息) 客服端(点击用户名.即可给该用户回复消息) 讲两种实现方式: 一:iframe + 服务器推技术comet(反向ajax,即服务器向浏览器推送数据) ...

    HTTP1.1规范中文版

    例如,HTTP持久连接(也称为keep-alive连接)允许在同一个TCP连接上发送和接收多个HTTP请求/响应,大大减少了连接和断开连接时的延迟,使得网页加载更快。 HTTP/1.1规范的修订版还引入了一些新特性,例如支持请求...

    计算机网络课后题答案——作业2 应用层.pdf

    这实际上是HTTP/1.1版本后引入的一种特性,称为"HTTP持久连接"(HTTP persistent connection),也被称为"Keep-Alive"。 非持续TCP连接的特点是"一次一个",这意味着对于每一个请求,都需要建立一个新的TCP连接,...

    http概念手册

    HTTP持久连接** HTTP 1.1引入了持久连接(Keep-Alive),允许在一个TCP连接上发送多个请求和响应,减少了建立和关闭连接的开销。 **7. HTTP版本** HTTP经历了1.0、1.1到现在的HTTP/2和HTTP/3。HTTP/2引入了多路...

    java commet+udp实现例子

    Comet是一种优化的HTTP持久连接技术,它允许服务器主动向客户端推送数据,而不是等待客户端发起请求。这种模式在实时应用如聊天室、股票报价、在线游戏等中非常有用,因为它消除了传统的HTTP短链接导致的延迟问题。...

    http/1.1协议2014年最新版

    这一点被称为持久连接(HTTP持久连接,也称为HTTP keep-alive)。此外,还有一种叫做管线化(pipelining)的技术,它允许客户端发送多个请求而无需等待每个请求的响应。 HTTP/1.1协议还包括了一系列的内容协商机制,...

    HTTP协议的运作方式

    4. **关闭连接**:在响应发送完毕后,服务器通常会关闭TCP连接,除非使用的是HTTP持久连接(HTTP/1.1默认开启),在这种情况下,连接保持打开状态,以便后续的请求和响应。 二、HTTP协议的细节探讨 1. **请求方法*...

    易语言HTTP访问对象演示源码-易语言

    HTTP/1.1引入了持久连接,允许复用TCP连接,减少了连接开销。而HTTP/2则进一步优化了性能,通过多路复用解决了1.1版的阻塞问题,同时使用二进制分帧和头部压缩,提高了传输效率。 通过分析和学习"易语言HTTP访问...

    http长连接

    HTTP长连接,也称为持久连接或持续连接,是一种让HTTP请求在完成后不立即断开连接的技术。这使得后续的请求可以在同一连接上发送,无需重新建立连接,从而大大提高了效率。HTTP长连接最初在HTTP 1.1版本中被标准化,...

    apach2配置文件

    - **定义**: KeepAlive指令用于控制是否启用HTTP持久连接。 - **示例**: `KeepAlive On` - **解释**: 设置为`On`表示启用持久连接,这样同一个客户端可以连续发送多个请求而无需重新建立连接。 **...

    18A答案1

    19. **HTTP持久连接**:允许重复使用同一个TCP连接进行多个HTTP请求,减少建立和关闭连接的开销,提高效率。而**非持久连接**每次请求都会创建新的连接。HTTP/1.1默认使用持久连接,并引入了流水线技术,允许同时...

    TCP中长连接短连接

    长连接,也称为持久连接,指的是客户端(Client)与服务器端(Server)在完成连接建立后,保持连接状态不立即断开,以便于进行多次的数据交互。TCP的三次握手建立连接后,双方可以在连接保持期间反复发送数据,减少...

    服务端推技术 - Server-side Push 多示例

    1. **Comet技术**:Comet是一种利用HTTP持久连接来实现双向通信的技术,它可以让服务器在连接保持打开的状态下,随时将数据推送给客户端。常见的Comet实现方式包括长轮询(Long Polling)和流(Streaming)。长轮询...

Global site tag (gtag.js) - Google Analytics