websockets on the jvm: atmosphere to the rescue!

72
@jfarcand @atmo_framework WebSockets on the JVM: Atmosphere to the rescue! @jfarcand Async-IO.org, http://async- io.org CTO

Upload: jfarcand

Post on 30-Jun-2015

948 views

Category:

Documents


4 download

DESCRIPTION

WebSockets' State of the Union on the JVM with the help of the Atmosphere Framework. Status of atmosphere.js, socketio.js, socks.js client side library discussed as well.

TRANSCRIPT

Page 1: Websockets on the JVM: Atmosphere to the rescue!

@jfarcand@atmo_framework

WebSockets on the JVM: Atmosphere to the rescue!

@jfarcandAsync-IO.org, http://async-io.orgCTO

Page 2: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

WebSockets: Myth or Reality

WebSocket a standard? Really?

Tricks for Production Ready WebSocket Application

Page 3: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

is a web technology providing for bi-directional, full-duplex communications channels over a single TCP connection.

WebSockets

Browser Serverrequest

empty response

request

response

event

request

request

responseevent

request

response part

event

response part

event

Polling Long Polling StreamingBrowser

Server

Browser Server

request

responseevent

event

Browser Server

request

Response

event

response

event

WebSocket

Page 4: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Agenda

• Who I am• Atmosphere• WebSockets: Serveur Side• WebSocket: Client Side• Socket.IO and Socks.js• Conclusion

Page 5: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Who is this strange accent guy• Creator of Frameworks

• Grizzly (NIO Framework)

• AsyncHttpClient (HTTP/WebSocket)

• Atmosphere Framework

• Ex-GlassFish, Tomcat & Jetty « committer »

• Ex Sun Microsystem, France Telecom, Ning, Sonatype

Page 6: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Currently• Founder anf CTO Async-

IO.org

• Since 2013• Atmosphere Support,

Atmosphere Pro & Elite

• Atmosphere is still licenced Apache 2

Page 7: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Async-IO

Page 8: Websockets on the JVM: Atmosphere to the rescue!

blank slidefor your own

pictures

WebSockets: Server Side

Page 9: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

WebSockets: Server Side

• Tomcat 7+, Jetty 7+, GlassFish 3+, Resin 2+, JBoss 7.1.2+ native Websocket API

• Non Portable, Unstable API

• Missing Functionality

• What the point of Atmosphere then???????

Page 10: Websockets on the JVM: Atmosphere to the rescue!

blank slidefor your own

pictures

Page 11: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

WebSockets: Server Side

AtmosphereTo

The Rescue!

Page 12: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Atmosphere: github.com/Atmosphere• Portable, Stable, EVERYWHERE

• Use Native API or JSR 356

• Javascript API(s) & Java (wAsync)

• 950+ mailing list

Page 13: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

JAX Awards 2014

Nominated for Most Innovative Java Technology

Page 14: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Atmosphere: Well Established!!

http://www.parleys.com/

play/514892260364bc

17fc56bde7/chapter0/about

Page 15: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Atmosphere: Run on top of

Page 16: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

atmosphere.js

• 100% Javascript Library

• Small, portable, mobile optimized

• Transparent Fallback

• One API to Rule them all: WebSockets/Server Sides Event/Long-Polling/HTML File/JSONP/Polling/Streaming etc.

Page 17: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Atmosphere : Clients

Page 18: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Atmosphere: Browsers

6+

3.5+

4+

3+

10+

Page 19: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Atmosphere: Into the Cloud

• Your Atmosphere’s Application transparently work into the cloud

Proxy/Load balancer

Page 20: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Atmosphere: Cloud

Page 21: Websockets on the JVM: Atmosphere to the rescue!

blank slidefor your own

pictures

Enterprise Ready?

Page 22: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Atmosphere Pro! • atmosphere-satellite: replicate your data and code together In-

Memory for faster execution and seamless elastic scalability across your Atmosphere's Nodes/Servers.

• atmosphere-tower-control: Monitor your Atmosphere's Node/Server state via any JMX compliant tool like Java Mission Control. Get statistics on how many websocket or long-polling clients are currently connected, add/move connected clients from one node to another, for example in case of a node being restarted, etc.

• atmosphere-postman: Client/Server extension to Atmosphere to support message delivery guarantee.

http://async-io.org/AtmospherePro.html

Page 23: Websockets on the JVM: Atmosphere to the rescue!

blank slidefor your own

pictures

Fix broken browsers/servers for you!

`

Page 24: Websockets on the JVM: Atmosphere to the rescue!

Atmosphere

Page 25: Websockets on the JVM: Atmosphere to the rescue!

var socket = atmosphere; var subSocket; var request = { url: document.location.toString() + 'chat’, contentType : "application/json”, transport : "websocket" , trackMessageLength : true };

request.onOpen = function(response) { content.html($('<p>', { text: 'Atmosphere connected using ' + response.transport })); }; request.onMessage = function (response) {

var json = atmosphere.util.parseJSON(response.responseBody)…

};

request.onClose = function(response) {…};

request.onReopen = function(response) {….}

request.onTransportFailure = function(errorMsg, request) {…}

subSocket = socket.subscribe(request);

Atmosphere

Page 26: Websockets on the JVM: Atmosphere to the rescue!

@ManagedService(path = "/chat”)public class Chat { @Ready public void onReady(AtmosphereResource r) {..}

@Disconnect public void onDisconnect(AtmosphereResourceEvent e) {..}

@Message( encoders = {JacksonEncoder.class}, decoders = {JacksonDecoder.class})

public Reply onMessage(Message message){return handleAndReply(message);

}}

Atmosphere

Page 27: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Problem #1 – Fallback

• Browser• Old version

• No support (IE 9)

• Proxys• Disconnect, block

• Load Balancer• Breaks Session Affinity

Page 28: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Fallback with Atmosphere

public void onReady(AtmosphereResource r) { switch (r.transport()) {

case WEBSOCKET:case SSE:case LONG-POLLING:case STREAMING:case JSONP:case POLLING:

r.write(“Atmosphere is cool”);}

}

Page 29: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Atmosphere I/O

• WebSocket uses « non blocking I/O »

• Fallback simulates « non blocking I/O>

Browsers behave the same way as packet are delivered uniformely.

Page 30: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Problem #2 –Protocol

Tomcat 7.x/8.x => RFC 6455 (Version

13) !!<= Safari 5.0.x

Jetty9.1+ => Hixie 76 <= Safari 5.0.x

Page 31: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Protocol Version

• Atmosphere => Transparent Fallback in case the protocol is not supported

Page 32: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Problem #3 – Lost Lost Lost

• I/O error, websocket message will be lost.

• Message must be put inside a cache

• Message must be discarted if the connection never come back.

Page 33: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Atmosphere – Messages Lost

@ManagedService(path = "/chat”)public class Chat {

@Message public void onMessage(AtmosphereResource r, String message){ // Transparently cache the message in case of a problem

// Transparently write it back once reconnected r.write(message); }}

Page 34: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Problem #4 – Proxy

• Existing Proxy are cutting the connection.

• Must recover transparently from a disconnect.

• Heartbeat saves your day!

Page 35: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Atmosphere – Proxy ? No Problem!

Page 36: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Problem #5 – New Spec!

• Difference between Tomcat, Undertow and Jetty already!

• Spec is young, missing fondamental concepts.

• Tomcat 8.0.12 is stable. GlassFish 4 is dead, Jetty 9.1.3 stable, Undertow 1.1.Final is stable, WelLogic is broken.

Page 37: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Problem #5 – JSR 356: Tomcat vs Jetty

@Message public void onMessage(String m, Session s) {

for (Session s: sessions.getOpenSessions()){ // Tomcat will throw an IllegalStateException

// if more than one thread call sendXXX.// Jetty won’t!

session.getAsyncRemote().sendText(m);}

}

Page 38: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Problem #5 – JSR 356: Tomcat vs Jetty private final Semaphore semaphore = new Semaphore(1, true);

@Message public void onMessage(String m, Session s) {

for (Session s: sessions.getOpenSessions()){try{ semaphore.acquireUninterruptibly();

session.getAsyncRemote().sendText(m, …);}finally {

semaphore.release();}

}}

Page 39: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Problem #5 – Tomcat vs Jetty

• I/O Event aren’t delivered the same way.

• CloseReason not the same depending on the server!!!!

// Hack if (closeCode == 1000 &&

getContainerName().contains("Tomcat")) { closeCode = 1005;

}

Page 40: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Firefox is the new Internet Explorer 6!

// Reload a tab/window // Firefox => 1001 // Chrome => 1000

if (isFirefox && c.getCode() == CloseReason.GOING_AWAY

|| c.getCode() == CloseReason.NO_STATUS_CODE) {...

}

Page 41: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Firefox is the new Internet Explorer 6!

Reload in Firefox produces phantom websockets connections!!!!!!!

Page 42: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Problem #6 – Closing Code

• How to detect if a websocket was closed by a Proxy, a Load Balancer or the Browser!!

Page 43: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Hell exists!!

Page 44: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Atmosphere

@Disconnect public void onClose(AtmosphereResourceEvent e) {

if (e.isClosedByClient()){

} else if (e.isClosedByApplication()) {

} else if (e.isUnexpectlyClosed()) {

}

Page 45: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

blank slidefor your own

pictures

WebSockets: Client Side

Page 46: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

WebSockets: Javascript API

• W3C SpecificationWebSocket ws = new WebSocket(“ws://127.0.0.1:8080”);

ws.onopen = function (message) {};

ws.onclose = function (message) {};

ws.onmessage = function (message) {}

Page 47: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

WebSocket: Supported Browsers

10+

10+

6+

5+

10+

?

2+

Page 48: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

W3C API

Ohhhhhhhhh• Pong/Ping: No exposed

• Headers: Can’t add/read

• Query String: No API, append them to the url

• Cookie: Impossible to read them

Page 49: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Atmosphere: First request

• W3C SpecificationT 127.0.0.1:52212 -> 127.0.0.1:8080 [AP]GET /chat?X-Atmosphere-tracking-id=0&X-Atmosphere-Framework=2.2.0-javascript&X-Atmosphere-Transport=websocket&X-Atmosphere-TrackMessageSize=true&X-Cache-Date=0&Content-Type=application/json&X-atmo-protocol=true HTTP/1.1.Upgrade: websocket.Connection: Upgrade.Host: 127.0.0.1:8080.Origin: http://127.0.0.1:8080.Sec-WebSocket-Key: TCBKrAyFFwW8HUXqLpj2wg==.Sec-WebSocket-Version: 13.Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits, x-webkit-deflate-frame.

Page 50: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Atmosphere: First request

• W3C Specification

T 127.0.0.1:8080 -> 127.0.0.1:52212 [AP]HTTP/1.1 101 Switching Protocols.X-Atmosphere-first-request: true.X-Atmosphere-tracking-id: bb7aeeb7-9e44-4aa9-848d-14bba6532de9.Connection: Upgrade.Sec-WebSocket-Accept: 5mHABDQFkWBtjoinv3lj+6dVwHg=.Upgrade: WebSocket.

Page 51: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Problem #1 – onclose

• Firefox will execute the ws.onclose function on F5 (reload)

• Chrome/Safari ….. NOT!

Page 52: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Problem #1: onclose

• W3C Specificationws.onclose = function(closeReason) {

switch(closeReason.code) {case 1000:

….}

// Firefox will execute this logic on every reload// closeReason.wasClean unreliableif (dirtyClose) {

reconnectTo(…); }}

Page 53: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Atmosphere: onclose

• W3C Specification

// Hahahaha go to hell Firefox!!atmosphere.onClose = function

(callback) {

};

Page 54: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Problem #2 – Messages’ length

• Messages can be truncated when the server write them

• The Browser received them in two chunks or I/O operation

Page 55: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Problem #2: Messages’ length

• W3C Specification

// Craaaaaaashhhhhhhhhhhhhws.onmessage = function (callback) {

window.JSON.parse(callback.data);};

Page 56: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Problem #2: What’s Up, Doctor!

• W3C Specification

// atmosphere.js transparently // handles it

atmosphere.onMessage = function (callback) {window.JSON.parse(callback.responseBody);

};

Page 57: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Problem #3 – UUID and Cookie

• No Cookie to identify the client

Page 58: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Problem #3 – UUID and Cookie

• Solutions:

• Normal request => set-cookie

• Next WebSockets

• Useful if you deploy on Amazon

(1) HTTP

(2) websockets

Page 59: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Atmosphere: Handshake Protocol

• W3C Specification

T 127.0.0.1:8080 -> 127.0.0.1:52212 [AP].651|bb7aeeb7-9e44-4aa9-848d-14bba6532de9|1397426374301|

T 127.0.0.1:8080 -> 127.0.0.1:52212 [AP]..

T 127.0.0.1:8080 -> 127.0.0.1:52212 [AP]..

Page 60: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Problem #4 – Proxy

• Proxy can close the websocket or completely ignore the websocket handshake, completely fooling the server…and the browser!

• ws.open never called!!!!

Page 61: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Problem #4 – Proxy

• W3C Specification

websocket.onopen = function (message) { alert(“Ha ha ha good luck!!!”);}

websocket.onmessage = function(message) { // Never called

alert(“Sleep on it!!!”);}

Page 62: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Problem #4 – Proxy

• W3C Specification

atmosphere.onReopen = function (callback) { // Yeahhhh!!!

};

atmosphere.onTransportFailure = function (callback) { // Apache Proxy, I hate you!!!

};

Page 63: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Hazelcast

Page 64: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

blank slidefor your own

pictures

SockJs et Socket.ioSocket.IO and Socks.js

Page 65: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Socket.IO• For Node.js

• Streaming, Long-Polling and now Websocket

• Extremely popular, lot of  »issues »

602 => https://github.com/LearnBoost/socket.io/issues

• Supported by Atmosphere, both client and server side. Replace node.js

Page 66: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Socket.IO - Atmosphere

• W3C Specification@ManagedService(path = "/chat”)public class Chat { @Ready public void onReady(AtmosphereResource r) {..}

@Disconnect public void onDisconnect(AtmosphereResourceEvent e) {..}

@Message( encoders = {JacksonEncoder.class}, decoders = {JacksonDecoder.class})

public Reply onMessage(Message message){return handleAndReply(message);

}}

Page 67: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Socket.IO - Atmosphere

• W3C Specificationvar socket = io.connect('', {'resource’:document.location.toString() + 'chat'});

socket.on('connect', function () { content.html($('<p>',

{ text:'Atmosphere connected using this.socket.transport.name}));});

socket.on('chat message', function() { var json = jQuery.parseJSON(msg);

… });

socket.on(‘error’, function (e) {…});

Page 68: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Socks.js

• For Node.js

• Emulate WebSocket, with « fallback »

• Socks.js popularity increase, due to Spring 4, Vert.x and Atmosphere support

Page 69: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Socks.js - Atmosphere

• W3C Specification@ManagedService(path = "/clavarder”)public class Chat { @Ready public void onReady(AtmosphereResource r) {..}

@Disconnect public void onDisconnect(AtmosphereResourceEvent e) {..}

@Message( encoders = {JacksonEncoder.class}, decoders = {JacksonDecoder.class})

public Reply onMessage(Message message){return handleAndReply(message);

}}

Page 70: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Socks.js- Atmosphere

• W3C Specificationvar socket = new SockJS('http://' + window.location.host + '/chat', null, { 'protocols_whitelist': ['websocket', 'xhr-streaming', 'iframe-eventsource', 'iframe-htmlfile', 'xhr-polling', 'jsonp-polling'] });

socket.onopen = function() { content.html($('<p>', { text: 'Atmosphere connected using SockJs client'}));}

socket.onmessage = function (response) { var message = response.data;

var json = JSON.parse(message);}

socket.onclose = function() {}

Page 71: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

Conclusion

• WebSockets in Prod without fallback? You’re Crazy!!

• Atmosphere is production ready, and fixes all the issues listed here!

• What are you waiting for?

Page 72: Websockets on the JVM: Atmosphere to the rescue!

@asyncio@atmo_framework

@All images copyright JeanFrancois Arcand

https://www.linkedin.com/in/jfarcand

http://async-io.org

http://github.com/Atmosphere/atmosphere

http://github.com/jfarcand

Credits