<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>OCTO talks ! &#187; Comet</title>
	<atom:link href="http://blog.octo.com/tag/comet/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.octo.com</link>
	<description>Le blog d&#039;OCTO Technology, cabinet d&#039;architectes en systèmes d&#039;information</description>
	<lastBuildDate>Fri, 03 Feb 2012 13:46:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Le push web vu par Diffusion &#8211; Partie 1</title>
		<link>http://blog.octo.com/le-push-web-vu-par-diffusion-partie-1/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=le-push-web-vu-par-diffusion-partie-1</link>
		<comments>http://blog.octo.com/le-push-web-vu-par-diffusion-partie-1/#comments</comments>
		<pubDate>Tue, 19 Jul 2011 08:53:56 +0000</pubDate>
		<dc:creator>Nicolas Colomer</dc:creator>
				<category><![CDATA[Architecture et technologies]]></category>
		<category><![CDATA[Comet]]></category>
		<category><![CDATA[diffusion]]></category>
		<category><![CDATA[push web]]></category>
		<category><![CDATA[pushtechnology]]></category>
		<category><![CDATA[web messaging]]></category>
		<category><![CDATA[WebSocket]]></category>

		<guid isPermaLink="false">http://blog.octo.com/?p=23931</guid>
		<description><![CDATA[Les problématiques de push de messages vers des clients connectés (encore appelé &#171;&#160;web messaging&#160;&#187;) sont courantes dans les secteurs où l’information varie sur des temps très court, comme la finance, la sureté, la supervision ou encore les réseaux sociaux. Les données doivent être diffusées le plus rapidement possible à de nombreux clients, car ces données n&#8217;ont [...]
Suggestion d'articles :<ol>
<li><a href='http://blog.octo.com/le-push-web-vu-par-diffusion-partie-2/' rel='bookmark' title='Le push web vu par Diffusion &#8211; Partie 2'>Le push web vu par Diffusion &#8211; Partie 2</a></li>
<li><a href='http://blog.octo.com/le-push-web-avec-pusher/' rel='bookmark' title='Le push web avec Pusher'>Le push web avec Pusher</a></li>
<li><a href='http://blog.octo.com/securite-des-services-web-1ere-partie/' rel='bookmark' title='Sécurité des services web – 1ère partie'>Sécurité des services web – 1ère partie</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fblog.octo.com%252Fle-push-web-vu-par-diffusion-partie-1%252F%22%2C%20%22style%22%3A%20%22small%22%2C%20%22title%22%3A%20%22Le%20push%20web%20vu%20par%20Diffusion%20-%20Partie%201%22%20%7D);"></div>
<p>Les problématiques de push de messages vers des clients connectés (encore appelé &laquo;&nbsp;web messaging&nbsp;&raquo;) sont courantes dans les secteurs où l’information varie sur des temps très court, comme la finance, la sureté, la supervision ou encore les réseaux sociaux. Les données doivent être diffusées le plus rapidement possible à de nombreux clients, car ces données n&#8217;ont de valeur (ou d&#8217;intérêt) que pendant un temps limité.</p>
<p>Pour faire du web messaging, il existe aujourd’hui différentes techniques (polling, « <a title="Comet" href="http://en.wikipedia.org/wiki/Comet_(programming)">comet</a> » long polling et streaming) qui s’appuient sur des technologies variées (XmlHttpRequest, <a title="WebSocket" href="http://en.wikipedia.org/wiki/WebSocket">WebSocket</a>, Flash socket, Silverlight socket, iFrame, RTMP). Le marché évolue d’ailleurs clairement dans ce sens : des solutions, jusqu’à présent concentrées sur la problématique <a title="MOM" href="http://fr.wikipedia.org/wiki/Message-Oriented_Middleware">Message-Oriented Middleware</a> (<a title="RabbitMQ" href="http://www.rabbitmq.com/">RabbitMQ</a>, <a title="HornetQ" href="http://www.jboss.org/hornetq">HornetQ</a>) offrent désormais une API HTTP, avec pour certaines d’entre elles, une API cliente basée sur WebSocket (même si cette technologie n’est pas encore <a href="http://caniuse.com/#feat=websockets">compatible</a> avec tous les navigateurs).</p>
<p>Nous allons ici parler d’une de ces solutions, permettant à la fois d’assurer une grande compatibilité et de hautes performances : <strong>Diffusion</strong>. Cet article a pour objet de présenter cette solution. Il se découpera en deux parties :</p>
<ul>
<li>Une présentation des concepts et du framework Diffusion</li>
<li>Une présentation plus technique via la mise en œuvre d&#8217;un POC</li>
</ul>
<p><span id="more-23931"></span></p>
<h1>1. Qu’est ce que Diffusion ?</h1>
<p>Diffusion est une solution standalone de diffusion de message éditée par la société <a title="PushTechnology" href="http://www.pushtechnology.com/" target="_blank">PushTechnology</a>, société fondée en 2006 et basée à Londres, spécialisée dans les problématiques de middleware orientés messages et de push web.</p>
<p>PushTechnology propose :</p>
<ul>
<li>Un serveur, appelé <strong>Diffusion Message Broker</strong>, basé sur le protocole TCP</li>
<li>Une surcouche orientée push web, appelée <strong>Diffusion Internet Message Broker</strong>, basé sur les protocoles HTTP et WebSocket</li>
<li>Une API, disponible dans différents langages</li>
</ul>
<h2>1.1. Diffusion Message Broker</h2>
<p>Le serveur <strong>Message Broker</strong> est un serveur orienté message développé en Java, multi-threadé et utilisant le framework <a title="NIO" href="http://en.wikipedia.org/wiki/New_I/O" target="_blank">NIO</a> (gestion d’I/O non bloquantes) afin de garantir le service auprès d’un grand nombre de clients concurrents.</p>
<p>Citons quelques-unes des key features <span style="text-decoration: underline;">mises en avant par l’éditeur</span> :</p>
<ul>
<li><strong>Hautes performances </strong>: jusqu’à 300k messages (de l’ordre de quelques octets) par seconde pour un unique broker déployé sur un serveur de configuration standard et dans un contexte intranet. L’éditeur n’indique pas d’informations supplémentaires sur les conditions de test.<br />
Il est à noter que ces messages sont au format binaire, permettant ainsi d’adapter leur structure au plus proche des besoins et de transmettre tout type de contenu.</li>
<li><strong>Très faible latence</strong> (de l’ordre de quelques millisecondes) et synchronisation entre les différents brokers au sein d’une architecture distribuée, permettant d’assurer l’intégrité des messages et leur localisation à tout instant.</li>
<li><strong>Canaux bidirectionnels</strong> de transmission des messages : un client peut donc répondre à un message qui lui serait soumis.</li>
</ul>
<h2>1.2. Diffusion Internet Message Broker</h2>
<p>L’une des spécificités de la solution Diffusion, celle qui nous intéresse aujourd’hui, est qu’elle offre une surcouche orientée web (et donc sur protocole HTTP). Appelée <strong>internet message broker</strong>, cette surcouche permet de diffuser des messages via Internet à destination de navigateurs, clients mobiles ou clients lourds connectés. Des tests de performance réalisés par l’éditeur ont montré qu’il était possible de diffuser jusqu’à 90k messages par secondes auprès de tels clients via Internet (conditions de test non précisées).</p>
<p>Plusieurs API sont ainsi mises à disposition afin de connecter ces différents types de clients à un broker Diffusion, parmi lesquelles :</p>
<ul>
<li>Navigateur : JavaScript, Flash, Silverlight,</li>
<li>Client mobile : Android, iOS, Windows Phone, J2ME</li>
<li>Client lourd : Java, .Net</li>
</ul>
<p>Les protocoles disponibles sont les suivants :</p>
<ul>
<li>Web Socket</li>
<li>Flash socket</li>
<li>Silverlight socket</li>
<li>XmlHttpRequest (HTTP Callback ou IFrame + long polling)</li>
<li>RTMP (streaming de médias)</li>
</ul>
<p>L’API JavaScript se différencie des autres API disponibles car elle possède un mécanisme de « fallback » : elle est capable de permuter parmi les 5 protocoles disponibles en fonction de la nature du client et de la connectivité disponible. Ce choix est donc transparent à la fois pour l’utilisateur et pour le développeur.</p>
<h1>2. Focus sur Internet Message Broker</h1>
<p>Comment fonctionne Diffusion et comment utiliser les différentes API mises à disposition afin d’implémenter rapidement une solution basée sur du web messaging ? Ouvrons un peu plus le capot…</p>
<h2>2.1. Architecture</h2>
<p>Le schéma ci-après présente le schéma général d’une architecture Diffusion :</p>
<p style="text-align: center;"><a href="http://blog.octo.com/wp-content/uploads/2011/07/Diffusion.png"><img class="size-medium wp-image-23934 aligncenter" title="Diffusion" src="http://blog.octo.com/wp-content/uploads/2011/07/Diffusion-300x261.png" alt="" width="300" height="261" /></a></p>
<p>On distingue trois couches :</p>
<ul>
<li>Les sources de message ou d’événement (en haut du schéma)</li>
<li>La centralisation, le traitement et la distribution de ces messages (la couche Diffusion Message Broker)</li>
<li>Les consommateurs de message (la couche Diffusion Clients)</li>
</ul>
<p>Nous allons détailler ces différentes couches dans ce qui suit.</p>
<h2>2.2. Concepts</h2>
<p>Dans son implémentation la plus simple, une architecture Diffusion est constituée de <strong><em>Topics</em></strong>, de <strong><em>Publishers</em></strong> et de <strong><em>Clients</em></strong>. Transitent entre ces acteurs des <strong><em>TopicMessages</em></strong>, qui peuvent être routés de manière avancée grâce à différents <strong>mécanismes</strong>.</p>
<h3>2.2.1. Le socle <em>Topic</em>, <em>Publisher</em>, <em>Client</em></h3>
<p>Les <strong><em>Topics</em></strong> sont des fils de messages sur lesquelles il est possible de publier. Ils peuvent être hiérarchisés en sous <em>Topics</em>. Ainsi, un message publié à la racine d’un arbre sera diffusé dans toutes ses branches, autrement dit dans chacun des sous <em>Topics</em>.</p>
<p>Les <em>Topics</em> peuvent être déclarés :</p>
<ul>
<li>Par configuration, lors du déploiement d’un serveur Diffusion</li>
<li>Programmatiquement (dans le code des « <em>Publisher</em> », voir ci-après)</li>
</ul>
<p>Les <strong><em>Publisher</em></strong> sont garants d’un ou plusieurs <em>Topics</em> mais également des <em>Clients</em> y souscrivant. Ils ont pour rôle de traiter les nouveaux messages et leur diffusion auprès d’un, plusieurs ou la totalité des clients ayant souscrit au <em>Topic</em>. Un <em>Publisher</em> peut être de deux types :</p>
<ul>
<li><em>internal</em> : ils sont alors déployés au sein du serveur Diffusion. C’est la forme de Publisher recommandée.</li>
<li><em>external</em> : ils sont alors déployés à l’extérieur d’une instance Diffusion et s’enregistrent auprès des serveurs Diffusion disponibles. Leur utilisation peut être justifiée par des besoins fonctionnelles ou techniques.</li>
</ul>
<p>Ils ont donc à leur charge la transmission des nouveaux messages vers tout ou partie des clients ayant souscrit au <em>Topic</em>.</p>
<p>Les <strong><em>Clients</em></strong> se connectent sur un serveur Diffusion et s’inscrivent à un ou plusieurs <em>Topics</em>. Ils reçoivent ainsi tous les messages dès lors qu’ils sont publiés sur ces derniers, mais ils peuvent également en publier de nouveaux : la chaine de transmission des messages est bidirectionnelle.</p>
<p>Chaque <em>Client</em> possède sa propre pile de messages au sein d’une instance Diffusion. Cette pile est de type FIFO. Elle est alimentée par les <em>Publishers</em> et continuellement déchargée à destination du <em>Client</em>.</p>
<h3>2.2.2. Les TopicMessages<em></em></h3>
<p>Un <strong><em>TopicMessage</em></strong> est l’implémentation des messages échangés entre les différents acteurs. Il se compose de <em>fixed headers</em> (utilisés par Diffusion pour sa mécanique interne), de <em>user headers</em> et d’un bloc <em>user data</em> (zone libre du message pour l’utilisateur).</p>
<p>Le contenu d’un message est binaire. Diffusion propose une hiérarchisation des données en deux niveaux grâce à des <em>records, des fields</em> et des <em>delimiters</em>. Ces <em>delimiters</em> sont en réalité de simples caractères ASCII, permettant de sérialiser simplement les données.</p>
<p>Il est possible d’utiliser des métadonnées afin de décrire les différents champs composants un message. Ces métadonnées permettent également de faire de la validation et de la transformation des données. Elles ne sont pas transmises avec le message et devront donc être connues à l’avance par les différents lecteurs du message.</p>
<p>Un <em>TopicMessage</em> existe sous deux formes :</p>
<ul>
<li><strong><em>Load message</em></strong> : reçu par le client lors de la souscription à un <em>Topic</em>. Il permet généralement d’initialiser un contexte</li>
<li><strong><em>Delta message</em></strong> : utilisé après le <em>LoadMessage</em>, il permet de transmettre toutes les mises à jour du contexte</li>
</ul>
<p>Il peut également avoir trois états :</p>
<ul>
<li><em>Normal </em>: le message est ajouté sur la pile de chacun des Clients</li>
<li><em>Expedited </em>: c’est un message prioritaire, il est ajouté au début de chaque pile (de chaque client) ayant souscrits au <em>Topic</em>. Il est donc le suivant à partir.</li>
<li><em>R</em><em>equiring acknowledegement </em>: ce message requiert un acquittement de la part de son destinataire. Si le message n’a pas été acquitté, il est placé dans une file dédiée et le <em>publisher</em> est alors notifié.</li>
</ul>
<p>Aux différents acteurs étant en mesure de publier sur un <em>Topic</em>, nous pouvons ajouter <em>l’<strong>EventPublisher</strong></em>. Il permet d’implémenter facilement des sources <strong>externes</strong> d’événements, directement connectées à un ou plusieurs <em>Topics</em> via un <em>Publisher</em>. Il peut s’intégrer à n’importe quel applicatif Java ou .Net grâce aux deux API mises à disposition.</p>
<h3>2.2.3. Mécanismes avancés de traitement de files</h3>
<p>Diffusion propose une gestion avancée des files de messages, avec entre autre les mécanismes suivants :</p>
<ul>
<li>La <strong>conflation </strong>: correspond aux messages dupliqués ou similaires au sein d’une file. Il ainsi possible de définir des règles de comparaison de message permettant d’éviter ce genre de situation. En plus d’offrir une information plus pertinente aux clients, cette technique permet de réduire le trafic sur le réseau, en évitant l&#8217;envoie de messages inutiles car déjà obsolète.</li>
<li>Le <strong>throttling </strong>: correspond à la capacité de temporiser (bufferiser) les messages avant leur envoi vers le Client. Cette technique permet de contrôler la bande passante. Il est possible de régler le throttling pour chaque client selon 3 critères :
<ul>
<li>le nombre de message par seconde</li>
<li>le nombre d’octet par seconde</li>
<li>l’intervalle de temps entre chaque message.</li>
</ul>
</li>
</ul>
<h2>3. Conclusion</h2>
<p>L’architecture et les mécanismes de Diffusion ne divergent pas tellement de celle d’un autre Message-Oriented Middleware, et les habitués retrouveront rapidement leurs marques. L’intérêt est ici de pouvoir connecter facilement un grand nombre de clients web, quel qu’en soit leur nature, à des files de messages.</p>
<p>Dans la seconde partie, nous aborderons, autour d’un use-case simple, les bases permettant de mettre en œuvre un navigateur connecté recevant des informations en temps réel depuis un serveur Diffusion.</p>
<p>&nbsp;</p>

 <img src="http://blog.octo.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=23931" width="1" height="1" style="display: none;" /><p>Suggestion d'articles :</p><ol>
<li><a href='http://blog.octo.com/le-push-web-vu-par-diffusion-partie-2/' rel='bookmark' title='Le push web vu par Diffusion &#8211; Partie 2'>Le push web vu par Diffusion &#8211; Partie 2</a></li>
<li><a href='http://blog.octo.com/le-push-web-avec-pusher/' rel='bookmark' title='Le push web avec Pusher'>Le push web avec Pusher</a></li>
<li><a href='http://blog.octo.com/securite-des-services-web-1ere-partie/' rel='bookmark' title='Sécurité des services web – 1ère partie'>Sécurité des services web – 1ère partie</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.octo.com/le-push-web-vu-par-diffusion-partie-1/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Pourquoi les Websockets ?</title>
		<link>http://blog.octo.com/pourquoi-les-websockets/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=pourquoi-les-websockets</link>
		<comments>http://blog.octo.com/pourquoi-les-websockets/#comments</comments>
		<pubDate>Thu, 15 Jul 2010 07:19:17 +0000</pubDate>
		<dc:creator>David Rousselie</dc:creator>
				<category><![CDATA[Architecture et technologies]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[Comet]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[Push]]></category>
		<category><![CDATA[WebSocket]]></category>

		<guid isPermaLink="false">http://blog.octo.com/?p=12763</guid>
		<description><![CDATA[Après la démocratisation d&#8217;Ajax (ie. requêtes HTTP asynchrones en Javascript), plusieurs techniques ont été élaborées afin de permettre le push de données depuis le serveur toujours en utilisant HTTP. C&#8217;est grâce à ces techniques que l&#8217;on reçoit nos mails dans une application web sans avoir à cliquer sur le bouton &#171;&#160;Refresh&#160;&#187;, que les applications de [...]
Suggestion d'articles :<ol>
<li><a href='http://blog.octo.com/jetty-html-5-les-websockets-sont-la/' rel='bookmark' title='Jetty &amp; HTML 5: les WebSockets sont là !'>Jetty &#038; HTML 5: les WebSockets sont là !</a></li>
<li><a href='http://blog.octo.com/des-telephones-mobiles-connectes-a-internet-pourquoi-faire/' rel='bookmark' title='Des téléphones mobiles connectés à internet. Pourquoi faire ?'>Des téléphones mobiles connectés à internet. Pourquoi faire ?</a></li>
<li><a href='http://blog.octo.com/dynamocracy-pourquoi/' rel='bookmark' title='Dynamocracy : pourquoi ?'>Dynamocracy : pourquoi ?</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fblog.octo.com%252Fpourquoi-les-websockets%252F%22%2C%20%22style%22%3A%20%22small%22%2C%20%22title%22%3A%20%22Pourquoi%20les%20Websockets%20%3F%22%20%7D);"></div>
<p>Après la démocratisation d&#8217;Ajax (ie. requêtes HTTP asynchrones en Javascript), <a href="http://blog.octo.com/apres-ajax-le-reverse-ajax-et-le-grizzly/">plusieurs techniques</a> ont été élaborées afin de permettre <strong>le push de données</strong> depuis le serveur toujours en utilisant HTTP. C&#8217;est grâce à ces techniques que l&#8217;on reçoit nos mails dans une application web sans avoir à cliquer sur le bouton &laquo;&nbsp;Refresh&nbsp;&raquo;, que les applications de chat sont possibles sans plugin tierce (Flash, Java, &#8230;), etc. Le W3C et l&#8217;IETF ont spécifié une <a href="http://dev.w3.org/html5/websockets/">API Javascript</a> et un protocole nommé <a href="http://www.whatwg.org/specs/web-socket-protocol/">Websocket</a>. Ce protocole <strong>connecté est adapté à l&#8217;envoi de données dans les deux sens</strong> et évite de <strong>détourner HTTP de son usage initial</strong> (ie. un protocole déconnecté sans état).<br />
<span id="more-12763"></span></p>
<h2>Le protocole Websocket, HTTP et les proxys</h2>
<p><strong>Websocket n&#8217;est donc pas une spécification des techniques de push sur HTTP</strong> (long polling, HTTP Streaming, &#8230;), <strong>ni une surcouche à HTTP</strong> mais bien <strong>un protocole à part entière</strong>.<br />
<strong>Il reste pourtant lié à HTTP en réutilisant l&#8217;architecture réseau de celui-ci</strong>. En effet, l&#8217;ouverture d&#8217;une connexion Websocket s&#8217;effectue avec une requête HTTP qui demande au serveur &laquo;&nbsp;de mettre à jour la connexion&nbsp;&raquo; en connexion Websocket.</p>
<pre>
GET /demo HTTP/1.1
Host: example.com
Connection: Upgrade
Sec-WebSocket-Key2: 12998 5 Y3 1  .P00
Sec-WebSocket-Protocol: sample
Upgrade: WebSocket
Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5
Origin: http://example.com

^n:ds[4U
</pre>
<p>Le serveur, s&#8217;il supporte le protocole Websocket, peut ainsi terminer l&#8217;ouverture de la connexion et la suite du dialogue entre le client et le serveur s&#8217;effectuera avec le protocole Websocket.</p>
<pre>
HTTP/1.1 101 WebSocket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
Sec-WebSocket-Origin: http://example.com
Sec-WebSocket-Location: ws://example.com/demo
Sec-WebSocket-Protocol: sample

8jKS'y:G*Co,Wxa-
</pre>
<p>Ce type d&#8217;ouverture de connexion permet de <strong>réutiliser le port HTTP</strong> (ou HTTPS) classiquement utilisé et <strong>de passer les proxys comme une simple requête HTTP</strong>. Cependant, <strong>certains proxy n&#8217;autorisant pas les connexions longues risquent de poser problème en coupant les connexions Websocket</strong>.<br />
Avec la démocratisation du protocole Websocket, on peut cependant espérer que ce type de proxy disparaîtra peu à peu.<br />
L&#8217;utilisation de Websocket sécurisé (wss:// dans l&#8217;URL au lieu de ws://) permet d&#8217;augmenter les chances de passer à travers ces proxys peu coopératifs. En effet, si un proxy est explicitement configuré dans le navigateur, les implémentations actuelles de Websocket utilisent des tunnels via HTTP CONNECT de la même façon que HTTPS. La connexion n&#8217;est ainsi plus différentiable d&#8217;une connexion HTTPS du point de vue des proxys.</p>
<h2>Le support des Websockets</h2>
<h3>Le support par les navigateurs</h3>
<p>Comme pour les autres fonctionnalités qui viennent avec HTML5, <strong>les Websockets ne sont pas supportées par tous les navigateurs</strong> :</p>
<ul>
<li>Chrome les supporte depuis sa version 4.0.429</li>
<li>Safari depuis la version 5.0</li>
</ul>
<p>Quant aux autres navigateurs, ils ne les supportent tout simplement pas encore.</p>
<p>Pour pallier à ce manque temporaire, deux approches ont été implémentées :</p>
<ul>
<li><strong>un wrapper Javascript client qui bascule sur une implémentation Flash</strong> (qui est capable d&#8217;ouvrir des sockets TCP). Cette solution permet de garder tous les avantages des Websockets mais ajoute une dépendance vers le Player Flash,</li>
<li><strong>un wrapper Javascript client qui bascule sur du long polling ou HTTP Streaming</strong>. Cette fois-ci, plus de dépendance vers le Player Flash mais on revient vers une émulation du push avec HTTP.</li>
</ul>
<h3>Le support côté serveur</h3>
<p>Côté serveur, il faut distinguer deux types de composants (dans le monde Java) :</p>
<ul>
<li><strong>les implémentations du protocole Websocket</strong> comme <a href="http://www.jboss.org/netty">Netty</a>, <a href="https://grizzly.dev.java.net/">Grizzly</a>, <a href="http://www.eclipse.org/jetty/">Jetty 7</a> (l&#8217;<a href="http://blog.octo.com/jetty-html-5-les-websockets-sont-la/">article de Xavier</a> montre comment utiliser les Websockets avec Jetty 7), <a href="http://jwebsocket.org/">JWebSocket</a> (et son implémentation TCP), <a href="http://www.kaazing.org">Kaazing</a>, &#8230; Ces implémentations proposent une API plus (Jetty) ou moins (Kaazing) bas niveau pour exploiter les fonctionnalités du push serveur.</li>
<li><strong>les frameworks qui proposent une API de plus haut niveau et qui s&#8217;appuient sur les implémentations précédentes</strong>. On retrouve ainsi <a href="https://atmosphere.dev.java.net/">Atmoshpere</a>, <a href="http://cometd.org/">Cometd</a> (en version 2) ou encore <a href="http://jwebsocket.org/">JWebSocket</a>. Ces frameworks proposent donc <strong>une API indépendante de l&#8217;implémentation WebSocket sous-jacente</strong> (d&#8217;ailleurs, Atmosphere était avant tout une implémentation de Comet).</li>
</ul>
<p>Cette distinction ne veut cependant pas dire que les frameworks implémentant le protocole Websocket sont forcément de plus bas niveau que Atmosphere ou JWebSocket. Par exemple, Kaazing propose des fonctionnalités et une API d&#8217;au moins aussi haut niveau que celle de JWebSocket.</p>
<h2>Pourquoi (pas) les Websockets ?</h2>
<p>Au-dela de pouvoir pousser des données du serveur vers le client, encore faut-il pouvoir l&#8217;exploiter sans passer son temps dans la plomberie. C&#8217;est bien de pouvoir réagir à une connexion, un message, une déconnexion, &#8230; mais il faut gérer les clients connectés, les timeouts des connexions (le client ne connait pas le timeout après lequel le serveur coupe la connexion), savoir quels messages renvoyer lorsqu&#8217;une coupure de connexion survient et <a href="http://blogs.webtide.com/gregw/entry/websocket_chat">autres limitations du fait de la jeunesse du protocole Websocket</a>.</p>
<p>Là encore <strong>les frameworks comme Kaazing, JWebsocket ou Cometd sont bien utiles pour s&#8217;occuper de ces problématiques bas niveau</strong> mais aussi pour proposer des fonctionnalités utilisant tout le potentiel des Websockets.</p>
<p>Parmi celles-ci, on peut trouver :</p>
<ul>
<li>du publish subscribe</li>
<li>du RPC (Remote Procedure Call) et RRPC (Reverse Remote Procedure Call) pour que le serveur puisse appeler des services du client</li>
<li>des passerelles vers des protocoles connectés comme JMS, JDBC, Jabber, IMAP, &#8230;</li>
<li>bus événementiel</li>
</ul>
<p>Enfin, il est légitime de se dire que toutes ces fonctionnalités sont envisageables avec des techniques comme Comet sur HTTP. Alors pourquoi préférer les Websockets alors que leur support par les navigateurs est encore limité et que les proxys risquent de ne pas toujours jouer le jeu ?</p>
<p>Tout d&#8217;abord, lorsqu&#8217;on utilise du polling ou tout autre technique sur HTTP, on utilise forcément <strong>une connexion dédiée pour recevoir des données poussées du serveur vers le client</strong> et <strong>une autre connexion pour envoyer des données depuis le client</strong> (via une requête HTTP classique). <strong>Une connexion Websocket, quant à elle, est full duplex</strong>. C&#8217;est à dire que la même connexion est utilisée pour recevoir et envoyer des données. Le serveur gère donc moins de connexions ouvertes et moins d&#8217;ouvertures et fermetures de connexions ponctuelles. Il faut cependant souligner que <strong>les implémentations serveur doivent être adaptées à la gestion d&#8217;un grand nombre de connexions simultanées et continues</strong> (<a href="http://www.kegel.com/c10k.html">utilisation d&#8217;un pool de threads plutôt qu&#8217;un thread par socket ouverte, entrées-sorties non bloquantes, notifications par l&#8217;OS de l&#8217;activité des sockets</a>, &#8230;), que ce soit en utilisant Comet ou les Websockets.</p>
<p>Ensuite, en terme de bande passante, <strong>la taille du message minimum du protocole WebSocket est de 2 octets</strong> (0&#215;00 pour le début du message et 0xFF pour la fin). <strong>Avec HTTP, il faut compter au moins 200 octets pour un header</strong>. Quand il s&#8217;agit d&#8217;envoyer des messages de maintient de connexions (ou de réouverture de connexion avec Comet), avec un nombre important de clients connectés, <strong>l&#8217;occupation de la bande passante avec Comet devient non négligeable</strong>.</p>
<h2>Conclusion</h2>
<p>Le protocole Websocket est donc un moyen de répondre au besoin de push de données depuis le serveur qui était jusque-là implémenté en détournant HTTP de son usage prévu initialement. Il permet ainsi d&#8217;optimiser l&#8217;usage des resources côté serveur et de faire le pont entre une architecture web (ie. centrée autour de HTTP et des navigateurs Internet) et les autres protocoles connectés (JMS, IMAP, Jabber, &#8230;) ouvrant ainsi la porte au web &laquo;&nbsp;temp réel&nbsp;&raquo;.</p>

 <img src="http://blog.octo.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=12763" width="1" height="1" style="display: none;" /><p>Suggestion d'articles :</p><ol>
<li><a href='http://blog.octo.com/jetty-html-5-les-websockets-sont-la/' rel='bookmark' title='Jetty &amp; HTML 5: les WebSockets sont là !'>Jetty &#038; HTML 5: les WebSockets sont là !</a></li>
<li><a href='http://blog.octo.com/des-telephones-mobiles-connectes-a-internet-pourquoi-faire/' rel='bookmark' title='Des téléphones mobiles connectés à internet. Pourquoi faire ?'>Des téléphones mobiles connectés à internet. Pourquoi faire ?</a></li>
<li><a href='http://blog.octo.com/dynamocracy-pourquoi/' rel='bookmark' title='Dynamocracy : pourquoi ?'>Dynamocracy : pourquoi ?</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.octo.com/pourquoi-les-websockets/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Après Ajax, le « Reverse Ajax »…et le Grizzly !</title>
		<link>http://blog.octo.com/apres-ajax-le-reverse-ajax-et-le-grizzly/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=apres-ajax-le-reverse-ajax-et-le-grizzly</link>
		<comments>http://blog.octo.com/apres-ajax-le-reverse-ajax-et-le-grizzly/#comments</comments>
		<pubDate>Thu, 04 Sep 2008 09:43:25 +0000</pubDate>
		<dc:creator>Olivier Mallassi</dc:creator>
				<category><![CDATA[Architecture et technologies]]></category>
		<category><![CDATA[Comet]]></category>
		<category><![CDATA[Grizzly]]></category>
		<category><![CDATA[Reverse Ajax]]></category>
		<category><![CDATA[RIA]]></category>

		<guid isPermaLink="false">http://new-blog.octo.com/2008/09/04/apres-ajax-le-reverse-ajax-et-le-grizzly/</guid>
		<description><![CDATA[<blockquote dir="ltr" style="MARGIN-RIGHT: 0px"> <p>- " Encore plus fort ! ce n'est plus ton browser qui demande de l'information. C'est ton serveur qui lui remonte, lui push de l'information et le tout en technologie web ! "<br />- " oulà, oulà...tu ne serai pas en train de me prendre pour un gars sorti de sa campagne toi ?! "</p> </blockquote> <p dir="ltr">En fait, si un peu mais pas tant que ca non plus ;-)<br /></p>
Suggestion d'articles :<ol>
<li><a href='http://blog.octo.com/et-apres-ria/' rel='bookmark' title='Et après RIA?'>Et après RIA?</a></li>
<li><a href='http://blog.octo.com/5-minutes-pour-monter-en-complexite-approche-tdd-tests-en-php-php-amp-ajax/' rel='bookmark' title='5 minutes pour : Monter en complexité, Approche TDD / Tests en PHP, PHP &amp; Ajax'>5 minutes pour : Monter en complexité, Approche TDD / Tests en PHP, PHP &#038; Ajax</a></li>
<li><a href='http://blog.octo.com/pourquoi-les-websockets/' rel='bookmark' title='Pourquoi les Websockets ?'>Pourquoi les Websockets ?</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fblog.octo.com%252Fapres-ajax-le-reverse-ajax-et-le-grizzly%252F%22%2C%20%22style%22%3A%20%22small%22%2C%20%22title%22%3A%20%22Apr%C3%A8s%20Ajax%2C%20le%20%C2%AB%20Reverse%20Ajax%20%C2%BB%E2%80%A6et%20le%20Grizzly%20%21%22%20%7D);"></div>
<blockquote style="MARGIN-RIGHT: 0px" dir="ltr"><p>- &nbsp;&raquo; Encore plus fort ! ce n&#8217;est plus ton browser qui demande de l&#8217;information. C&#8217;est ton serveur qui lui remonte, lui push de l&#8217;information et le tout en technologie web ! &nbsp;&raquo;<br />
- &nbsp;&raquo; oulà, oulà&#8230;tu ne serai pas en train de me prendre pour un gars sorti de sa campagne toi ?! &laquo;&nbsp;</p></blockquote>
<p dir="ltr">En fait, si un peu mais pas tant que ca non plus ;-)</p>
<p><span id="more-115"></span></p>
<p>Le besoin est réel et tend à se démocratiser sur le web : informer l&#8217;utilisateur de la modification d&#8217;information au niveau du serveur, en (quasi) temps réel. Les cas d&#8217;utilisations sont tout autant réels. Les exemples classiques sont Gmail et Gtalk. L&#8217;iphone 3G en a fait un argument publicitaire. Des applications d&#8217;alarming ou de monitoring en web peuvent en avoir l&#8217;utilité, les plateformes de &nbsp;&raquo; e-trading &nbsp;&raquo; ou certaines applications de call-center également.</p>
<p>Il existe 3 solutions pour &nbsp;&raquo; remonter &nbsp;&raquo; de l&#8217;information au client</p>
<table border="0" cellspacing="1" cellpadding="1" >
<tbody>
<tr>
<td valign="middle">Le <strong>poll</strong>. Dans ce cas, la remontée d&#8217;information du serveur vers le client est simulée. En effet, dans le cas du poll ou pull, le client exécute une requête vers son serveur à intervalle de temps régulier, espérant ainsi être mis au courant d&#8217;une mise à jour.<br />
Cette approche montre les limitations suivantes : </p>
<ul>
<li>Certains évènements peuvent être manqués si l&#8217;intervalle entre deux requêtes est trop long</li>
<li>A l&#8217;inverse, il est tout à fait possible de réaliser un appel &nbsp;&raquo; à vide &nbsp;&raquo; si aucun évènement n&#8217;est disponible</li>
<li>Un intervalle de temps trop court entre deux requêtes aura tendance à (sur)charger le serveur</li>
</ul>
</td>
<td valign="top"><img src="/wp-content/uploads/images/poll.jpg" alt="" width="293" height="259" /></td>
</tr>
<tr>
<td valign="middle">Le <strong>Streaming http</strong>. A l&#8217;exact opposé du poll, le streaming http repose sur l&#8217;utilisation de connexion http persistantes, ie. qui ne sont jamais relâchés. Les informations de réponse sont écrites au fur et à mesure de leurs arrivées. Très usitée par les applications multimedia (vidéo, audio&#8230;), la mise en oeuvre de cette solution demande néanmoins une infrastructure adaptée aux connexions permanentes et il n&#8217;est pas évident que tous les proxys (en entreprise surtout) l&#8217;accepte.</td>
<td><img src="/wp-content/uploads/images/httpstreaming.jpg" alt="" width="295" height="261" /></td>
</tr>
<tr>
<td valign="middle">Le <strong>Reverse Ajax ou Comet</strong>. A mi chemin entre les précédentes solutions, les termes &nbsp;&raquo; Comet &nbsp;&raquo; et son synonyme &nbsp;&raquo; Reverse Ajax &nbsp;&raquo; ont été introduit Alex Russel et Joe Walker et décrivent un mode de fonctionnement où le serveur &nbsp;&raquo; remonte &nbsp;&raquo; de l&#8217;information au client sans que ce dernier ne l&#8217;ait expressément demandée. Ce mode de fonctionnement est en fait basé sur le principe du poll sauf que la requête http peut rester en attente, d&#8217;un évènement ou du timeout, auquel cas, cette dernière se &nbsp;&raquo; clôt &nbsp;&raquo; classiquement.<br />
Ce mécanisme de long-polling repose &#8211; et cela de manière à assurer la scalabilité &#8211; sur le découplage des notions de requêtes http et des notions de Threads : il faut être capable de mettre en attente certains clients http, tout en exécutant des services &#8211; donc des threads &#8211; sans pour autant avoir autant de threads que de clients http potentiels&#8230;bref, vu d&#8217;avion ca n&#8217;a déjà pas l&#8217;air simple&#8230;</td>
<td valign="top"><img src="/wp-content/uploads/images/comet.jpg" alt="" width="303" height="207" /> </p>
<p> </td>
</tr>
</tbody>
</table>
<p>L&#8217;élément différentiant entre ces solutions reste la <strong>fréquence de mise à jour de la donnée</strong> et<strong> l&#8217;importance qu&#8217;à la fraîcheur de cette donnée</strong> pour le client.</p>
<h3>Comet ou le &laquo;&nbsp;long polling&nbsp;&raquo;</h3>
<blockquote><p>In web development, Comet is a neologism to describe a web application model in which a long-held HTTP request allows a web server to push data to a browser, without the browser explicitly requesting it</p></blockquote>
<blockquote style="MARGIN-RIGHT: 0px" dir="ltr">
<blockquote style="MARGIN-RIGHT: 0px" dir="ltr">
<blockquote style="MARGIN-RIGHT: 0px" dir="ltr">
<blockquote style="MARGIN-RIGHT: 0px" dir="ltr">
<blockquote style="MARGIN-RIGHT: 0px" dir="ltr">
<blockquote style="MARGIN-RIGHT: 0px" dir="ltr">
<blockquote style="MARGIN-RIGHT: 0px" dir="ltr">
<blockquote style="MARGIN-RIGHT: 0px" dir="ltr"><p>Source: <a href="http://en.wikipedia.org/wiki/Comet_(programming)">wikipedia</a></p></blockquote>
</blockquote>
</blockquote>
</blockquote>
</blockquote>
</blockquote>
</blockquote>
</blockquote>
<p>Contrairement à ce que peut laisser penser la première partie, cette problématique de &nbsp;&raquo; long-polling &nbsp;&raquo; impacte à la fois le client et le serveur :</p>
<ul>
<li>Le client car il faut gérer l&#8217;ouverture et surtout la réouverture des connexions http &#8211; lors de la fermeture normale ou du timeout -.</li>
<li>Le serveur car il faut gérer ces histoires de long polling et de découplage requête/thread sans avoir à trop mettre les mains dans le cambouis&#8230;</li>
</ul>
<p>Il existe aujourd&#8217;hui plusieurs solutions open source implémentant les concepts de Comet. La plupart de ces solutions adressent &nbsp;&raquo; uniquement &nbsp;&raquo; &#8211; en même temps c&#8217;est déjà beaucoup&#8230; &#8211; la partie serveur, et ce de manière plus ou moins light en terme d&#8217;APIs proposées :</p>
<ul>
<li>Tomcat 6 propose les NIO &#8211; <a href="http://tomcat.apache.org/tomcat-6.0-doc/aio.html ">advanced IO</a>. Côté code, Tomcat propose uniquement une interface CometProcessor que devra implémenter votre servlet. A vous de jouer avec les threads pour écrire les messages sur les HttpServletResponse souhaitées. La configuration de ces Advanced IO, sans être insurmontable n&#8217;est pas immédiate : il est nécessaire de modifier la configuration du connecteur http au niveau du fichier server.xml et de rajouter une dll dans la variable java.library.path</li>
<li>Jetty 6 propose une API un peu plus haut niveau que celle de Tomcat. Jetty introduit ainsi le concept de <a href="http://docs.codehaus.org/display/JETTY/Continuations">continuations</a>, un objet appelable depuis une servlet et qui permet de suspendre la requête http en cours et de libérer le thread courant.</li>
<li><a href="http://cometdproject.dojotoolkit.org/">DOJO</a> et le protocole de Bayeux. DOJO est l&#8217;initiateur du protocole de Bayeux &#8211; j&#8217;avoue ne pas avoir trouver de relation avec la ville de <a href="http://fr.wikipedia.org/wiki/Bayeux">Bayeux</a> et ces <a href="http://fr.wikipedia.org/wiki/Tapisserie_de_Bayeux">tapisseries</a>, en même temps il n&#8217;y a certainement aucune relation&#8230;Bref, Dojo propose une API cliente JavaScript permettant d&#8217;interagir avec un serveur implémentant ce fameux protocole de Bayeux. Glassfish &#8211; via Grizzly &#8211; étant un des serveurs implémentant ce protocole, il est tout à fait possible d&#8217;imaginer un client utilisant DOJO et s&#8217;interfaçant avec Glassfish.</li>
<li><a href="https://grizzly.dev.java.net/">Grizzly</a>/<a href="https://glassfish.dev.java.net/">Glassfish</a>. Glassfish dans sa version 3 embarque le moteur http Grizzly et propose une solution &nbsp;&raquo; out of the box &laquo;&nbsp;. Ce moteur propose un support de comet soit via
<ul>
<li>Une implémentation du protocole de Bayeux.</li>
<li>Une API masquant les mécanismes &nbsp;&raquo; <a href="http://weblogs.java.net/blog/jfarcand/archive/2006/02/grizzly_part_ii.html">Asynchronous Request Processing</a> &nbsp;&raquo; disponible dans Grizzly.La mise en oeuvre de comet dans glassfish est simplissime et consiste à modifier le fichier domain.xml.</li>
</ul>
</li>
</ul>
<p>Certaines solutions de développement &#8211; a contrario des solutions portées par le serveur d&#8217;application ou le conteneur de servlet présentés précédemment &#8211; intègrent cette problématique :</p>
<ul>
<li>Côté GWT, on peut noter l&#8217;initiative <a href="http://code.google.com/p/rocket-gwt/wiki/Comet">Rocket/GWT</a> qui encapsule ces problématiques dans des APIs java client et serveur</li>
<li>Côté Flex, Adobe BlazeDS (et son équivalent payant) propose des mécanismes de &nbsp;&raquo; push serveur &laquo;&nbsp;. Le principe réside dans la définition de &nbsp;&raquo; channel &nbsp;&raquo; auxquels s&#8217;abonnent et publient les clients</li>
<li>Côté JSF, IceFaces annonce une solution de &nbsp;&raquo; push server &nbsp;&raquo; alors que jBoss RichFaces ne fournit que le poll</li>
</ul>
<h3>Le protocole de Bayeux : une tentative de standardisation des échanges type &nbsp;&raquo; push &laquo;&nbsp;</h3>
<p>Le <a href="http://svn.xantus.org/shortbus/trunk/bayeux/bayeux.html">protocole de Bayeux</a>, poussé par DOJO, vise une normalisation permettant de délivrer des évènements, au format JSON, entre des clients et un serveur, des clients et des clients (via le serveur..),  sur la base du modèle publish/subscribe.</p>
<p>Ce protocole repose &nbsp;&raquo; principalement &nbsp;&raquo; sur :</p>
<ul>
<li>La notion de &nbsp;&raquo; channel &laquo;&nbsp;, une destination déterminée par un nom logique (ou plus exactement une uri) sur laquelle seront poussés des messages, eux-mêmes consommés par les clients ayant souscris à ce channel. Formuler autrement, ce &nbsp;&raquo; channel &nbsp;&raquo; peut être vu comme le sujet de conversation que les clients vont partager. Ce protocole définit de plus des &nbsp;&raquo; channels &nbsp;&raquo; techniques pour gérer l&#8217;abonnement et le désabonnement des clients&#8230;</li>
<li>Les messages encodés en JSON et proposant quelques propriétés intéressantes comme le channel, un identifiant unique du client&#8230;</li>
</ul>
<p>Ainsi dans ce protocole, un exemple de message est :</p>

<div class="wp_codebox"><table><tr id="p1151"><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code" id="p115code1"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">/*[{&quot;channel&quot;:&quot;/cometd/myChannel&quot;,&quot;successful&quot;:true,&quot;clientId&quot;:&quot;2d714396f339f90d&quot;,&quot;id&quot;:&quot;6&quot;},
{&quot;channel&quot;:&quot;/cometd/myChannel&quot;,&quot;data&quot;:{&quot;test&quot;:&quot;one 
message&quot;},&quot;id&quot;:&quot;6&quot;,&quot;clientId&quot;:&quot;2d714396f339f90d&quot;}]*/</span></pre></td></tr></table></div>

<p>Ce protocole ne définit pas d&#8217;API cliente ou serveur mais décrit seulement les mécanismes d&#8217;échanges entre serveur et clients dans le cadre d&#8217;échange de type &nbsp;&raquo; push &laquo;&nbsp;.</p>
<h3>Mise en oeuvre&#8230;</h3>
<h4>&#8230;avec les APIs Grizzly/glassfish</h4>
<p>Loin de moi l&#8217;envie de vous refaire un tutorial complet sur Grizzly. Reste que ces APIs sont assez simples et proposent les principaux concepts suivants :</p>
<ul>
<li><em>CometEngine</em>. C&#8217;est par la que tout commence et ce moteur permet de gérer des CometContext</li>
<li><em>CometContext</em>. Cet objet CometContext est associé à une URL &#8211; en fait l&#8217;url où seront faits les GET et les POST&#8230; &#8211; et gère un ensemble de CometHandler</li>
<li><em>CometHandler</em>. On peut voir cet objet comme un &nbsp;&raquo; client &laquo;&nbsp;. Une nouvelle instance du CometHandler est associé au context lors de la méthode doGet() de votre servlet et tout ou partie de ces handlers sont notifiés sur le doPost()&#8230;</li>
</ul>
<p>En terme de code,  les APIs sont utilisées dans une servlet comme suit :</p>
<ul>
<li>Le CometContext est initialisé dans le méthode init() de votre servlet</li>
</ul>

<div class="wp_codebox"><table><tr id="p1152"><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code" id="p115code2"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> init<span style="color: #009900;">&#40;</span>ServletConfig config<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> ServletException <span style="color: #009900;">&#123;</span>... 
<span style="color: #006633;">CometEngine</span> engine <span style="color: #339933;">=</span> CometEngine.<span style="color: #006633;">getEngine</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
CometContext cometContext <span style="color: #339933;">=</span> engine.<span style="color: #006633;">register</span><span style="color: #009900;">&#40;</span>contextPath<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<ul>
<li>Un nouvel handler est instancié dans la méthode doGet(), donc pour chaque requête, et associé au CometContext. Chaque requête est ainsi mise en attente (regardez avec FireBugs ;-) )</li>
</ul>

<div class="wp_codebox"><table><tr id="p1153"><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code" id="p115code3"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000066; font-weight: bold;">void</span> doGet<span style="color: #009900;">&#40;</span>HttpServletRequest req, HttpServletResponse resp<span style="color: #009900;">&#41;</span>   <span style="color: #000000; font-weight: bold;">throws</span> ServletException, <span style="color: #003399;">IOException</span> <span style="color: #009900;">&#123;</span> 
    SampleCometHandler handler <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> SampleCometHandler<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
    handler.<span style="color: #006633;">attach</span><span style="color: #009900;">&#40;</span>resp<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
    CometContext context <span style="color: #339933;">=</span> CometEngine.<span style="color: #006633;">getEngine</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getCometContext</span><span style="color: #009900;">&#40;</span>contextPath<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>   
    context.<span style="color: #006633;">addCometHandler</span><span style="color: #009900;">&#40;</span>handler<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<ul>
<li>Lors d&#8217;un POST, le paramètre company est récupérer de la requête, l&#8217;ensemble des handlers associés au CometContext est notifié. A noter qu&#8217;il est possible dans ce cas de ne notifier qu&#8217;un seul handler (et donc un seul client)</li>
</ul>

<div class="wp_codebox"><table><tr id="p1154"><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code" id="p115code4"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000066; font-weight: bold;">void</span> doPost<span style="color: #009900;">&#40;</span>HttpServletRequest req, HttpServletResponse resp<span style="color: #009900;">&#41;</span>  <span style="color: #000000; font-weight: bold;">throws</span> ServletException, <span style="color: #003399;">IOException</span> <span style="color: #009900;">&#123;</span> 
    CometEngine engine <span style="color: #339933;">=</span> CometEngine.<span style="color: #006633;">getEngine</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
    CometContext context <span style="color: #339933;">=</span> engine.<span style="color: #006633;">getCometContext</span><span style="color: #009900;">&#40;</span>contextPath<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    context.<span style="color: #006633;">notify</span><span style="color: #009900;">&#40;</span>req.<span style="color: #006633;">getParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;company&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>  
...</pre></td></tr></table></div>

<ul>
<li>L&#8217;implémentation du handler peut se faire de la manière suivante. Lors de la notification, chaque handler écrit le CometEvent (ie. le message) sur la HttpServeltResponse qui lui est associée.</li>
</ul>

<div class="wp_codebox"><table><tr id="p1155"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code" id="p115code5"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">class</span> SampleCometHandler <span style="color: #000000; font-weight: bold;">implements</span>   CometHandler <span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> onEvent<span style="color: #009900;">&#40;</span>com.<span style="color: #006633;">sun</span>.<span style="color: #006633;">grizzly</span>.<span style="color: #006633;">comet</span>.<span style="color: #006633;">CometEvent</span> event<span style="color: #009900;">&#41;</span>    <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">IOException</span> <span style="color: #009900;">&#123;</span>   
    <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>event.<span style="color: #006633;">getType</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> CometEvent.<span style="color: #006633;">NOTIFY</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>    
    <span style="color: #666666; font-style: italic;">// le client a fait le post    </span>
    <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">response</span>.<span style="color: #006633;">getWriter</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">write</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;message: &quot;</span> <span style="color: #339933;">+</span> event.<span style="color: #006633;">attachment</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
    <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">response</span>.<span style="color: #006633;">getWriter</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">flush</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">// supprimer cette ligne pour faire du streaming</span>
    event.<span style="color: #006633;">getCometContext</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">resumeCometHandler</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Reste maintenant à implémenter un &nbsp;&raquo; petit &nbsp;&raquo; client, simplement en JavaScript et de la manière suivante :</p>
<ul>
<li>Une requête client réalise un GET et attend</li>
</ul>

<div class="wp_codebox"><table><tr id="p1156"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code" id="p115code6"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> doGet<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  <span style="color: #003366; font-weight: bold;">new</span> Ajax.<span style="color: #660066;">Request</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'/CometSample/CometSampleServlet'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span>
   method<span style="color: #339933;">:</span><span style="color: #3366CC;">'get'</span><span style="color: #339933;">,</span>
   onSuccess<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>transport<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
     $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'result'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">update</span><span style="color: #009900;">&#40;</span>transport.<span style="color: #660066;">responseText</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<ul>
<li>Un autre client poste son message</li>
</ul>

<div class="wp_codebox"><table><tr id="p1157"><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code" id="p115code7"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> doPost<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  <span style="color: #003366; font-weight: bold;">new</span> Ajax.<span style="color: #660066;">Request</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'/CometSample/CometSampleServlet'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span>
  method<span style="color: #339933;">:</span><span style="color: #3366CC;">'post'</span><span style="color: #339933;">,</span>
   parameters<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>company<span style="color: #339933;">:</span><span style="color: #3366CC;">'octo'</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
  onSuccess<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>transport<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>...<span style="color: #009900;">&#125;</span>
 <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<h4>&#8230;de l&#8217;implémentation Grizzly du protocole de bayeux</h4>
<p>Grizzly fournit une implémentation du protocole de Bayeux via une servlet &nbsp;&raquo; générique &nbsp;&raquo; qu&#8217;il est simplement nécessaire de configurer au niveau du fichier web.xml</p>

<div class="wp_codebox"><table><tr id="p1158"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code" id="p115code8"><pre class="xml" style="font-family:monospace;">&nbsp;
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;servlet<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;servlet</span> -name<span style="color: #000000; font-weight: bold;">&gt;</span></span>Grizzly Cometd Servlet<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;servlet</span> -class<span style="color: #000000; font-weight: bold;">&gt;</span></span>com.sun.grizzly.cometd.servlet.CometdServlet<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;init</span> -param<span style="color: #000000; font-weight: bold;">&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;param</span> -name<span style="color: #000000; font-weight: bold;">&gt;</span></span>expirationDelay<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/param<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;param</span> -value<span style="color: #000000; font-weight: bold;">&gt;</span></span>60000<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/param<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/init<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;load</span> -on-startup<span style="color: #000000; font-weight: bold;">&gt;</span></span>1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/load<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;servlet</span> -mapping<span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;servlet</span> -name<span style="color: #000000; font-weight: bold;">&gt;</span></span>Grizzly Cometd Servlet<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;url</span> -pattern<span style="color: #000000; font-weight: bold;">&gt;</span></span>/cometd/*<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/url<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Côté client, le framework DOJO fournit une extension JavaScript permettant de s&#8217;abonner à un channel et de publier des messages.</p>
<ul>
<li>Concernant la souscription</li>
</ul>

<div class="wp_codebox"><table><tr id="p1159"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code" id="p115code9"><pre class="javascript" style="font-family:monospace;">&nbsp;
<span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;text/javascript&quot;</span><span style="color: #339933;">&gt;</span>
    	dojo.<span style="color: #660066;">require</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;dojox.cometd&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    	dojox.<span style="color: #660066;">cometd</span>.<span style="color: #660066;">init</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;http://localhost:8080/CometSample/cometd&quot;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    	dojox.<span style="color: #660066;">cometd</span>.<span style="color: #660066;">subscribe</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;/cometd/myChannel&quot;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>msg<span style="color: #009900;">&#41;</span>
    	<span style="color: #009900;">&#123;</span>
    		$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'result'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">update</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'message received : '</span> <span style="color: #339933;">+</span> msg.<span style="color: #660066;">data</span>.<span style="color: #660066;">test</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    	<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #339933;">&lt;/</span>script<span style="color: #339933;">&gt;</span>
&nbsp;
<span style="color: #339933;">&lt;</span>ul<span style="color: #339933;">&gt;</span>
	<span style="color: #339933;">&lt;</span>li<span style="color: #339933;">&gt;</span>Concernant la publication<span style="color: #339933;">&lt;/</span>li<span style="color: #339933;">&gt;</span>
<span style="color: #339933;">&lt;/</span>ul<span style="color: #339933;">&gt;</span></pre></td></tr></table></div>


<div class="wp_codebox"><table><tr id="p11510"><td class="line_numbers"><pre>1
2
</pre></td><td class="code" id="p115code10"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> data <span style="color: #339933;">=</span> $F<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'text2Send'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
dojox.<span style="color: #660066;">cometd</span>.<span style="color: #660066;">publish</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'/cometd/myChannel'</span><span style="color: #339933;">,</span><span style="color: #009900;">&#123;</span>test<span style="color: #339933;">:</span> data <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<h3>Les limitations de Comet</h3>
<p>La principale <a href="http://www.openajax.org/runtime/wiki/The_Two_HTTP_Connection_Limit_Issue">limitation</a> à la mise en oeuvre de Comet vient en  fait des browsers.<br />
Ces derniers ne permettent en général de n&#8217;ouvrir que deux connexions http par domaine. En fait, c&#8217;est même conseillé dans la norme HTTP/1.1. Cet <a href="http://www.oreillynet.com/xml/blog/2006/10/what_i_didnt_know_about_xhr.html">article</a> de 2006 donne pas mal de détail sur cette limitation.<br />
J&#8217;ai pu tester cette limitation (sur Firefox 3.0.1) sur mes exemples : lorsque deux de mes browsers ouvraient des connexions de type GET sur le domaine localhost :8080, la seconde connexion GET était systématiquement mise en attente&#8230;en remplaçant simplement localhost par mon IP (et donc en changeant de domaine), le problème se résout.<br />
Au-delà de l&#8217;anecdote, cette limite de deux connexions pose un problème avec le long-polling qui monopolise une des deux connections mais il y a fort à parier que les constructeurs vont résoudre le problème, IE8 devrait déjà porter le nombre de connections à 8&#8230;</p>
<h3>Pour conclure&#8230;</h3>
<p>L&#8217;API Grizzly me parait très naturelle à utiliser et masque vraiment les problématiques de manipulation de thread ; elle gagnerait à fournir une petite librairie JavaScript permettant d&#8217;automatiser l&#8217;ouverture de la connexion ainsi que la reprise en cas de timeout&#8230; On peut de plus regretter la forte imbrication Grizzly/Glassfish : il semble délicat &#8211; pour avoir essayé, rapidement certes&#8230; &#8211; d&#8217;imaginer utiliser le moteur http Grizzly dans Tomcat&#8230;<br />
A l&#8217;inverse, DOJO fournit un client JavaScript bien pensé &#8211; au travers de son extension dojox.cometd &#8211; et l&#8217;implémentation du protocole de Bayeux par Grizzly a cela de génial qu&#8217;elle ne demande &#8211; pour les cas nominaux d&#8217;utilisation &#8211; pas de développement supplémentaire : juste la configuration d&#8217;une servlet.<br />
Reste que ces solutions sont encore artisanales &#8211; au sens étymologique, donc positif. Les APIs aussi bien côté serveur que client ne sont pas encore définies mais il faut noter que les mécanismes de &nbsp;&raquo; push server &nbsp;&raquo; seront standardisés dans la <a href="http://jcp.org/en/jsr/detail?id=315">version 3.0 de Servlet</a> &#8211; donc les containeurs de servlet JEE6 -.<br />
Reste enfin que les cas d&#8217;application dans l&#8217;informatique d&#8217;entreprise ne sont pas forcément des plus répandus et aujourd&#8217;hui plutôt implémentés par des solutions RDA, mais demain qui sait ? ;-)</p>

 <img src="http://blog.octo.com/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=115" width="1" height="1" style="display: none;" /><p>Suggestion d'articles :</p><ol>
<li><a href='http://blog.octo.com/et-apres-ria/' rel='bookmark' title='Et après RIA?'>Et après RIA?</a></li>
<li><a href='http://blog.octo.com/5-minutes-pour-monter-en-complexite-approche-tdd-tests-en-php-php-amp-ajax/' rel='bookmark' title='5 minutes pour : Monter en complexité, Approche TDD / Tests en PHP, PHP &amp; Ajax'>5 minutes pour : Monter en complexité, Approche TDD / Tests en PHP, PHP &#038; Ajax</a></li>
<li><a href='http://blog.octo.com/pourquoi-les-websockets/' rel='bookmark' title='Pourquoi les Websockets ?'>Pourquoi les Websockets ?</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.octo.com/apres-ajax-le-reverse-ajax-et-le-grizzly/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
	</channel>
</rss>

