Comet (programming): Difference between revisions
Undid revision 221802329 erm… that edit summary had nothing to do with the edit. anyway, these changes of yours I am re-reverting were unjustified stylistic regressions |
Canderson7 (talk | contribs) A pretty hefty reorganization. See the forthcoming summary on the talk page. |
||
Line 1: | Line 1: | ||
{{Articleissues|article=yes|cleanup=June |
{{Articleissues|article=yes |
||
| cleanup=June 2008 |
|||
| OR = June 2008 |
| OR = June 2008 |
||
| peacock = June 2008 |
| peacock = June 2008 |
||
Line 10: | Line 11: | ||
The Comet approach differs from the [[World Wide Web#How the Web works|original model of the web]], in which a browser receives a complete web page in response to each request, and also from the [[Ajax (programming)|Ajax model]], in which a browser requests chunks of data in order to update the current page. The effect is similar to that of applications which use traditional Ajax with [[polling (computer science)|polling]] to detect new information on the server, but Comet improves [[throughput]] and reduces [[lag|latency]] and [[Load (computing)|server load]]. Consequently, Comet enables the creation of [[event-driven programming|event-driven]] web applications and real-time interaction to an extent that would otherwise be untenable. |
The Comet approach differs from the [[World Wide Web#How the Web works|original model of the web]], in which a browser receives a complete web page in response to each request, and also from the [[Ajax (programming)|Ajax model]], in which a browser requests chunks of data in order to update the current page. The effect is similar to that of applications which use traditional Ajax with [[polling (computer science)|polling]] to detect new information on the server, but Comet improves [[throughput]] and reduces [[lag|latency]] and [[Load (computing)|server load]]. Consequently, Comet enables the creation of [[event-driven programming|event-driven]] web applications and real-time interaction to an extent that would otherwise be untenable. |
||
== |
== Traditional architectures == |
||
[[Web application]]s have historically been less flexible and capable than [[application software|desktop applications]] counterparts, due to the restrictions placed on their access to local and network resources, and the limitations of in-browser program environments. As web browsers have evolved, many of these limitations have been addressed, bringing [[rich Internet application]]s closer to desktop-application–like functionality. |
|||
One such limitation is that each chunk of information sent by a web server to a browser must be explicitly requested. Comet removes this limitation, allowing applications to respond in real time to events external to the browser, such as updates to a real-time data source, or messages sent by another user. Comet is best understood in comparison with web application architectures which suffer this limitation. |
|||
⚫ | |||
<!-- TODO: Image of traditional model of the web |
<!-- TODO: Image of traditional model of the web |
||
--> |
--> |
||
[[Web application]]s have historically been less flexible and capable than [[application software|desktop applications]] counterparts, because of the many constraints of the online environment. One such traditional limitation, the limitation that Comet seeks to address, is the inability of a [[web server]] to choose when to send updated information to a [[web browser]].{{ref label|browser|a|}} This limited interaction can engender an unwieldy series of interactions and precludes the use of real-time applications. It is the hallmark of the [[World_Wide_Web#How_the_Web_works|early page-by-page web model]] and is only partly addressed by the successive techniques of [[Ajax (programming)|Ajax]] and Ajax with [[polling (computer science)|polling]]. |
|||
⚫ | |||
⚫ | |||
⚫ | Traditionally, each chunk of information sent by a web server to a browser must be explicitly requested. Each time the user opens a [[web page]], the browser initiates an [[Hypertext Transfer Protocol|HTTP]] connection to the [[web server]], which returns the HTML code for the page and closes the connection. The browser then makes another HTTP request for each resource used by the page—e.g. an image or [[Cascading Style Sheets|stylesheet]]—and the server responds to each in turn. |
||
<!-- TODO: Wikipedia screenshot |
<!-- TODO: Wikipedia screenshot |
||
--> |
--> |
||
[[Wikipedia]], for example, is a complex application built using this page-by-page approach. Users interact with the [[website]] by clicking hyperlinks to navigate from page to page, and edit or add new pages by filling out [[form (web)|web form]]s, which also open new pages when submitted. On the server side, a complete HTML page is dynamically generated in response to each request. Users continually update wiki pages, but those changes are not reflected in Wikipedia’s interface until each page is reloaded. |
[[Wikipedia]], for example, is a complex application built using this page-by-page approach. Users interact with the [[website]] by clicking hyperlinks to navigate from page to page, and edit or add new pages by filling out [[form (web)|web form]]s, which also open new pages when submitted. On the server side, a complete HTML page is dynamically generated in response to each request. Users continually update wiki pages, but those changes are not reflected in Wikipedia’s interface until each page is reloaded. |
||
Though this model is simple and robust, it is also limiting; each page is updated only when the user explicitly refreshes (re-requests) it. Transferring entire pages, along with their associated resources, can take several seconds or longer. This encourages web applications with relatively few requests for new data, limits user interaction to filling out forms or pressing buttons or [[hyperlink]]s, and precludes real-time applications. |
|||
=== Ajax === |
=== Ajax === |
||
Line 30: | Line 27: | ||
<!-- TODO: Image of Ajax model |
<!-- TODO: Image of Ajax model |
||
--> |
--> |
||
To overcome these limitations of the page-by-page model, many web applications turn to [[Ajax (programming)|Ajax]] ([[Asynchronous I/O|asynchronous]] [[JavaScript]] and [[XML]]). |
To overcome these limitations of the page-by-page model, many web applications turn to ''[[Ajax (programming)|Ajax]]'' ([[Asynchronous I/O|asynchronous]] [[JavaScript]] and [[XML]]). The term ''Ajax'', like ''Comet'', refers to a user interaction model, “a way of thinking about the architecture of web applications”, rather than any specific technique (in the words of [[Jesse James Garrett]], the term’s originator). Concretely, “an Ajax application eliminates the start–stop–start–stop nature of interaction on the Web by introducing an intermediary—an Ajax engine—between the user and the server.”<ref>Jesse James Garrett ([[18 February]] [[2005]]). “[http://www.adaptivepath.com/ideas/essays/archives/000385.php Ajax: A New Approach to Web Applications]”. ''Adaptive Path''. Retrieved [[29 November]] [[2007]].</ref> In the Ajax model, servers respond to each request in sequence, just as before, but the browser uses JavaScript to modify the current page rather than opening a new page. This limits the server’s response to only the relevant information (usually in XML or [[JSON]] format), dramatically increasing application responsiveness by avoiding redundant data transfer and eliminating whole-page re-rendering. Furthermore, since Ajax requests are handled asynchronously in the background, the user can continue to interact with the page as data is retrieved. A principle example of this technology is the [[Google Maps]] web application. <ref>Paul Graham (November 2005). “[http://www.paulgraham.com/web20.html Web 2.0]”. ''paulgraham.com''. Retrieved [[29 November]] [[2007]].</ref> In Google Maps, new tiles of map imagery are loaded as the user clicks and drags the map, and the user can continue to pan and zoom the map even before all tiles in range have loaded. |
||
⚫ | Ajax does not fully address the limitations of the traditional page-by-page web model, however, because the server still responds to each request by the browser as a single event, closing each connection as a response is served. Any changing information is only updated in response to explicit user actions. This problem becomes a major hurdle when designing applications which should update in real time, in response to some [[Event-driven programming|event]] on the server, such as another user sending it information. |
||
<!-- TODO: Google Maps screenshot |
|||
--> |
|||
{{Rquote|right|Traditionally, a Web site is about flipping pages but we took a different approach with Maps which is one page of Javascript.|Lars Rasmussen<ref>Rodney Gedda ([[14 October]] [[2005]]). “[http://www.computerworld.com.au/index.php/id;1401986683;fp;16;fpid;0 Desktop apps coming to the Web: Google]”. ''Computerworld''. Retrieved [[29 November]] [[2007]].</ref>}} |
|||
Ajax provides much richer user interaction than the traditional web. For instance, in [[Google Maps]]—perhaps the canonical Ajax application<ref>Paul Graham (November 2005). “[http://www.paulgraham.com/web20.html Web 2.0]”. ''paulgraham.com''. Retrieved [[29 November]] [[2007]].</ref>—new tiles of map imagery are loaded as the user clicks and drags the map, and the user can continue to pan and zoom the map even before all tiles in range have loaded. |
|||
⚫ | |||
=== Ajax with polling === |
=== Ajax with polling === |
||
<!-- TODO: Image of Ajax with polling |
<!-- TODO: Image of Ajax with polling |
||
--> |
--> |
||
One solution is for the browser to regularly [[polling (computer science)|poll]] the server, asking it if a new event has occurred (e.g. each five seconds asking the server “Any new events?”). This introduces an unhappy trade-off between latency and server load; the average event latency is half the poll interval (plus network latency and any time spent processing data), so increasing responsiveness proportionally increases the number of requests received by the server. At high polling frequencies, this wastes server resources and bandwidth processing many negative responses (“No new events, try again later”). |
One solution is for the browser to regularly [[polling (computer science)|poll]] the server, asking it if a new event has occurred (e.g. each five seconds asking the server “Any new events?”). This introduces an unhappy trade-off between latency and server load; the average event latency is half the poll interval (plus network latency and any time spent processing data), so increasing responsiveness proportionally increases the number of requests received by the server. At high polling frequencies, this wastes server resources and bandwidth processing many negative responses (“No new events, try again later”). Although applications with predictable information updates, or those which tolerate relatively infrequent updates, can use polling without excessive waste, the technology is nonetheless too unwieldy for most implementations. |
||
== Implementation of Comet == |
|||
<!-- TODO: Image of Comet, showing both streaming and long polling |
<!-- TODO: Image of Comet, showing both streaming and long polling |
||
--> |
--> |
||
⚫ | {{Rquote|right|This analysis shows that for the worst case, when the message rate is high, load and latency for Comet long-polling are identical to traditional polling, and for most cases the load and latency are significantly better than traditional polling.|Greg Wilkins<ref name="wilkins-comparison"/>}} |
||
Instead of repeatedly polling for new events, Comet applications rely on a persistent HTTP connection between server and client, using one of two strategies: |
|||
''Comet'' is an umbrella term for technologies that attempt to eliminate both the limitations of the page-by-page model and the cumbersome nature of traditional polling. Instead, Comet applications can accomplish something approaching real-time interaction by relying on a persistent HTTP connection to provide the browser with updates as designated by the server. Although, holding one connection open for Comet can negatively affect the performance of the client{{ref label|connections|b|}} and also presents scalability issues for the server (see [[#Scalability]]), this has not proved to be a significant barrier to adoption. |
|||
⚫ | |||
⚫ | |||
; Long polling |
|||
⚫ | |||
⚫ | Because until recently, browsers were not designed with Comet in mind, web application developers mostly use several unintended side-effects of browser-native objects to build Comet “[[transport layer|transports]]” (methods of sending Comet events), each with different benefits and drawbacks. Each of these requires specialized code on both the server, which must send specially-formed responses, and in the browser-side JavaScript.<ref name="comet-future-1">Jacob Rus ([[11 December]] [[2007]]). “[http://cometdaily.com/2007/12/11/the-future-of-comet-part-1-comet-today/ The Future of Comet: Part 1, Comet Today]”. ''Comet Daily''. Retrieved [[14 December]] [[2007]].</ref><ref name="meteor-transports">Andrew Betts (2007). “[http://meteorserver.org/browser-techniques/ Browser Techniques]”. ''Meteor website''. Retrieved [[29 November]] [[2007]].</ref> |
||
Using either of these approaches, the server is able to send new information to the browser with low latency, enabling the Comet user-interaction model. Using Comet, applications such as real-time [[chat room]]s, multiplayer games, and live-updating [[information graphics|infographics]] become feasible web applications. |
|||
⚫ | It is important to note that the use of such browser-native technologies is inherent in the term Comet. An alternative approach with the same goal is the use of plugins, such as [[Java applet]]s or the proprietary [[Adobe Flash]].{{ref label|blazeds|c|}} These have the advantage of working identically across all browsers with the appropriate plugin installed, need not use HTTP connections, and face none of the security restrictions placed on browser-native transports. These strengths, however, are also the main drawbacks of proprietary plugins: not all clients have the plugins installed—for instance, the Apple [[iPhone]] includes neither—and the use of protocols other than HTTP, and ports other than port 80, can cause them to be blocked by firewalls. |
||
⚫ | Unlike with polling, long polling sends an event [[Payload (software)|payload]] along with each connection. While in the worst case—frequently occurring events with small payloads—long polling incurs significant [[computational overhead]], Greg Wilkins found that in most cases, long polling outperforms polling.<ref name="wilkins-comparison">Greg Wilkins ([[6 November]] [[2007]]). “[http://cometdaily.com/2007/11/06/comet-is-always-better-than-polling/ Comet is Always Better Than Polling]”. ''Comet Daily''. Retrieved [[29 November]] [[2007]].</ref> Streaming has better performance still, as it eliminates much of the per-message overhead. |
||
⚫ | Comet, though, avoids many of these risks, the drawback being that a given Comet transport is often an ''ad hoc'' approach that works for a limited class of compatible browsers. The specific transport or transports best for any given use depends on which browsers are targeted, the desired performance of the solution, need for cross-[[domain name|domain]] use, tolerance for user interface side-effects, and the stringency of [[proxy server]]s and [[firewall (networking)|firewall]]s between the client and server. |
||
== Browser compatibility == |
|||
⚫ | Because until recently, browsers were not designed with Comet in mind, web application developers mostly use several unintended side-effects of browser-native objects to build Comet “[[transport layer|transports]]” (methods of sending Comet events), each with different benefits and drawbacks. Each of these requires specialized code on both the server, which must send specially-formed responses, and in the browser-side JavaScript.<ref name="comet-future-1">Jacob Rus ([[11 December]] [[2007]]). “[http://cometdaily.com/2007/12/11/the-future-of-comet-part-1-comet-today/ The Future of Comet: Part 1, Comet Today]”. ''Comet Daily''. Retrieved [[14 December]] [[2007]].</ref><ref name="meteor-transports">Andrew Betts (2007). “[http://meteorserver.org/browser-techniques/ Browser Techniques]”. ''Meteor website''. Retrieved [[29 November]] [[2007]].</ref> |
||
Specific methods of implementing of Comet fall into two major categories: streaming and long polling. |
|||
⚫ | |||
⚫ | The specific transport or transports best for any given use depends on which browsers are targeted, the desired performance of the solution, need for cross-[[domain name|domain]] use, tolerance for user interface side-effects, and the stringency of [[proxy server]]s and [[firewall (networking)|firewall]]s between the client and server. |
||
⚫ | In an application using ''streaming Comet'', the browser opens a single persistent connection to the server for all Comet events, which is handled incrementally on the browser side. Each time the server sends a new event, the browser interprets it, but neither side closes the connection. Specific technologies for accomplishing streaming Comet include the following. |
||
=== “Forever frame” IFrame === |
==== “Forever frame” IFrame ==== |
||
The earliest Comet transport (in use as early as 2000, see [[#History|History]] section below) uses an invisible [[IFrame]] HTML element (an ''inline frame'', which allows a website to embed one HTML document inside another). This invisible IFrame is declared by the server to be infinitely long—hence “forever frame”—and as events occur, is gradually filled with <code>script</code> tags, containing JavaScript to be executed in the browser. Because browsers render HTML pages incrementally, each <code>script</code> tag is executed as it is received.<ref name="comet-future-1"/> |
The earliest Comet transport (in use as early as 2000, see [[#History|History]] section below) uses an invisible [[IFrame]] HTML element (an ''inline frame'', which allows a website to embed one HTML document inside another). This invisible IFrame is declared by the server to be infinitely long—hence “forever frame”—and as events occur, is gradually filled with <code>script</code> tags, containing JavaScript to be executed in the browser. Because browsers render HTML pages incrementally, each <code>script</code> tag is executed as it is received.<ref name="comet-future-1"/> |
||
The main benefit of the IFrame method is that it works in every common browser. Two downsides of this transport are first that it requires a kilobyte of data to be sent down the connection before the Safari browser (running on Mac OS X 10.4; this is fixed in the latest version of OS X) will begin incrementally rendering the IFrame or 256 bytes in Internet Explorer,<ref name="maciej">Maciej Stachowiak ([[26 June]] [[2007]]). “[http://lists.macosforge.org/pipermail/webkit-dev/2007-June/002041.html Re: XMLHttpRequest and readyState==3]”. ''Webkit-dev'' mailing list. Retrieved [[29 November]] [[2007]].</ref><!-- TODO: still need ref for IE needing padding |
The main benefit of the IFrame method is that it works in every common browser. Two downsides of this transport are first that it requires a kilobyte of data to be sent down the connection before the Safari browser (running on Mac OS X 10.4; this is fixed in the latest version of OS X) will begin incrementally rendering the IFrame or 256 bytes in Internet Explorer,<ref name="maciej">Maciej Stachowiak ([[26 June]] [[2007]]). “[http://lists.macosforge.org/pipermail/webkit-dev/2007-June/002041.html Re: XMLHttpRequest and readyState==3]”. ''Webkit-dev'' mailing list. Retrieved [[29 November]] [[2007]].</ref><!-- TODO: still need ref for IE needing padding |
||
--> and second that the continually loading IFrame causes many browsers to display undesirable visual artifacts such as loading bars and wait cursors, though adding additional |
--> and second that the continually loading IFrame causes many browsers to display undesirable visual artifacts such as loading bars and wait cursors, though adding additional IFrames to the page will eliminate these artifacts in some browsers.<ref name="meteor-transports"/> |
||
=== Htmlfile ActiveX object === |
===== Htmlfile ActiveX object ===== |
||
By placing the incrementally-rendered IFrame inside an ActiveX object, it is possible to remove the negative side-effects of the IFrame transport in [[Internet Explorer]].<ref name="gtalks-javascript">Alex Russell ([[12 February]] [[2006]]). “[http://alex.dojotoolkit.org/?p=538 What else is buried down in the depths of Google’s amazing JavaScript?]”. ''Continuing Intermittent Incoherency''. Retrieved [[29 November]] [[2007]].<br/> For advice about avoiding garbage collection bugs when implementing Comet with htmlfiles, see:<br/> Michael Carter ([[25 October]] [[2007]]). “[http://cometdaily.com/2007/10/25/http-streaming-and-internet-explorer/ HTTP Streaming and Internet Explorer]”. ''Comet Daily''. Retrieved [[29 November]] [[2007]].<br/> Michael Carter ([[18 November]] [[2007]]). “[http://cometdaily.com/2007/11/18/ie-activexhtmlfile-transport-part-ii/ IE ActiveX("htmlfile") Transport, Part II]”. ''Comet Daily''. Retrieved 29 Nov 2007.</ref><ref name="comet-future-1"/> The technique only works in Internet Explorer, however. |
By placing the incrementally-rendered IFrame inside an ActiveX object, it is possible to remove the negative side-effects of the IFrame transport in [[Internet Explorer]].<ref name="gtalks-javascript">Alex Russell ([[12 February]] [[2006]]). “[http://alex.dojotoolkit.org/?p=538 What else is buried down in the depths of Google’s amazing JavaScript?]”. ''Continuing Intermittent Incoherency''. Retrieved [[29 November]] [[2007]].<br/> For advice about avoiding garbage collection bugs when implementing Comet with htmlfiles, see:<br/> Michael Carter ([[25 October]] [[2007]]). “[http://cometdaily.com/2007/10/25/http-streaming-and-internet-explorer/ HTTP Streaming and Internet Explorer]”. ''Comet Daily''. Retrieved [[29 November]] [[2007]].<br/> Michael Carter ([[18 November]] [[2007]]). “[http://cometdaily.com/2007/11/18/ie-activexhtmlfile-transport-part-ii/ IE ActiveX("htmlfile") Transport, Part II]”. ''Comet Daily''. Retrieved 29 Nov 2007.</ref><ref name="comet-future-1"/> The technique only works in Internet Explorer, however. |
||
=== Multipart XHR === |
==== Multipart XHR ==== |
||
The [[XMLHttpRequest]] (XHR) object, the main tool used by Ajax applications for browser–server communication, can also be pressed into service for server–browser Comet messaging, in a few different ways. |
The [[XMLHttpRequest]] (XHR) object, the main tool used by Ajax applications for browser–server communication, can also be pressed into service for server–browser Comet messaging, in a few different ways. |
||
In 1995, [[Netscape Navigator]] added a feature called “server push”, which allowed servers to send new versions of an image or HTML page to that browser, as part of a [[MIME#Multipart messages|multipart]] HTTP response (see [[#History|History]] section, below), using the content type <code>multipart/x-mixed-replace</code>. Since 2004, [[Gecko (layout engine)|Gecko]]-based browsers such as [[Mozilla Firefox|Firefox]] accept multipart responses to XHR, which can therefore be used as a streaming Comet transport.<ref>Johnny Stenback, et al. (March–April 2004). “[http://bugzilla.mozilla.org/show_bug.cgi?id=237319 Bug 237319 – Add support for server push using <code>multipart/x-mixed-replace</code> with XMLHttpRequest]”. ''Mozilla Bugzilla'' bug tracker. Retrieved [[29 November]] [[2007]]. Also see:<br/> Alex Russell ([[6 August]] [[2005]]). “[http://alex.dojotoolkit.org/?p=503 Toward server-sent data w/o iframes]”. ''Continuing Intermittent Incoherency''. Retrieved [[29 November]] [[2007]].</ref> On the server side, each message is encoded as a separate portion of the multipart response, and on the client, the [[callback (computer science)|callback function]] provided to the XHR <code>onreadystatechange</code> function will be called as each message arrives. This functionality is only included in Gecko-based browsers, though there is discussion of adding it to Webkit.<ref>Rob Butler, et al. (June 2006). “[http://bugs.webkit.org/show_bug.cgi?id=14392 Bug 14392: Add support for <code>multipart/x-mixed-replace</code> to XMLHttpRequest]”. ''Webkit Bugzilla'' bug tracker. Retrieved [[29 November]] [[2007]].</ref> Additionally, it is |
In 1995, [[Netscape Navigator]] added a feature called “server push”, which allowed servers to send new versions of an image or HTML page to that browser, as part of a [[MIME#Multipart messages|multipart]] HTTP response (see [[#History|History]] section, below), using the content type <code>multipart/x-mixed-replace</code>. Since 2004, [[Gecko (layout engine)|Gecko]]-based browsers such as [[Mozilla Firefox|Firefox]] accept multipart responses to XHR, which can therefore be used as a streaming Comet transport.<ref>Johnny Stenback, et al. (March–April 2004). “[http://bugzilla.mozilla.org/show_bug.cgi?id=237319 Bug 237319 – Add support for server push using <code>multipart/x-mixed-replace</code> with XMLHttpRequest]”. ''Mozilla Bugzilla'' bug tracker. Retrieved [[29 November]] [[2007]]. Also see:<br/> Alex Russell ([[6 August]] [[2005]]). “[http://alex.dojotoolkit.org/?p=503 Toward server-sent data w/o iframes]”. ''Continuing Intermittent Incoherency''. Retrieved [[29 November]] [[2007]].</ref> On the server side, each message is encoded as a separate portion of the multipart response, and on the client, the [[callback (computer science)|callback function]] provided to the XHR <code>onreadystatechange</code> function will be called as each message arrives. This functionality is only included in Gecko-based browsers, though there is discussion of adding it to Webkit.<ref>Rob Butler, et al. (June 2006). “[http://bugs.webkit.org/show_bug.cgi?id=14392 Bug 14392: Add support for <code>multipart/x-mixed-replace</code> to XMLHttpRequest]”. ''Webkit Bugzilla'' bug tracker. Retrieved [[29 November]] [[2007]].</ref> Additionally, it is currently impossible to determine when the multipart XHR connection has been closed.<ref>Alex Russell ([[21 December]] [[2006]]). “[http://alex.dojotoolkit.org/?p=595 Adventures In Comet and Multipart Mime]”. ''Continuing Intermittent Incoherency''. Retrieved [[29 November]] [[2007]].</ref> |
||
=== XHR streaming === |
==== XHR streaming ==== |
||
Instead of creating a multipart response, and depending on the browser to transparently parse each event, it is also possible to generate a custom data format for an XHR response, and parse out each event using browser-side JavaScript, relying only on the browser firing the <code>onreadystatechange</code> callback each time it receives new data, with ready state 3 (this is the behavior of both Gecko- and Webkit-based browsers).<ref name="comet-future-1"/><ref name="meteor-transports"/> Note that for Webkit-based browsers, this requires at least 256 bytes of data at the beginning of the event stream, before Webkit will begin to incrementally render it.<ref name="maciej"/> |
Instead of creating a multipart response, and depending on the browser to transparently parse each event, it is also possible to generate a custom data format for an XHR response, and parse out each event using browser-side JavaScript, relying only on the browser firing the <code>onreadystatechange</code> callback each time it receives new data, with ready state 3 (this is the behavior of both Gecko- and Webkit-based browsers).<ref name="comet-future-1"/><ref name="meteor-transports"/> Note that for Webkit-based browsers, this requires at least 256 bytes of data at the beginning of the event stream, before Webkit will begin to incrementally render it.<ref name="maciej"/> |
||
=== |
===Long polling=== |
||
Because none of the above streaming transports works across all modern browsers without causing negative side-effects in any—forcing Comet developers to implement several complex streaming transports, switching between them depending on the browser—many Comet applications instead opt for long polling, which is easy to implement on the browser side, and works in every browser which supports XHR. |
|||
⚫ | None of the above streaming transports works across all modern browsers without causing negative side-effects in any—forcing Comet developers to implement several complex streaming transports, switching between them depending on the browser. Consequently many Comet applications instead opt for long polling, which is easier to implement on the browser side, and works, at minimum, in every browser that supports XHR. As the name suggests, ''long polling'' requires a new request for each event (or set of events). The browser makes an Ajax-style request to the server, which is kept open until the server has new data to send to the browser. After sending such an event, the server closes the connection, and the browser immediately opens a new one. |
||
⚫ | {{Rquote|right|This analysis shows that for the worst case, when the message rate is high, load and latency for Comet long-polling are identical to traditional polling, and for most cases the load and latency are significantly better than traditional polling.|Greg Wilkins<ref name="wilkins-comparison"/>}} |
||
⚫ | Unlike with polling, long polling sends an event [[Payload (software)|payload]] along with each connection. While in the worst case—frequently occurring events with small payloads—long polling incurs significant [[computational overhead]], Greg Wilkins found that in most cases, long polling outperforms polling.<ref name="wilkins-comparison">Greg Wilkins ([[6 November]] [[2007]]). “[http://cometdaily.com/2007/11/06/comet-is-always-better-than-polling/ Comet is Always Better Than Polling]”. ''Comet Daily''. Retrieved [[29 November]] [[2007]].</ref> Streaming has better performance still, as it eliminates much of the per-message overhead. |
||
Specific technologies for accomplishing long-polling include the following. |
|||
==== XHR long polling ==== |
|||
For the most part, XHR long polling works like any standard use of XHR. The browser makes an asynchronous request of the server, and provides a function to be called when the server has responded. At the end of this callback function, the browser creates and sends another XHR, to await the next event. Thus the browser always keeps a connection open to the server, to be answered as each event occurs. |
For the most part, XHR long polling works like any standard use of XHR. The browser makes an asynchronous request of the server, and provides a function to be called when the server has responded. At the end of this callback function, the browser creates and sends another XHR, to await the next event. Thus the browser always keeps a connection open to the server, to be answered as each event occurs. |
||
=== Dynamic script tag long polling === |
==== Dynamic script tag long polling ==== |
||
While any Comet transport can be made to work across [[subdomains]], none of the above transports can be used across different [[second-level domain]]s (SLDs), due to browser security policies designed to prevent [[cross-site scripting]] attacks.<ref>Andrew Betts ([[4 December]] [[2007]]). “[http://cometdaily.com/2007/12/04/cross-site-scripting-joy/ Cross Site Scripting Joy]”. ''Comet Daily''. Retrieved [[14 December]] [[2007]].</ref> That is, if the main web page is served from one SLD, and the Comet server is located at another SLD, Comet events cannot be used to modify the HTML and DOM of the main page, using those transports. This can be worked around by creating a [[proxy server]] in front of one or both sources, making them appear to originate from the same domain; however, this is often undesirable, for complexity or performance reasons. |
While any Comet transport can be made to work across [[subdomains]], none of the above transports can be used across different [[second-level domain]]s (SLDs), due to browser security policies designed to prevent [[cross-site scripting]] attacks.<ref>Andrew Betts ([[4 December]] [[2007]]). “[http://cometdaily.com/2007/12/04/cross-site-scripting-joy/ Cross Site Scripting Joy]”. ''Comet Daily''. Retrieved [[14 December]] [[2007]].</ref> That is, if the main web page is served from one SLD, and the Comet server is located at another SLD, Comet events cannot be used to modify the HTML and DOM of the main page, using those transports. This can be worked around by creating a [[proxy server]] in front of one or both sources, making them appear to originate from the same domain; however, this is often undesirable, for complexity or performance reasons. |
||
Line 94: | Line 93: | ||
=== Server-sent events === |
=== Server-sent events === |
||
All of the previously listed transports are [[ad hoc]] uses of browser features not originally intended for Comet. Since 2005, another alternative, produced by the [[Web Hypertext Application Technology Working Group]] (WHATWG), has existed as part of the draft [[HTML 5]] specification. Called server-sent events, it attempts to avoid the disadvantages of other Comet transports, while making Comet applications |
All of the previously listed transports are [[ad hoc]] uses of browser features not originally intended for Comet. Since 2005, another alternative, produced by the [[Web Hypertext Application Technology Working Group]] (WHATWG), has existed as part of the draft [[HTML 5]] specification. Called server-sent events, it attempts to avoid the disadvantages of other Comet transports, while making Comet applications more straight-forward to implement, both on the server side, and in the browser-side JavaScript.<ref name='server-sent-events'>Ian Hickson, et al. (2005–2008). ''HTML 5 specification'', § 6.2: [http://www.whatwg.org/specs/web-apps/current-work/multipage/section-server-sent-events.html Server-sent DOM events]. WHATWG. Retrieved [[14 December]] [[2007]].</ref><ref name='comet-future-2'>Jacob Rus ([[10 January]] [[2008]]). “[http://cometdaily.com/2008/01/10/the-future-of-comet-part-2-html-5%e2%80%99s-server-sent-events/ The Future of Comet: Part 2, HTML 5’s Server-Sent Events]”. ''Comet Daily''. Retrieved [[1 April]] [[2008]].</ref> |
||
⚫ | The server-sent event portions of the HTML 5 specification stipulate both a new HTML element, <code>event-source</code>, and a new data format, called the DOM event stream. JavaScript can be used to attach callback functions to multiple types of events. Because server-sent events can be received by an HTML element in the browser, the specification leaves room for future browsers to implement special behavior for some event types, which could be used to make purely [[declarative programming|declarative]] Comet applications (that is, not requiring any imperative JavaScript at all). |
||
=== General considerations === |
|||
⚫ | The HTTP 1.1 specification states that “A single-user client ''should not'' maintain more than 2 connections with any server or proxy”,<ref>''HTTP 1.1 specification'', [http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html section 8.14]. W3C. Retrieved [[30 November]] [[2007]].</ref> and this recommendation is followed by most browsers, including Internet Explorer and Firefox. Holding one connection open for Comet can therefore impact performance; the browser may be unable to send a new user-initiated Ajax request while the browser loads, for example, a series of images. This can be worked around by creating a distinct [[hostname]] (usually at a different [[subdomain]]) for Comet connections—these two subdomains might be hosted on the same physical server. |
||
⚫ | The server-sent event portions of the HTML 5 specification stipulate both a new HTML element, <code>event-source</code>, and a new data format, called the DOM event stream. JavaScript can be used to attach callback functions to multiple types of events. Because server-sent events can be received by an HTML element in the browser, the specification leaves room for future browsers to implement special behavior for some event types, which could be used to make purely [[declarative programming|declarative]] Comet applications (that is, not requiring any imperative JavaScript at all). This is a controversial proposal; some developers feel that the additional complexity is unnecessary, because such applications are never likely to be purely declarative, and it is not difficult to just use JavaScript. |
||
=== Alternatives === |
|||
⚫ | |||
== Scalability == |
== Scalability == |
||
Line 130: | Line 123: | ||
Many Comet applications can be organized in terms of a [[publish/subscribe]] (pub/sub) architecture.<ref name="scalable-comet"/> In pub/sub, message senders do not send messages directly to message receivers. Instead, published messages are classified into “channels”, to which interested users subscribe. Publishers are separated from subscribers by a pub/sub layer, which takes care of the details of sending messages published to each channel to its subscribers. |
Many Comet applications can be organized in terms of a [[publish/subscribe]] (pub/sub) architecture.<ref name="scalable-comet"/> In pub/sub, message senders do not send messages directly to message receivers. Instead, published messages are classified into “channels”, to which interested users subscribe. Publishers are separated from subscribers by a pub/sub layer, which takes care of the details of sending messages published to each channel to its subscribers. |
||
Some Comet servers are explicitly organized around publish/subscribe, building it in to the Comet server directly. This has the advantage of reducing the number of moving parts, and potentially aids standardization |
Some Comet servers, such as those implementing the Bayeux protocol, are explicitly organized around publish/subscribe, building it in to the Comet server directly.<ref name="bayeux"/> This has the advantage of reducing the number of moving parts, and potentially aids standardization (see the [[#Standardization attempts]]). Alternately, an existing pub/sub system can be used, such as [[Internet Relay Chat]], [[XMPP]] (Jabber), or the [[Java Message Service]], in a layer above the Comet server, and can be customized to maximize performance for the particular application.<ref name="scalable-comet"/> |
||
== Reliability == |
== Reliability == |
||
Line 159: | Line 152: | ||
=== Popularization === |
=== Popularization === |
||
In 2005 and 2006, several prominent applications exposed Comet to a wider audience: [[Meebo]]’s multi-protocol web-based chat application enables users to connect to AOL, Yahoo, and Microsoft chat platforms through the browser; Google added web-based chat to [[Gmail]]; [[JotSpot]], a startup since acquired by Google, built Comet-based real-time collaborative document editing; Comet-based chat is the centerpiece of the event-planning site [[Renkoo]].<ref name="gtalks-javascript"/><ref>Dion Almaer ([[29 September]] [[2005]]). “[http://ajaxian.com/archives/jotspot-live-live-group-note-taking Jotspot Live: Live, group note-taking]” (interview with Abe Fettig). ''Ajaxian''. Retrieved [[15 December]] [[2007]]. <br>Matt Marshall ([[15 December]] [[2006]]). “[http://venturebeat.com/2006/12/15/renkoo-launches-just-in-time-to-schedule-holiday-cocktails/ Renkoo launches event service — in time to schedule holiday cocktails]”. ''Venture Beat''. Retrieved [[15 December]] [[2007]].</ref> Meanwhile, Comet continued to make inroads into enterprise markets. |
In 2005 and 2006, several prominent applications exposed Comet to a wider audience: [[Meebo]]’s multi-protocol web-based chat application enables users to connect to AOL, Yahoo, and Microsoft chat platforms through the browser; Google added web-based chat to [[Gmail]]; [[JotSpot]], a startup since acquired by Google, built Comet-based real-time collaborative document editing; Comet-based chat is the centerpiece of the event-planning site [[Renkoo]].<ref name="gtalks-javascript"/><ref>Dion Almaer ([[29 September]] [[2005]]). “[http://ajaxian.com/archives/jotspot-live-live-group-note-taking Jotspot Live: Live, group note-taking]” (interview with Abe Fettig). ''Ajaxian''. Retrieved [[15 December]] [[2007]]. <br>Matt Marshall ([[15 December]] [[2006]]). “[http://venturebeat.com/2006/12/15/renkoo-launches-just-in-time-to-schedule-holiday-cocktails/ Renkoo launches event service — in time to schedule holiday cocktails]”. ''Venture Beat''. Retrieved [[15 December]] [[2007]].</ref> Meanwhile, Comet continued to make inroads into enterprise markets. For instance, new enterprise Comet companies and solutions were created such as the Java-based [[ICEfaces]] [[JavaServer Faces|JSF]] framework. Others that had previously used Java-applet based transports, such as Caplin Systems, switched instead to pure-JavaScript implementations.<ref>Clint Boulton ([[27 December]] [[2005]]). “[http://www.devxnews.com/article.php/3573506/ Startups Board the AJAX Bandwagon]”. ''DevX News''. Retrieved [[18 February]] [[2008]].</ref><ref name="comet-at-caplin"/> |
||
In March 2006, [[software engineer]] Alex Russell coined the term ''Comet'' in a post on his personal blog. The new term was a play on ''Ajax'' ([[Ajax (cleanser)|Ajax]] and [[Comet (cleanser)|Comet]] both being common household cleansers).<ref name="alex_comet">Alex Russell ([[3 March]] [[2006]]). “[http://alex.dojotoolkit.org/?p=545 Comet: Low Latency Data for the Browser]”. ''Continuing Intermittent Incoherency.'' Retrieved [[29 November]] [[2007]].</ref> This [[umbrella term]] for previously existing concepts gained currency as a moniker, and ''Comet'' quickly became a prominent lecture topic at web-related technology conferences. In late 2007, the website ''Comet Daily'' assembled a group of Comet server implementors to write articles about Comet techniques and usage.<ref>Dylan Schiemann ([[18 October]] [[2007]]). “[http://cometdaily.com/2007/10/18/why-comet-daily/ Why Comet Daily?]”. ''Comet Daily'' . Retrieved 8 Jan 2008.</ref> |
In March 2006, [[software engineer]] Alex Russell coined the term ''Comet'' in a post on his personal blog. The new term was a play on ''Ajax'' ([[Ajax (cleanser)|Ajax]] and [[Comet (cleanser)|Comet]] both being common household cleansers).<ref name="alex_comet">Alex Russell ([[3 March]] [[2006]]). “[http://alex.dojotoolkit.org/?p=545 Comet: Low Latency Data for the Browser]”. ''Continuing Intermittent Incoherency.'' Retrieved [[29 November]] [[2007]].</ref> This [[umbrella term]] for previously existing concepts gained currency as a moniker, and ''Comet'' quickly became a prominent lecture topic at web-related technology conferences. In late 2007, the website ''Comet Daily'' assembled a group of Comet server implementors to write articles about Comet techniques and usage.<ref>Dylan Schiemann ([[18 October]] [[2007]]). “[http://cometdaily.com/2007/10/18/why-comet-daily/ Why Comet Daily?]”. ''Comet Daily'' . Retrieved 8 Jan 2008.</ref> |
||
Line 172: | Line 165: | ||
<ol style="list-style-type: lower-alpha;"> |
<ol style="list-style-type: lower-alpha;"> |
||
<li>{{note|browser}} Because web browsers are by far the most common applications used to access the web, and because traditionally non-browser [[user agent]]s have had little support for Comet, the term ''browser'' will be used throughout this article instead of the more generic terms ''client application'' or ''user agent''. ''Browser'' in this context should be understood to imply web user agents in general.</li> |
<li>{{note|browser}} Because web browsers are by far the most common applications used to access the web, and because traditionally non-browser [[user agent]]s have had little support for Comet, the term ''browser'' will be used throughout this article instead of the more generic terms ''client application'' or ''user agent''. ''Browser'' in this context should be understood to imply web user agents in general.</li> |
||
⚫ | <li>{{note|connections}}The HTTP 1.1 specification states that “A single-user client ''should not'' maintain more than 2 connections with any server or proxy”,<ref>''HTTP 1.1 specification'', [http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html section 8.14]. W3C. Retrieved [[30 November]] [[2007]].</ref> and this recommendation is followed by most browsers, including Internet Explorer and Firefox. Holding one connection open for Comet can therefore impact performance; the browser may be unable to send a new user-initiated Ajax request while the browser loads, for example, a series of images. This can be worked around by creating a distinct [[hostname]] (usually at a different [[subdomain]]) for Comet connections—these two subdomains might be hosted on the same physical server.</li> |
||
<li>{{note|ajax}} The term ''Ajax'', like ''Comet'', refers to a user interaction model, “a way of thinking about the architecture of web applications”, rather than any specific technique (in the words of [[Jesse James Garrett]], the term’s originator). Concretely, “an Ajax application eliminates the start–stop–start–stop nature of interaction on the Web by introducing an intermediary—an Ajax engine—between the user and the server.”<ref>Jesse James Garrett ([[18 February]] [[2005]]). “[http://www.adaptivepath.com/ideas/essays/archives/000385.php Ajax: A New Approach to Web Applications]”. ''Adaptive Path''. Retrieved [[29 November]] [[2007]].</ref></li> |
|||
<li>{{note|declarative}} This is a controversial proposal; some developers feel that the additional complexity is unnecessary, because such applications are never likely to be purely declarative, and it is not difficult to just use JavaScript.<ref name='comet-future-2'/></li> |
|||
<li>{{note|blazeds}} As part of their effort to make Flash and Flex a complete alternative to open-standards–based web technologies, Adobe has open-sourced the Java [[BlazeDS]] server plugin, which streams events to Flash applications.</li> |
<li>{{note|blazeds}} As part of their effort to make Flash and Flex a complete alternative to open-standards–based web technologies, Adobe has open-sourced the Java [[BlazeDS]] server plugin, which streams events to Flash applications.</li> |
||
<li>{{note|pubsub-inside}} This is for example the approach taken by Comet servers implementing the Bayeux protocol.<ref name="bayeux"/> See the [[#Standardization attempts|Standarization attempts]] section.</li> |
|||
<li>{{note|caplin-purejs}} New enterprise Comet companies and solutions were created, for instance the Java-based [[ICEfaces]] [[JavaServer Faces|JSF]] framework, and others which had previously used Java-applet based transports, for instance Caplin Systems, switched instead to pure-JavaScript implementations.<ref>Clint Boulton ([[27 December]] [[2005]]). “[http://www.devxnews.com/article.php/3573506/ Startups Board the AJAX Bandwagon]”. ''DevX News''. Retrieved [[18 February]] [[2008]].</ref><ref name="comet-at-caplin"/></li> |
|||
</ol> |
</ol> |
||
Revision as of 22:23, 27 June 2008
![]() | This article has multiple issues. Please help improve it or discuss these issues on the talk page. (Learn how and when to remove these template messages)
No issues specified. Please specify issues, or remove this template. |
Template:Otheruses2 In web development, Comet is a neologism coined in 2006 to describe application architecture in which a long-lived HTTP connection allows a web server to push data to a client asynchronously and with no need for the client to explicitly request it. Comet is an umbrella term that encompasses numerous specific techniques for achieving this user-interaction model. These methods rely on browser-native technologies, such as JavaScript, rather than on proprietary plugins, but have few other unifying features. Each method has its own trade-offs in terms of browser support and side effects, latency, and throughput.
The Comet approach differs from the original model of the web, in which a browser receives a complete web page in response to each request, and also from the Ajax model, in which a browser requests chunks of data in order to update the current page. The effect is similar to that of applications which use traditional Ajax with polling to detect new information on the server, but Comet improves throughput and reduces latency and server load. Consequently, Comet enables the creation of event-driven web applications and real-time interaction to an extent that would otherwise be untenable.
Traditional architectures
Web applications have historically been less flexible and capable than desktop applications counterparts, because of the many constraints of the online environment. One such traditional limitation, the limitation that Comet seeks to address, is the inability of a web server to choose when to send updated information to a web browser.[a] This limited interaction can engender an unwieldy series of interactions and precludes the use of real-time applications. It is the hallmark of the early page-by-page web model and is only partly addressed by the successive techniques of Ajax and Ajax with polling.
Page-by-page model
Traditionally, each chunk of information sent by a web server to a browser must be explicitly requested. Each time the user opens a web page, the browser initiates an HTTP connection to the web server, which returns the HTML code for the page and closes the connection. The browser then makes another HTTP request for each resource used by the page—e.g. an image or stylesheet—and the server responds to each in turn.
Wikipedia, for example, is a complex application built using this page-by-page approach. Users interact with the website by clicking hyperlinks to navigate from page to page, and edit or add new pages by filling out web forms, which also open new pages when submitted. On the server side, a complete HTML page is dynamically generated in response to each request. Users continually update wiki pages, but those changes are not reflected in Wikipedia’s interface until each page is reloaded.
Ajax
To overcome these limitations of the page-by-page model, many web applications turn to Ajax (asynchronous JavaScript and XML). The term Ajax, like Comet, refers to a user interaction model, “a way of thinking about the architecture of web applications”, rather than any specific technique (in the words of Jesse James Garrett, the term’s originator). Concretely, “an Ajax application eliminates the start–stop–start–stop nature of interaction on the Web by introducing an intermediary—an Ajax engine—between the user and the server.”[1] In the Ajax model, servers respond to each request in sequence, just as before, but the browser uses JavaScript to modify the current page rather than opening a new page. This limits the server’s response to only the relevant information (usually in XML or JSON format), dramatically increasing application responsiveness by avoiding redundant data transfer and eliminating whole-page re-rendering. Furthermore, since Ajax requests are handled asynchronously in the background, the user can continue to interact with the page as data is retrieved. A principle example of this technology is the Google Maps web application. [2] In Google Maps, new tiles of map imagery are loaded as the user clicks and drags the map, and the user can continue to pan and zoom the map even before all tiles in range have loaded.
Ajax does not fully address the limitations of the traditional page-by-page web model, however, because the server still responds to each request by the browser as a single event, closing each connection as a response is served. Any changing information is only updated in response to explicit user actions. This problem becomes a major hurdle when designing applications which should update in real time, in response to some event on the server, such as another user sending it information.
Ajax with polling
One solution is for the browser to regularly poll the server, asking it if a new event has occurred (e.g. each five seconds asking the server “Any new events?”). This introduces an unhappy trade-off between latency and server load; the average event latency is half the poll interval (plus network latency and any time spent processing data), so increasing responsiveness proportionally increases the number of requests received by the server. At high polling frequencies, this wastes server resources and bandwidth processing many negative responses (“No new events, try again later”). Although applications with predictable information updates, or those which tolerate relatively infrequent updates, can use polling without excessive waste, the technology is nonetheless too unwieldy for most implementations.
Implementation of Comet
Comet is an umbrella term for technologies that attempt to eliminate both the limitations of the page-by-page model and the cumbersome nature of traditional polling. Instead, Comet applications can accomplish something approaching real-time interaction by relying on a persistent HTTP connection to provide the browser with updates as designated by the server. Although, holding one connection open for Comet can negatively affect the performance of the client[b] and also presents scalability issues for the server (see #Scalability), this has not proved to be a significant barrier to adoption.
Because until recently, browsers were not designed with Comet in mind, web application developers mostly use several unintended side-effects of browser-native objects to build Comet “transports” (methods of sending Comet events), each with different benefits and drawbacks. Each of these requires specialized code on both the server, which must send specially-formed responses, and in the browser-side JavaScript.[3][4]
It is important to note that the use of such browser-native technologies is inherent in the term Comet. An alternative approach with the same goal is the use of plugins, such as Java applets or the proprietary Adobe Flash.[c] These have the advantage of working identically across all browsers with the appropriate plugin installed, need not use HTTP connections, and face none of the security restrictions placed on browser-native transports. These strengths, however, are also the main drawbacks of proprietary plugins: not all clients have the plugins installed—for instance, the Apple iPhone includes neither—and the use of protocols other than HTTP, and ports other than port 80, can cause them to be blocked by firewalls.
Comet, though, avoids many of these risks, the drawback being that a given Comet transport is often an ad hoc approach that works for a limited class of compatible browsers. The specific transport or transports best for any given use depends on which browsers are targeted, the desired performance of the solution, need for cross-domain use, tolerance for user interface side-effects, and the stringency of proxy servers and firewalls between the client and server.
Specific methods of implementing of Comet fall into two major categories: streaming and long polling.
Streaming
In an application using streaming Comet, the browser opens a single persistent connection to the server for all Comet events, which is handled incrementally on the browser side. Each time the server sends a new event, the browser interprets it, but neither side closes the connection. Specific technologies for accomplishing streaming Comet include the following.
“Forever frame” IFrame
The earliest Comet transport (in use as early as 2000, see History section below) uses an invisible IFrame HTML element (an inline frame, which allows a website to embed one HTML document inside another). This invisible IFrame is declared by the server to be infinitely long—hence “forever frame”—and as events occur, is gradually filled with script
tags, containing JavaScript to be executed in the browser. Because browsers render HTML pages incrementally, each script
tag is executed as it is received.[3]
The main benefit of the IFrame method is that it works in every common browser. Two downsides of this transport are first that it requires a kilobyte of data to be sent down the connection before the Safari browser (running on Mac OS X 10.4; this is fixed in the latest version of OS X) will begin incrementally rendering the IFrame or 256 bytes in Internet Explorer,[5] and second that the continually loading IFrame causes many browsers to display undesirable visual artifacts such as loading bars and wait cursors, though adding additional IFrames to the page will eliminate these artifacts in some browsers.[4]
Htmlfile ActiveX object
By placing the incrementally-rendered IFrame inside an ActiveX object, it is possible to remove the negative side-effects of the IFrame transport in Internet Explorer.[6][3] The technique only works in Internet Explorer, however.
Multipart XHR
The XMLHttpRequest (XHR) object, the main tool used by Ajax applications for browser–server communication, can also be pressed into service for server–browser Comet messaging, in a few different ways.
In 1995, Netscape Navigator added a feature called “server push”, which allowed servers to send new versions of an image or HTML page to that browser, as part of a multipart HTTP response (see History section, below), using the content type multipart/x-mixed-replace
. Since 2004, Gecko-based browsers such as Firefox accept multipart responses to XHR, which can therefore be used as a streaming Comet transport.[7] On the server side, each message is encoded as a separate portion of the multipart response, and on the client, the callback function provided to the XHR onreadystatechange
function will be called as each message arrives. This functionality is only included in Gecko-based browsers, though there is discussion of adding it to Webkit.[8] Additionally, it is currently impossible to determine when the multipart XHR connection has been closed.[9]
XHR streaming
Instead of creating a multipart response, and depending on the browser to transparently parse each event, it is also possible to generate a custom data format for an XHR response, and parse out each event using browser-side JavaScript, relying only on the browser firing the onreadystatechange
callback each time it receives new data, with ready state 3 (this is the behavior of both Gecko- and Webkit-based browsers).[3][4] Note that for Webkit-based browsers, this requires at least 256 bytes of data at the beginning of the event stream, before Webkit will begin to incrementally render it.[5]
Long polling
None of the above streaming transports works across all modern browsers without causing negative side-effects in any—forcing Comet developers to implement several complex streaming transports, switching between them depending on the browser. Consequently many Comet applications instead opt for long polling, which is easier to implement on the browser side, and works, at minimum, in every browser that supports XHR. As the name suggests, long polling requires a new request for each event (or set of events). The browser makes an Ajax-style request to the server, which is kept open until the server has new data to send to the browser. After sending such an event, the server closes the connection, and the browser immediately opens a new one.
This analysis shows that for the worst case, when the message rate is high, load and latency for Comet long-polling are identical to traditional polling, and for most cases the load and latency are significantly better than traditional polling.
— Greg Wilkins[10]
Unlike with polling, long polling sends an event payload along with each connection. While in the worst case—frequently occurring events with small payloads—long polling incurs significant computational overhead, Greg Wilkins found that in most cases, long polling outperforms polling.[10] Streaming has better performance still, as it eliminates much of the per-message overhead.
Specific technologies for accomplishing long-polling include the following.
XHR long polling
For the most part, XHR long polling works like any standard use of XHR. The browser makes an asynchronous request of the server, and provides a function to be called when the server has responded. At the end of this callback function, the browser creates and sends another XHR, to await the next event. Thus the browser always keeps a connection open to the server, to be answered as each event occurs.
Dynamic script tag long polling
While any Comet transport can be made to work across subdomains, none of the above transports can be used across different second-level domains (SLDs), due to browser security policies designed to prevent cross-site scripting attacks.[11] That is, if the main web page is served from one SLD, and the Comet server is located at another SLD, Comet events cannot be used to modify the HTML and DOM of the main page, using those transports. This can be worked around by creating a proxy server in front of one or both sources, making them appear to originate from the same domain; however, this is often undesirable, for complexity or performance reasons.
Unlike IFrames or XHR objects, script
tags can be pointed at any URI, and JavaScript code in the response will be executed in the current HTML document. This creates a potential security risk for both servers involved, and though the risk to the data provider (in our case, the Comet server) can be avoided using “JSONP”. As Bob Ippolito explains, “Your page is still toast if the remote host decides to inject malicious code instead of JSON data”.[12]
A long-polling Comet transport can be created by dynamically creating script
elements, and setting their source to the location of the Comet server, which then sends back JavaScript (or JSONP) with some event as its payload, and closes the connection. Each time the script connection is closed, the browser opens a new one, just as in the XHR long polling case. This method is the only cross-browser choice for developers looking to implement cross-domain Comet.[3][13]
Server-sent events
All of the previously listed transports are ad hoc uses of browser features not originally intended for Comet. Since 2005, another alternative, produced by the Web Hypertext Application Technology Working Group (WHATWG), has existed as part of the draft HTML 5 specification. Called server-sent events, it attempts to avoid the disadvantages of other Comet transports, while making Comet applications more straight-forward to implement, both on the server side, and in the browser-side JavaScript.[14][15]
The server-sent event portions of the HTML 5 specification stipulate both a new HTML element, event-source
, and a new data format, called the DOM event stream. JavaScript can be used to attach callback functions to multiple types of events. Because server-sent events can be received by an HTML element in the browser, the specification leaves room for future browsers to implement special behavior for some event types, which could be used to make purely declarative Comet applications (that is, not requiring any imperative JavaScript at all). This is a controversial proposal; some developers feel that the additional complexity is unnecessary, because such applications are never likely to be purely declarative, and it is not difficult to just use JavaScript.
Scalability
Because Comet applications send events in real time, they typically use more resources than other types of web applications, making them more difficult to scale (grow to support large numbers of users).
- Comet relies on continually keeping at least one server–client connection open for each client. Traditional web servers, designed for the page-by-page application architecture, cannot cope with such large numbers of open connections. This is a vertical scalability problem: it is difficult to handle many users on each server.
- Additionally, because Comet applications are often interactive, allowing arbitrary groups of users to communicate with each-other, splitting tasks among servers is more difficult than for applications in which each user acts independently. This is a horizontal scalability problem: it is difficult to add more servers to the application.
Vertical scalability
…traditional architecture based on the “one-thread-per-connection” model makes scalability practically impossible for tens of thousands of users.
— Alessandro Alinone[16]
Most web servers, such as Apache, are threaded applications; multiple threads run simultaneously, but each thread uses synchronous (or blocking) input/output (I/O). As each request arrives at the server, a thread is assigned to that connection. In a traditional web application, this connection is closed as quickly as possible, freeing the thread to handle another request; however, Comet requires connections which are kept open indefinitely. As long as one of these connections stays open, the thread handling it is unavailable for other requests, which are starved. As a consequence, each thread, which could normally serve dozens or hundreds of web requests per second, can handle only a few Comet connections. As threads are added, more and more processing time is spent in context switches, eventually slowing the server to a crawl.[17]
Because threaded servers using blocking I/O break down after such a small number of Comet users, servers designed for Comet use an event-driven model instead, with asynchronous I/O. Instead of requiring a new thread for each handful of connections, these event-based servers use a fixed number of threads, each of which handles as many connections as necessary. This type of server not only manages vastly more Comet users than a threaded server, but it also degrades gracefully: as server load increases, latency increases uniformly for all users, instead of starving some for long periods.[17]
Horizontal scalability
All web applications are difficult to scale to hundreds of thousands or millions of users. Because even the most powerful servers collapse under such a heavy load, resources (connections, processing, database storage, etc.) must be distributed across many servers. Scaling traditional web applications is well-understood, and supported by robust tools, such as the open source memcached distributed memory caching system.
The assignment of users to Comet servers depends on the nature of the application in question.[17] In applications where users can be broken into relatively small groups receiving the same events, each group can be assigned to a particular Comet server. For instance, in a multiplayer card game application, each user plays in a single game, and only a few users are involved in each game. Conversely, in applications where the events a user receives are independent of the events other users receive, particular users should be assigned to particular servers. For example, in a real-time weather map, updated information can easily be sent to each Comet server, which can then pass it along to the users connected to that server.
In the general case, however, where arbitrary users connect to arbitrary event sources—this might be the case, for instance, in a chat application which allows users to join arbitrary rooms—it is difficult to scalably distribute users among Comet servers. It is impossible to organize servers by group, because one user might connect to groups on multiple servers simultaneously, and also difficult to organize servers by user, because users on arbitrary servers may wish to communicate.[17]
This is especially difficult when the Comet server is built in to the application, because it precludes distributing Comet server nodes separately from application nodes. Michael Carter recommends building minimal functionality into the Comet server itself, and building applications with a layered architecture: treating each layer as a black box, so that each can be effectively scaled independently, and sharing nothing between Comet nodes.[17]
Publish/subscribe
Many Comet applications can be organized in terms of a publish/subscribe (pub/sub) architecture.[17] In pub/sub, message senders do not send messages directly to message receivers. Instead, published messages are classified into “channels”, to which interested users subscribe. Publishers are separated from subscribers by a pub/sub layer, which takes care of the details of sending messages published to each channel to its subscribers.
Some Comet servers, such as those implementing the Bayeux protocol, are explicitly organized around publish/subscribe, building it in to the Comet server directly.[18] This has the advantage of reducing the number of moving parts, and potentially aids standardization (see the #Standardization attempts). Alternately, an existing pub/sub system can be used, such as Internet Relay Chat, XMPP (Jabber), or the Java Message Service, in a layer above the Comet server, and can be customized to maximize performance for the particular application.[17]
Reliability
Proxy servers and firewalls between the browser and web server can pose network problems. Firewalls are often configured to drop connections that have been open for too long (as a security heuristic), so many Comet frameworks tear down and recreate the Comet connection periodically. Naive intervening HTTP proxies may buffer pushed messages in chunks up to 32 or 64 kilobytes, necessitating a system for adaptive detection of intervening proxy buffer sizes.[citation needed]
In clustered server environments (see Horizontal scalability above), messages must be routed to whichever Comet server a given browser is connected to, and for some applications, message delivery is critical even in the event of a server crash. In enterprise Java systems, this is typically handled by Message Oriented Middleware, often encapsulated by JavaSpaces.[citation needed]
History
Server push
In 1995, Netscape Navigator introduced “server push” technology, allowing web applications to update images or HTML pages at will, by sending new versions of a resource as separate parts of a multipart HTTP response (at the same time, Netscape also introduced “client pull”, a way for Navigator to re-request a page after a specific amount of time, analogous to the ajax with polling model described above).[19] Microsoft Internet Explorer copied this feature. The main use of server push was in webcams; each frame was pushed to browsers as a part of the multipart message.
While it was real-time, Netscape’s server push cannot really be defined as Comet, as it relied on complete replacement of pages. This also limited its adoption for general applications.
Java applets
The ability to embed Java applets into browsers opened richer real-time options. An applet can open a raw TCP socket to the server from which it has loaded. This socket can remain open as long as the browser keeps open the document which hosts the applet. Event notifications can be sent in any format—text or binary—and decoded by Java code in the applet.
But we are still working within the confines of a browser. Unless the applet constitutes the entire client application, it is difficult to integrate the HTML content with the updates coming from the server.
— Just van den Broecke[20]
Despite their capabilities, however, Java applets never really took off. User interfaces in Java applets were often buggy and frustrating for users, suffering graphical glitches. Communications on ports other than port 80 are blocked by aggressive firewalls. Not all users had the proper version of the Java plugin installed in their browsers, or even any version at all. When possible, web application developers preferred to use browser-native technologies (see Disadvantages of Java applets).[19][20] To mitigate these disadvantages, some developers—for instance, Caplin Systems in 1998—used Java applets merely as a transport mechanism, leaving application-specific interface logic to browser-native JavaScript.[21]
Early Comet applications
Circa 2000, developers began creating the first pure-JavaScript Comet applications, using the Frame/IFrame transport. Pushlets, a framework created by the Dutch Just van den Broecke, was the first open source Comet implementation, based on server-side Java servlets, and a client-side JavaScript library.[20] The 2000 startup KnowNow built several Comet demonstrations, and planned to create a platform on top of the Web, which would be used by other developers to implement real-time web apps. After releasing their Comet server prototype as mod_pubsub, KnowNow turned, like other Comet implementations of the time, to enterprise applications.[22][citation needed] Bang Networks—a 1999 Silicon Valley start-up backed by Netscape co-founder Marc Andreessen and lavishly financed—attempted to create a real-time push standard for the whole Web, but ran out of cash and folded at the end of 2003.[citation needed] Lightstreamer, an Italian company, focused on the financial market with their Java-based server.[citation needed]
While these early implementations made a splash in the Silicon Valley popular imagination, Comet’s impact didn’t at the time live up to the headlines. Comet instead found a niche in financial trading and similar enterprise markets, and for the next several years, remained in that niche, unable to expand to large-scale consumer-oriented applications.
Popularization
In 2005 and 2006, several prominent applications exposed Comet to a wider audience: Meebo’s multi-protocol web-based chat application enables users to connect to AOL, Yahoo, and Microsoft chat platforms through the browser; Google added web-based chat to Gmail; JotSpot, a startup since acquired by Google, built Comet-based real-time collaborative document editing; Comet-based chat is the centerpiece of the event-planning site Renkoo.[6][23] Meanwhile, Comet continued to make inroads into enterprise markets. For instance, new enterprise Comet companies and solutions were created such as the Java-based ICEfaces JSF framework. Others that had previously used Java-applet based transports, such as Caplin Systems, switched instead to pure-JavaScript implementations.[24][21]
In March 2006, software engineer Alex Russell coined the term Comet in a post on his personal blog. The new term was a play on Ajax (Ajax and Comet both being common household cleansers).[25] This umbrella term for previously existing concepts gained currency as a moniker, and Comet quickly became a prominent lecture topic at web-related technology conferences. In late 2007, the website Comet Daily assembled a group of Comet server implementors to write articles about Comet techniques and usage.[26]
Standardization attempts
Attempts to standardize Comet have come from two sides:
- The WHATWG’s HTML 5 specification attempts to standardize the Comet transport (see Server-sent events, above). If HTML 5 is implemented in many browsers, Comet developers will be able to avoid the current need to implement several transports.[14][15]
- The Bayeux protocol, defined by the Dojo foundation, leaves browser-specific transports in place, and defines a higher-level protocol for communication between browser and server, with the aim of allowing re-use of client-side JavaScript code with multiple Comet servers, and allowing the same Comet server to communicate with multiple client-side JavaScript implementations. Bayeux is based on a publish/subscribe model, so servers supporting Bayeux have publish/subscribe built-in.[18]
Notes
- ^ Because web browsers are by far the most common applications used to access the web, and because traditionally non-browser user agents have had little support for Comet, the term browser will be used throughout this article instead of the more generic terms client application or user agent. Browser in this context should be understood to imply web user agents in general.
- ^ The HTTP 1.1 specification states that “A single-user client should not maintain more than 2 connections with any server or proxy”,[27] and this recommendation is followed by most browsers, including Internet Explorer and Firefox. Holding one connection open for Comet can therefore impact performance; the browser may be unable to send a new user-initiated Ajax request while the browser loads, for example, a series of images. This can be worked around by creating a distinct hostname (usually at a different subdomain) for Comet connections—these two subdomains might be hosted on the same physical server.
- ^ As part of their effort to make Flash and Flex a complete alternative to open-standards–based web technologies, Adobe has open-sourced the Java BlazeDS server plugin, which streams events to Flash applications.
References
- ^ Jesse James Garrett (18 February 2005). “Ajax: A New Approach to Web Applications”. Adaptive Path. Retrieved 29 November 2007.
- ^ Paul Graham (November 2005). “Web 2.0”. paulgraham.com. Retrieved 29 November 2007.
- ^ a b c d e Jacob Rus (11 December 2007). “The Future of Comet: Part 1, Comet Today”. Comet Daily. Retrieved 14 December 2007.
- ^ a b c Andrew Betts (2007). “Browser Techniques”. Meteor website. Retrieved 29 November 2007.
- ^ a b Maciej Stachowiak (26 June 2007). “Re: XMLHttpRequest and readyState==3”. Webkit-dev mailing list. Retrieved 29 November 2007.
- ^ a b Alex Russell (12 February 2006). “What else is buried down in the depths of Google’s amazing JavaScript?”. Continuing Intermittent Incoherency. Retrieved 29 November 2007.
For advice about avoiding garbage collection bugs when implementing Comet with htmlfiles, see:
Michael Carter (25 October 2007). “HTTP Streaming and Internet Explorer”. Comet Daily. Retrieved 29 November 2007.
Michael Carter (18 November 2007). “IE ActiveX("htmlfile") Transport, Part II”. Comet Daily. Retrieved 29 Nov 2007. - ^ Johnny Stenback, et al. (March–April 2004). “Bug 237319 – Add support for server push using
multipart/x-mixed-replace
with XMLHttpRequest”. Mozilla Bugzilla bug tracker. Retrieved 29 November 2007. Also see:
Alex Russell (6 August 2005). “Toward server-sent data w/o iframes”. Continuing Intermittent Incoherency. Retrieved 29 November 2007. - ^ Rob Butler, et al. (June 2006). “Bug 14392: Add support for
multipart/x-mixed-replace
to XMLHttpRequest”. Webkit Bugzilla bug tracker. Retrieved 29 November 2007. - ^ Alex Russell (21 December 2006). “Adventures In Comet and Multipart Mime”. Continuing Intermittent Incoherency. Retrieved 29 November 2007.
- ^ a b Greg Wilkins (6 November 2007). “Comet is Always Better Than Polling”. Comet Daily. Retrieved 29 November 2007.
- ^ Andrew Betts (4 December 2007). “Cross Site Scripting Joy”. Comet Daily. Retrieved 14 December 2007.
- ^ Bob Ippolito (5 December 2005). “Remote JSON – JSONP”. from __future__ import *. Retrieved 30 November 2007.
- ^ Alex Russell (22 July 2006). “Cross Domain Comet”. Continuing Intermittent Incoherency. Retrieved 30 November 2007.
- ^ a b Ian Hickson, et al. (2005–2008). HTML 5 specification, § 6.2: Server-sent DOM events. WHATWG. Retrieved 14 December 2007.
- ^ a b Jacob Rus (10 January 2008). “The Future of Comet: Part 2, HTML 5’s Server-Sent Events”. Comet Daily. Retrieved 1 April 2008.
- ^ Alessandro Alinone (December 2005). “Changing the Web Paradigm”. Lightstreamer white paper. Retrieved 14 December 2007.
- ^ a b c d e f g Michael Carter (24 October 2007). “Comet for Highly Scalable Applications”. Presentation at The Ajax Experience Boston. (Link goes to PDF slides). Retrieved 30 November 2007.
- ^ a b Alex Russell, et al. (2007). Bayeux Protocol specification, 1.0 draft 1. Dojo Foundation. Retrieved 14 December 2007.
- ^ a b Alessandro Alinone (19 October 2007). “Comet and Push Technology”. Comet Daily. Retrieved 14 December 2007.
- ^ a b c Just van den Broecke (3 January 2007). “Pushlets: Send events from servlets to DHTML client browsers”. JavaWorld. Retrieved 14 December 2007.
- ^ a b Martin Tyler (30 November 2007). “The Evolution of Comet at Caplin”. Comet Daily. Retrieved 19 February 2008.
- ^ Rohit Khare (August 2005). “Beyond AJAX: Accelerating Web Applications with Real-Time Event Notification”. KnowNow white paper (link from the Wayback Machine). Retrieved 14 December 2007.
- ^ Dion Almaer (29 September 2005). “Jotspot Live: Live, group note-taking” (interview with Abe Fettig). Ajaxian. Retrieved 15 December 2007.
Matt Marshall (15 December 2006). “Renkoo launches event service — in time to schedule holiday cocktails”. Venture Beat. Retrieved 15 December 2007. - ^ Clint Boulton (27 December 2005). “Startups Board the AJAX Bandwagon”. DevX News. Retrieved 18 February 2008.
- ^ Alex Russell (3 March 2006). “Comet: Low Latency Data for the Browser”. Continuing Intermittent Incoherency. Retrieved 29 November 2007.
- ^ Dylan Schiemann (18 October 2007). “Why Comet Daily?”. Comet Daily . Retrieved 8 Jan 2008.
- ^ HTTP 1.1 specification, section 8.14. W3C. Retrieved 30 November 2007.
External links
- Comet Daily – a website dedicated to articles on Comet techniques
- HTTP Streaming at Ajax Patterns