Internet Engineering Task Force (IETF) S. Loreto Request for Comments: 6202 Ericsson Category: Informational P. Saint-Andre ISSN: 2070-1721 Cisco S. Salsano University of Rome "Tor Vergata" G. Wilkins Webtide April 2011 Known Issues and Best Practices for the Use of Long Polling and Streaming in Bidirectional HTTP
AbstractOn today's Internet, the Hypertext Transfer Protocol (HTTP) is often used (some would say abused) to enable asynchronous, "server- initiated" communication from a server to a client as well as communication from a client to a server. This document describes known issues and best practices related to such "bidirectional HTTP" applications, focusing on the two most common mechanisms: HTTP long polling and HTTP streaming. Status of This Memo This document is not an Internet Standards Track specification; it is published for informational purposes. This document is a product of the Internet Engineering Task Force (IETF). It represents the consensus of the IETF community. It has received public review and has been approved for publication by the Internet Engineering Steering Group (IESG). Not all documents approved by the IESG are a candidate for any level of Internet Standard; see Section 2 of RFC 5741. Information about the current status of this document, any errata, and how to provide feedback on it may be obtained at http://www.rfc-editor.org/info/rfc6202.
Copyright Notice Copyright (c) 2011 IETF Trust and the persons identified as the document authors. All rights reserved. This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License. 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3 2. HTTP Long Polling . . . . . . . . . . . . . . . . . . . . . . 4 2.1. Definition . . . . . . . . . . . . . . . . . . . . . . . . 4 2.2. HTTP Long Polling Issues . . . . . . . . . . . . . . . . . 5 3. HTTP Streaming . . . . . . . . . . . . . . . . . . . . . . . . 7 3.1. Definition . . . . . . . . . . . . . . . . . . . . . . . . 7 3.2. HTTP Streaming Issues . . . . . . . . . . . . . . . . . . 8 4. Overview of Technologies . . . . . . . . . . . . . . . . . . . 10 4.1. Bayeux . . . . . . . . . . . . . . . . . . . . . . . . . . 10 4.2. BOSH . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 4.3. Server-Sent Events . . . . . . . . . . . . . . . . . . . . 13 5. HTTP Best Practices . . . . . . . . . . . . . . . . . . . . . 13 5.1. Limits to the Maximum Number of Connections . . . . . . . 13 5.2. Pipelined Connections . . . . . . . . . . . . . . . . . . 14 5.3. Proxies . . . . . . . . . . . . . . . . . . . . . . . . . 14 5.4. HTTP Responses . . . . . . . . . . . . . . . . . . . . . . 15 5.5. Timeouts . . . . . . . . . . . . . . . . . . . . . . . . . 15 5.6. Impact on Intermediary Entities . . . . . . . . . . . . . 16 6. Security Considerations . . . . . . . . . . . . . . . . . . . 16 7. References . . . . . . . . . . . . . . . . . . . . . . . . . . 17 7.1. Normative References . . . . . . . . . . . . . . . . . . . 17 7.2. Informative References . . . . . . . . . . . . . . . . . . 17 8. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 18
RFC2616] is a request/response protocol. HTTP defines the following entities: clients, proxies, and servers. A client establishes connections to a server for the purpose of sending HTTP requests. A server accepts connections from clients in order to service HTTP requests by sending back responses. Proxies are intermediate entities that can be involved in the delivery of requests and responses from the client to the server and vice versa. In the standard HTTP model, a server cannot initiate a connection with a client nor send an unrequested HTTP response to a client; thus, the server cannot push asynchronous events to clients. Therefore, in order to receive asynchronous events as soon as possible, the client needs to poll the server periodically for new content. However, continual polling can consume significant bandwidth by forcing a request/response round trip when no data is available. It can also be inefficient because it reduces the responsiveness of the application since data is queued until the server receives the next poll request from the client. In order to improve this situation, several server-push programming mechanisms have been implemented in recent years. These mechanisms, which are often grouped under the common label "Comet" [COMET], enable a web server to send updates to clients without waiting for a poll request from the client. Such mechanisms can deliver updates to clients in a more timely manner while avoiding the latency experienced by client applications due to the frequent opening and closing of connections necessary to periodically poll for data. The two most common server-push mechanisms are HTTP long polling and HTTP streaming: HTTP Long Polling: The server attempts to "hold open" (not immediately reply to) each HTTP request, responding only when there are events to deliver. In this way, there is always a pending request to which the server can reply for the purpose of delivering events as they occur, thereby minimizing the latency in message delivery. HTTP Streaming: The server keeps a request open indefinitely; that is, it never terminates the request or closes the connection, even after it pushes data to the client. It is possible to define other technologies for bidirectional HTTP; however, such technologies typically require changes to HTTP itself (e.g., by defining new HTTP methods). This document focuses only on
bidirectional HTTP technologies that work within the current scope of HTTP as defined in [RFC2616] (HTTP 1.1) and [RFC1945] (HTTP 1.0). The authors acknowledge that both the HTTP long polling and HTTP streaming mechanisms stretch the original semantic of HTTP and that the HTTP protocol was not designed for bidirectional communication. This document neither encourages nor discourages the use of these mechanisms, and takes no position on whether they provide appropriate solutions to the problem of providing bidirectional communication between clients and servers. Instead, this document merely identifies technical issues with these mechanisms and suggests best practices for their deployment. The remainder of this document is organized as follows. Section 2 analyzes the HTTP long polling technique. Section 3 analyzes the HTTP streaming technique. Section 4 provides an overview of the specific technologies that use the server-push technique. Section 5 lists best practices for bidirectional HTTP using existing technologies.
The basic life cycle of an application using HTTP long polling is as follows: 1. The client makes an initial request and then waits for a response. 2. The server defers its response until an update is available or until a particular status or timeout has occurred. 3. When an update is available, the server sends a complete response to the client. 4. The client typically sends a new long poll request, either immediately upon receiving a response or after a pause to allow an acceptable latency period. The HTTP long polling mechanism can be applied to either persistent or non-persistent HTTP connections. The use of persistent HTTP connections will avoid the additional overhead of establishing a new TCP/IP connection [TCP] for every long poll request.
packet, next packet, negative ack, retransmit). When HTTP pipelining (see Section 5.2) is available, the latency due to the server waiting for a new request can be avoided. Connection Establishment: A common criticism of both short polling and long polling is that these mechanisms frequently open TCP/IP connections and then close them. However, both polling mechanisms work well with persistent HTTP connections that can be reused for many poll requests. Specifically, the short duration of the pause between a long poll response and the next long poll request avoids the closing of idle connections. Allocated Resources: Operating systems will allocate resources to TCP/IP connections and to HTTP requests outstanding on those connections. The HTTP long polling mechanism requires that for each client both a TCP/IP connection and an HTTP request are held open. Thus, it is important to consider the resources related to both of these when sizing an HTTP long polling application. Typically, the resources used per TCP/IP connection are minimal and can scale reasonably. Frequently, the resources allocated to HTTP requests can be significant, and scaling the total number of requests outstanding can be limited on some gateways, proxies, and servers. Graceful Degradation: A long polling client or server that is under load has a natural tendency to gracefully degrade in performance at a cost of message latency. If load causes either a client or server to run slowly, then events to be pushed to the client will queue (waiting either for the client to send a long poll request or for the server to free up CPU cycles that can be used to process a long poll request that is being held at the server). If multiple messages are queued for a client, they might be delivered in a batch within a single long poll response. This can significantly reduce the per-message overhead and thus ease the workload of the client or server for the given message load. Timeouts: Long poll requests need to remain pending or "hanging" until the server has something to send to the client. The timeout issues related to these pending requests are discussed in Section 5.5. Caching: Caching mechanisms implemented by intermediate entities can interfere with long poll requests. This issue is discussed in Section 5.6.
current request/response is complete. The client's inclusion of the 'Connection: close' header field in the request will also prevent pipelining. The main issue with EOF is that it is difficult to tell the difference between a connection terminated by a fault and one that is correctly terminated. An HTTP/1.0 server can use only EOF as a streaming mechanism. In contrast, both EOF and "chunked transfer" are available to an HTTP/1.1 server. The "chunked transfer" mechanism is the one typically used by HTTP/1.1 servers for streaming. This is accomplished by including the header "Transfer-Encoding: chunked" at the beginning of the response, which enables the server to send the following parts of the response in different "chunks" over the same connection. Each chunk starts with the hexadecimal expression of the length of its data, followed by CR/LF (the end of the response is indicated with a chunk of size 0). HTTP/1.1 200 OK Content-Type: text/plain Transfer-Encoding: chunked 25 This is the data in the first chunk 1C and this is the second one 0 Figure 1: Transfer-Encoding response To achieve the same result, an HTTP/1.0 server will omit the Content- Length header in the response. Thus, it will be able to send the subsequent parts of the response on the same connection (in this case, the different parts of the response are not explicitly separated by HTTP protocol, and the end of the response is achieved by closing the connection).
BOSH is able to work reliably both when network conditions force every HTTP request to be made over a different TCP connection and when it is possible to use HTTP/1.1 and then rely on two persistent TCP connections. If the connection manager has no data to send to the client for an agreed amount of time (also negotiated during the first request), then the connection manager will respond to the request it has been holding with no data, and that response immediately triggers a fresh client request. The connection manager does so to ensure that if a network connection is broken then both parties will realize that fact within a reasonable amount of time. Moreover, BOSH defines the negotiation of an "inactivity period" value that specifies the longest allowable inactivity period (in seconds). This enables the client to ensure that the periods with no requests pending are never too long. BOSH allows data to be pushed immediately when HTTP pipelining is available. However, if HTTP pipelining is not available and one of the endpoints has just pushed some data, BOSH will usually need to wait for a network round-trip time until the server is able to again push data to the client. BOSH uses standard HTTP POST request and response bodies to encode all information. BOSH normally uses HTTP pipelining over a persistent HTTP/1.1 connection. However, a client can deliver its POST requests in any way permitted by HTTP 1.0 or HTTP 1.1. (Although the use of HTTP POST with pipelining is discouraged in RFC 2616, BOSH employs various methods, such as request identifiers, to ensure that this usage does not lead to indeterminate results if the transport connection is terminated prematurely.) BOSH clients and connection managers are not allowed to use Chunked Transfer Coding, since intermediaries might buffer each partial HTTP request or response and only forward the full request or response once it is available. BOSH allows the usage of the Accept-Encoding and Content-Encoding headers in the request and in the response, respectively, and then compresses the response body accordingly. Each BOSH session can share the HTTP connection(s) it uses with other HTTP traffic, including other BOSH sessions and HTTP requests and responses completely unrelated to the BOSH protocol (e.g., Web page downloads).
long polling solution will work fine with this, as will most HTTP streaming solutions. The main downside is performance, since most proxies are not designed to hold many open connections. Reverse proxies can come to grief when they try to share connections to the servers between multiple clients. As an example, Apache with mod_jk shares a small set of connections (often 8 or 16) between all clients. If long polls are sent on those shared connections, then the proxy can be starved of connections, which means that other requests (either long poll or normal) can be held up. Thus, Comet mechanisms currently need to avoid any connection sharing -- either in the browser or in any intermediary -- because the HTTP assumption is that each request will complete as fast as possible. One of the main reasons why both HTTP long polling and HTTP streaming are perceived as having a negative impact on servers and proxies is that they use a synchronous programming model for handling requests, since the resources allocated to each request are held for the duration of the request. Asynchronous proxies and servers can handle long polls using slightly more resources than normal HTTP traffic. Unfortunately some synchronous proxies do exist (e.g., Apache mod_jk) and many HTTP application servers also have a blocking model for their request handling (e.g., the Java servlet 2.5 specification). RFC2616], the server responds to a request it has successfully received by sending a 200 OK answer, but only when a particular event, status, or timeout has occurred. The 200 OK body section contains the actual event, status, or timeout that occurred. This "best practice" is simply standard HTTP.
Several experiments have shown success with timeouts as high as 120 seconds, but generally 30 seconds is a safer value. Therefore, vendors of network equipment wishing to be compatible with the HTTP long polling mechanism are advised to implement a timeout substantially greater than 30 seconds (where "substantially" means several times more than the medium network transit time). CORS]. Another security concern is that the number of open connections that needs to be maintained by a server in HTTP long polling and HTTP streaming could more easily lead to denial-of-service (DoS) attacks [RFC4732].
[RFC1945] Berners-Lee, T., Fielding, R., and H. Nielsen, "Hypertext Transfer Protocol -- HTTP/1.0", RFC 1945, May 1996. [RFC2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H., Masinter, L., Leach, P., and T. Berners-Lee, "Hypertext Transfer Protocol -- HTTP/1.1", RFC 2616, June 1999. [RFC4732] Handley, M., Rescorla, E., and IAB, "Internet Denial-of-Service Considerations", RFC 4732, December 2006. [BAYEUX] Russell, A., Wilkins, G., Davis, D., and M. Nesbitt, "Bayeux Protocol -- Bayeux 1.0.0", 2007, <http://svn.cometd.com/trunk/bayeux/bayeux.html>. [BOSH] Paterson, I., Smith, D., and P. Saint-Andre, "Bidirectional-streams Over Synchronous HTTP (BOSH)", XSF XEP 0124, February 2007. [COMET] Russell, A., "Comet: Low Latency Data for the Browser", March 2006, <http://infrequently.org/ 2006/03/comet-low-latency-data-for-the-browser/ >. [COOKIE] Barth, A., "HTTP State Management Mechanism", Work in Progress, March 2011. [CORS] van Kesteren, A., "Cross-Origin Resource Sharing", W3C Working Draft WD-cors-20100727, latest version available at <http://www.w3.org/TR/cors/>, July 2010, <http://www.w3.org/TR/2010/WD-cors-20100727/>. [HTTPBIS] Fielding, R., Ed., Gettys, J., Mogul, J., Nielsen, H., Masinter, L., Leach, P., Berners-Lee, T., Lafon, Y., Ed., and J. Reschke, Ed., "HTTP/1.1, part 1: URIs, Connections, and Message Parsing", Work in Progress, March 2011. [JSONP] Wikipedia, "JSON with padding", <http://en.wikipedia.org/wiki/JSONP#JSONP>.