Persistent Connections Issue
"Persistent Connections" issue
- Comet is a World Wide Web application architecture in which a web server sends data to a client program (normally a web browser) asynchronously without any need for the client to explicitly request it. It allows creation of event-driven web applications, enabling real-time interaction which would otherwise require much more work. Though the term Comet was coined in 2006, the idea is several years older, and has been called various names, including server push, HTTP push, HTTP streaming, Pushlets, Reverse Ajax, and others. Many Ajax applications need to maintain a long-lived connection with the server so that the server can push data to the client whenever new information is available. The term used to describe the ability to push data to an Ajax client is "Comet".
To achieve Ajax Push today, applications today use various techniques (polling, long polling, streaming response: see ), all of which have significant shortcomings, and some (all?) of which can be characterized as ugly hacks.
This feature request calls on browsers to deliver built-in support for persistent connections in order to enable Ajax Push.
Why Is This Important?
There is a significant demand for Ajax Push in the marketplace. Several commercial companies serve this demand, and some open source Ajax toolkits provide Ajax Push functionality. However, the industry would benefit if browsers supported persistent connections natively using the same approaches.
Here are some notes extracted from a different feature request The_Two_HTTP_Connection_Limit_Issue.
- Comet (server push): HTTP connections are request/response based and are only initiated by the client. However, many applications require Comet (server push) style communications. These applications include web-based chatting, financial trading, real-time web alerting, system monitoring, etc. In general, Comet implementations use some form of "long lived connection" for delivering server push messages. This "long lived HTTP connection" is a normal HTTP connection but the server keeps it open. Whenever a message occurs, the server uses this connection to deliver the message to the client. In doing so, the server can initiate communications to the client without having to passively wait for the client to initiate a connection first. The problem is that this long lived connection consumes one of the two connections limit. If the user opens two browser windows of the same Comet application, both connections are consumed. When both connections are consumed, even normal HTTP requests (such as opening a URL, loading an image, loading CSS, etc) are blocked. It appears to the user that the application is locked up.
- Pipelining problems: With the growing adoption of pipelining in browsers, a significant issue is that if a response is long-lived, requests may be pipelined on the same connection as the Comet request, and the responses to these requests will be indefinitely queued behind the Comet long-lived response. Please see this blog for more information: http://cometdaily.com/2008/02/22/comet-and-http-pipelining/
This problem can also be seen in FF3: https://bugzilla.mozilla.org/show_bug.cgi?id=329977#c6 With the test case: http://persevere.sitepen.com:9080/test/pipeline-problem.html
- Duplex communication on HTTP: Comet essentially aims to provide full duplex communication with the server. I believe it is absolutely necessary that we aim for a future where duplex communication can happen on a single TCP connection. This is completely viable with HTTP, but it can't be done with current browsers, duplex communication requires two TCP connections (even though the TCP protocol is duplex). This can actually be achieved with sufficient control over pipelining. Pipelined requests can intentionally be sent behind a long-lived streaming response, and provide the mechanism for sending messages in both directions at any time.
- Broken interactive mode in IE: Comet can be significantly more efficient if messages can be streamed over a single HTTP response. This works fine in Firefox and Safari, but IE's XMLHttpRequest fails to provide the received stream of data as data is received by the browser (readyState=3, i.e. interactive mode).
- Broken network detection: Using a persistent connection can help with detecting if the remote web site has gone down or if the network has disappeared. Finding out if you are offline (and switching a website into offline mode) is a surprisingly tricky problem, and persistent connections that break are one way to do this, using heartbeats. This hasn't been done more up to now due to the hacks necessary to do this, bugs with not seeing if the network disappears when the comet-connection breaks, and the 2-connection limit on IE.
Various products today deliver server push by using various techniques (polling, long polling, streaming response: see ), all of which have significant shortcomings, and some (all?) of which can be characterized as ugly hacks.
HTML5 has a Connection interface, which is a base class for 3 different constructors, TCPConnection(), LocalBroadcastConnection(), and PeerToPeerConnection(). The TCPConnection() is the one that addresses this particular requirement:
SVG Tiny 1.2
SVG Tiny 1.2, which ships on various mobile phones, also has a Connection interface that allows for socket communications and addresses the key issue:
Comment: SVG?!? SVG is vector graphics, why in the world are they trying to do network communication!
New flag on XMLHttpRequest, doesn't count against connection limit
Here is an extensive detailed proposal of how to include a property to advice XHR requests to avoid connection limiting and pipelining issues: http://www.openajax.org/runtime/wiki/XHR_Connection_Length_Advice
Original (which I don't believe is as flexible as numeric advice to address future problems with long-lived XHR): Another possible solution is to somehow flag an XHR request that it is meant to serve as a long-lived connection, where this flag tells the browser that the XHR connection is supposed to be long-lived, and the browser does not count this connection against the HTTP connection limit (e.g., 2 or 6 connections) that it establishes for each domain.
Background material that request this feature
In this section, the contributors should express their opinions about this feature request, such as providing particular technical analysis or describing in prose why this feature is important (or not). It is recommended that each contributor create his own level-3 sub-section (e.g., === Jon Ferraiolo Comments ===).
It is OK for others to insert comments within other people's sections, but as a courtesy please make sure that it is clear which part of the section is original and which section are annotative comments. For example, perhaps annotative comments would be colorized (e.g., enclosed by <span style="color:red">JON: Here is what I think about what you are saying.</span>).
Kris Zyp's comments
I don't believe that TCPConnection is really all that helpful for Comet. Many users are behind proxies, and so Comet developers would still need to create HTTP paths (that properly use the proxies) for Comet. I think Comet must continue to use HTTP, for the massive interoperability that it affords. Having devs reimplementing HTTP on top of TCPConnection seems silly. TCPConnection seems like a dangerous path for security as well.
However, I believe that a central goal of persistent connections should be achieving duplex communication over HTTP on a single TCP connection. Persistent connections are almost inevitably an effort to achieve duplex communication. TCP is a designed to handle duplex over a single TCP connection. The fact that we need two TCP connections for duplex communication in the browser is a terrible waste of resources. It is possible to do duplex with HTTP using pipelining of requests and streaming responses using a single TCP connection. I believe my proposal XHR Connection Length Advice provides the necessary mechanisms for us to work towards that end.
Brad Neuberg's comments
I'm surprised this isn't in HTML 5. The TCPConnection class seems much too low level for this (though its useful for other socket-oriented things, like folks have been doing with Flash's socket features). Server-sent events I think have been marked as a 'mistake' by the HTML 5 folks. I think its best to modify the XHR interface to simply be able to open an XHR and keep it persistent if it was marked as such, with you receiving data on the onreadystatechange as data comes in. Why proliferate the number of interfaces developers have to learn; just use XHR. I think though that it should respect the HTTP connections limit, with a server able to bump this up using the META tag approach I proposed on the HTTP connection limit page.
Greg Wilkins comments
I agree that TCPConnection is too low level. HTTP is the protocol of the web and we should embrace it or replace it.
A partial solution is the ability to hint to the browser that a particular request may be long held by the server. This would allow the browser to avoid pipelining other requests behind that connection.
A full solution would allow some explicit control over pipelining, as it may be that it is advantageous to have several long-poll style requests pipelined, so that responding to one does not incur a network latency before another response can be sent.
I do not believe that streaming HTTP responses is a valid solution. Proxies are entitled to cache an entire response before sending a single byte down stream. Unless there is a HTTP/1.2 standard that insists that content chunks must be immediately forwarded, then streaming solutions will always be invalid against the RFC.
John Fallows' comments
TCPConnection in HTML5, recently renamed WebSocket, is undergoing some changes to leverage the HTTP-based infrastructure of the Web. The following summarizes the latest available status from ongoing discussions, and seems to directly address many of the issues highlighted with the original TCPConnection proposal.
WebSocket setup sends an HTTP OPTIONS request with an Upgrade header to switch protocols to use the WebSocket wire protocol. The server can then send either a 101 Switching Protocols HTTP response, or a 426 Upgrade Required HTTP response, depending on success or failure of the upgrade. After 101 Switching Protocols is received, the single connection becomes a full duplex TCP connection. Proxies are leveraged via an initial HTTP CONNECT request, in much the same way as HTTPS works today, but even for unencrypted HTTP connections.
The initial connection information for a WebSocket is now URL-based which, when combined with the initial HTTP OPTIONS request, allows for re-use of existing HTTP-based infrastructure to route incoming WebSocket requests to a target server. Cross-domain security is covered by HTTP authentication headers during the initial HTTP OPTIONS request. Encryption of WebSocket requests is specified by an appropriate URL scheme in the connection URL, such as HTTPS, performing an initial TLS handshake to establish the encryption parameters prior to sending the encrypted HTTP OPTIONS request.
Proxies cannot assume any knowledge of the HTTP connection after a 101 Switching Protocols response, so it would be illegal for them to buffer the bytes passing through in either direction.
IMHO, these latest advances in WebSocket represent a best of breed approach for Comet, and furthermore for full-duplex bidirectional communication from the browser. Using HTTP as a handshake mechanism for connection setup fully leverages the existing HTTP-based Web architecture, and then upgrading to a vanilla (or near-vanilla) TCP connection eliminates the undesirable overhead of sending subsequent TCP packets in HTTP envelopes.
Phase I Voting - Vote for Your Top 5 Features
NOTE: PHASE I VOTING IS NOW OPEN. (2008-04-01) We have now changed the voting procedure. Instead of putting votes on each separate wiki page, we are asking people to cast their Phase I Votes on the following wiki page:
Phase II Voting
More about this later.