Bidirektionale Verbindungen für Webanwendungen

Embed Size (px)

DESCRIPTION

Vortrag "Bidirektionale Verbindungen für Webanwendungen" über Websocket und Server-Push Technologien auf der JAX 2012 in Mainz.

Citation preview

  • 1. Bidirektionale Verbindungen fr Webanwendungen JAX 2012, MainzMarco Rico Gomez @mricog Weigle Wilczek GmbHRoman Roelofsen @romanroe

2. Agenda Warum ?Wie ? TechnikenBibliothekenLive DemoWhat's next 3. Warum ? moderne Webanwendungen hneln immer mehr RichClient-Applikationen fr derartige Anwendungen ist das HTTP Protokoll nicht gemacht es braucht Hacks bzw. Erweiterungen 4. AJAX & Comet 5. AJAX (Asynchronous JavaScript and XML)5 6. Comet (Server push)6 7. Comet - Long-Polling Browser setzt eine AJAX Anfrage ab bleibt geffnet bis neue Daten vom Server gesendet werden Daten werden in der onreadystatechange CallbackFunktion verarbeitet neue Verbindung wird aufgebaut7 8. Comet - Streaming eine persistente HTTP VerbindungDaten werden inkrementell verarbeitet ohne die Verbindung zu schlieenzwei Varianten: hidden iframeXMLHttpRequest Daten werden in der onreadystatechange CallbackFunktion verarbeitet8 9. Comet - Hacks Nur 2 gleichzeitige persistente Verbindungen je Client zu einem Server erlaubt (HTTP 1.1) Komplex seit 2008 haben die meisten Browser jedoch auf 6 Verbindungen erweitert Bidirektionale Verbindung muss ber zwei Kanle simuliert werdenHTTPOverhead Request-/ Response-Header 9 10. HTML5 Server-Sent Event (SSE)10 11. HTML5 Server-Sent Event (SSE) Unidirektionale Kommunikation Server->ClientClient abonniert einen StreamBei neuen Ereignissen wird der Client benachrichtigt Verbindung bleibt geffnet geschlossene Verbindungen werden automatisch wieder geffnet11 12. SSE JavaScript API if (!!window.EventSource) { var source = new EventSource('sse-stream.html'); } else { // Result to xhr polling :( } // new message callback function source.addEventListener('message', function(e) { console.log(e.data); }, false); // register open callback (optional) source.addEventListener('open', function(e) { ... }, false); // register error callback (optional) source.addEventListener('error', function(e) { ... }, false); // cancel source.close();12 13. SSE - Server-response HTTP/1.1 200 OK Content-Type: text/event-stream Cache-Control: no-cache Connection: keep-alive id: my-unique-connection-id event: foo data: This is the 1st line data: Here comes the 2nd line13 14. SSE Jetty EventSourceServlet class StockEventServlet extends EventSourceServlet { def newEventSource(request: HttpServletRequest) = new StockEventSource() } class StockEventSource extends EventSource { private var emitter: Emitter def onOpen(emitter: Emitter) { this.emitter = emitter } def emitEvent(data: String) { emitter.data(data) } def onClose() { /* NOP */ } }14 15. HTML5 WebSockets15 16. HTML5 WebSockets TCP fr das Web bidirektionale Kommunikation ber eine TCP Verbindung eliminiert HTTP-Overhead16 17. WebSocket Server (Java)17 18. WebSocket Handshake WebSocket Verbindung anfordernHTTP-Kompatibel einfacher HTTP GET Request18 19. WebSocket Handshake (Client) GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Origin: http://example.com Sec-WebSocket-Protocol: foo, bar Sec-WebSocket-Version: 1319 20. WebSocket Handshake (Server) HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= Sec-WebSocket-Protocol: bar20 21. WebSocket JavaScript API var websocket = new WebSocket('ws://ws.example.com/chat', ['foo', 'bar']); websocket.onopen = function () { websocket.send('Ping'); // Send the message 'Ping' to the server }; // process new message from the server websocket.onmessage = function (e) { console.log('Server: ' + e.data); }; // register error callback function websocket.onerror = function (error) { ... }21 22. WebSocket Jetty WebSocketServlet class ChatWebSocketServlet extends WebSocketServlet { def doGet(request: HttpServletRequest, response: HttpServletResponse) {} def doPost(request: HttpServletRequest, response: HttpServletResponse) {} def doWebSocketConnect(request: HttpServletRequest, protocol: String) = new ChatWebSocket() // shared resource (thread-safe !!!) private val members = new CopyOnWriteArraySet()}class ChatWebSocket extends WebSocket { ... }22 23. WebSocket Jetty WebSocketServlet class ChatWebSocket extends WebSocket { private var outbound: Outbound = null def onConnect(outbound: Outbound) { this.outbound = outbound } def onMessage(frame: Byte, data: String) { for(member