`

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

 

 

分享到:
评论

相关推荐

    关于Http持久连接和HttpClient连接池的深入理解

    众所周知,httpclient是java开发中非常常见的一种访问网络资源的方式了,下面这篇文章主要给大家介绍了关于Http持久连接和HttpClient连接池的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,...

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

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

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

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

    易语言建立HTTP连接请求

    建立HTTP连接请求系统结构:取端口,HTTP查询信息,Http创建请求,Internet关闭句柄,Internet建立连接,Http发送请求,Internet激活, ======窗口程序集1 || ||------__启动窗口_创建完毕 || ||------_按钮1_被单

    net-http-persistent:与Net的线程安全的持久连接

    净HTTP持久 家 博士 描述: 使用Net :: HTTP管理持久连接,包括用于连接到多个主机的线程池。 使用持久的HTTP连接可以大大提高HTTP的速度。 为每个请求创建一个新的HTTP连接涉及一个额外的TCP往返,并导致TCP...

    最近很火的分布式数据库 RethinkDB.zip

    能够通过WebSockets和http持久连接来支持这一功能,但数据库系统要迎合实时需求仍然是一个大的工程难题。而RethinkDB作为第一个开 源、可扩展的数据库,就是特别为实时推送数据到应用而设计的。哪些人在用 RethinkDB...

    http_connection_monitor:监控您的出站 HTTP 请求,了解通过持久连接发出的请求数

    监控您的出站 HTTP 请求,了解通过持久连接发出的请求数。 这将帮助您发现 HTTP 使用中的低效率。 特点 计算每个目的地和汇总统计数据 允许离线处理 pcap 转储文件,以便于在生产中使用 打开抓包设备后可以删除...

    ASP.NET用SignalR建立浏览器和服务器的持久连接详解

    浏览器访问网页通过的是 HTTP 协议,浏览器发送一个请求,服务器返回一个结果。服务器是被动接收请求,如果想反过来,服务器主动发送信息给浏览器咋办呢? 有很多解决方法,比如轮循(浏览器定时去向服务器询问是否...

    BS穿透内网长连接例子带测试实例.net

    BS穿透内网长连接例子带测试实例,vs2015项目LongPoll,http默认保持长连接(HTTP persistent connection ,也有翻译为持久连接),数据传输完成了保持TCP连接不断开(不发RST包、不四次握手),等待在同域名下继续用...

    Python 通过监听端口实现唯一脚本运行方式

    我就废话不多说了,大家还是直接看代码吧 try: s = socket.socket() s.bind(('127.0.0.1', port)) ...它作为web服务器,具有较出色的抗负载能力,它适用于用户量大,高并发,或者大量的HTTP持久连接的情况。

    HttpClient入门基础教程高清晰PDF.pdf

    持久连接 HTTP 连接路由 路由计算 安全 HTTP 连接 HTTP 路由参数 套接字工厂 安全套接字分层 SSL/TLS 的定制 主机名验证 协议模式 HttpClient 代理配置 HTTP 连接管理器 连接操作...

    nginx反向代理时如何保持长连接

    HTTP1.1之后,HTTP协议支持持久连接,也就是长连接,优点在于在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟。 如果我们使用了nginx去作为反向代理或者负载均衡,从客户端过来的长...

    HTTP完全分析-KeepAlive模式

    我们知道HTTP协议采用“请求-应答...当使用Keep-Alive模式(又称持久连接、连接重用)时,Keep-Alive功能使客户端到服务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive功能避免了建立或者重新建立连接。

    foolsock:用于Socket持久连接PHP RPC

    业务层与后端的服务之间的通信协议中,http并不是一种高效的rpc协议。事实上php中有众多的扩展可以为我们提供很好的范例,如:mysql、memcached等等都是最常见不过的"服务"了,我们完全可以采用它们的客户端处理方式...

    garmin-api:用Java编写的Garmin Rest API的通用连接器。 它允许您将HTTP会话持久化到文件

    允许您将Http Session持久保存到文件中,从而可以解决Garmin API登录数量限制 通用JSON响应-您可以创建自己的模型 用法 基本用法: // Login for GarminSession LoginConnector loginConnector = new ...

    PHP数据库长连接mysql_pconnect的细节

    PHP的MySQL持久化连接,美好的目标,却拥有糟糕的口碑,往往令人敬而远之。这到底是为啥么。近距离观察后发现,这家伙也不容易啊,要看Apache的脸色,还得听MySQL指挥。  对于作为Apache模块运行的PHP来说,要实现...

    requests-2.22.0.tar.gz

    最新版requests模块。 requests是使用Apache2 licensed 许可证的HTTP库。 用python编写。 比urllib2模块更简洁。...Request支持HTTP连接保持和连接池,支持使用cookie保持会话...requests会自动实现持久连接keep-alive

    Xserver:C 语言实现的一个 web server,使用 JSON 格式的配置文件,支持静态请求和 PHP 文件,以及GET POST方法

    程式设计模型 I / O复用(epoll ET) ...http持久连接 投放静态(.html) 支持PHP(FastCGI) 计时器(MinHeap) 获取/发布 一些HTTP / 1.1功能 去做 内存池 保持活动(超时) 网络平台 strace追踪系统调用

    guzzle-master完整的HTTP客户端的PHP类.zip

    使用这个框架内,我们可以发送并行 持久连接。并且能够通过插件实现缓存,OAuth, AWS集成All the power of cURL with a simple interface. 持久连接和并行请求 Streams request and response bodies...

Global site tag (gtag.js) - Google Analytics