레이블이 websocket인 게시물을 표시합니다. 모든 게시물 표시
레이블이 websocket인 게시물을 표시합니다. 모든 게시물 표시

2013년 5월 1일 수요일

Comet, WebSocket solution - Atmosphere

이전 블로그에서 이전 함 (원본 글 2013/05/01 작성)

Atmosphere


The Asynchronous WebSocket/Comet Framework

 The Atmosphere Framework contains client and server side components for building Asynchronous Web Application. The majority of popular frameworks are either supporting Atmosphere or supported natively by the framework. The Atmosphere Framework supports all majors Browsers and Servers

Atmosphere transparently supports WebSockets, Server Side Events (SSE), Long-Polling, HTTP Streaming (Forever frame) and JSONP.

Atmosphere is a Java technolog framework that provides a common API for using the Comet and WebSocket features of many of the web servers, including Tomcat, Jetty, GlassFish, Weblogic, Grizzly, JBossWeb, JBoss, and Resin. 

Atmosphere can detect native server APIs (for Comet and WebSockets) and switch back to Servlet 3.0, if available, for Comet. Or, also for Comet, it will fall back to a "managed" asynchronous mode (but not as scalable as Jetty Continuations). Atmosphere has been around for more than two years, and it is still in active development.


The Atmosphere framework is composed of the Atmosphere runtime, which provides a common API for all different web server solutions and standards. On top of this, the client can access the API and Reverse Ajax features through the Google Web Toolkit (GWT) by setting up a mere servlet. Or, you can also use Jersey, a framework implementing the JSR-311 (JAX-RS specification). 

Atmosphere's strength remains on the server side: it provides a standardized API that covers all of the different solutions and ways to communicate with WebSockets or Comet. Atmosphere does not use a protocol between the client and server, like Socket.IO and CometD. Both libraries provide a client-side JavaScript and a server-side servlet that communicate using a specific protocol (for handshaking, messaging, acknowledgment, and heartbeat). Atmosphere's goal is to provide a common communication channel on the server side.

Atmosphere comes with a jQuery client library to facilitate the connection setup, which is able to automatically detect the best transport available (WebSockets or CometD). Usage of Atmosphere's jQuery plugin is similar to the HTML5 WebSockets API. First, you connect to the server, register a callback to receive messages, and then you can push some data.

ProsCons
If you have to deploy a web application in several web servers that you can't control. You'll have a better chance that the Reverse Ajax features of your application work correctly due to the number of web servers supported by Atmosphere.
When you need a common API over a raw Reverse Ajax communication, without any protocol defined, because you want to develop or extend it.
Lack of documentation about Atmosphere's architecture, project, concepts, and APIs, which is helpful if you need to go into the source code or analyze several provided samples. The API is highly technical, and sometimes obscure, compared to the simple APIs of other frameworks, such as Socket.IO and CometD. Even when using Atmosphere annotations, some names and attributes were too technical.
Though a good abstraction on the server side, there is not a good client library. There is no protocol, so all additional features are left to the developer. The current library is too simple for the needs of a big, scalable web application if you require advanced timeout detection, acknowledgement, back-off, cross-domain and so on, especially when working with mobile devices. In this case, CometD is much more reliable; it leverages a communication protocol that can be used to activate some control flow and error detection, all provided within CometD. Using the CometD JavaScript client with the Atmosphere CometD plugin could be a good alternative if you need extra features.


Comet, WebSocket solution - CometD

이전 블로그에서 이전 함 (원본 글 2013/05/01 작성)

 Welcome to CometD Project @ The Dojo Foundation 
 

☄ CometD Bayeux Ajax Push

CometD is a scalable HTTP-based event routing bus that uses a Ajax Push technology pattern known as Comet. The term 'Comet' was coined by Alex Russell in his post Comet: Low Latency Data for the Browser.
CometD is a Dojo Foundation project to provide implementations of the Bayeux protocol in javascript, java, perl, python and other languages. Other organizations (eg. Sun, IBM and BEA) also have implementations of Bayeux that are not strictly part of the CometD project, but where possible they are linked to from this site.

CometD makes use of an Ajax push technology pattern known as Comet, but also uses emerging web standards such as WebSocket for low latency communication.

The CometD project provides Java and JavaScript libraries that allow you to write low-latency, server-side, event-driven web applications in a simple and portable way. You can therefore concentrate on the business side of your application rather than worrying about low-level details such as the transport (HTTP or WebSocket), the scalability and the robustness. The CometD libraries provide these latter characteristics.


he CometD project provides the Bayeux specification, that defines the protocol used to exchange information between client and server, and provides (eventually) standardized APIs for servers and clients.
Currently the API bindings for JavaScript (on the client) and Java (for both client and server) have reached a stable status.



The CometD framework, an event-driven communication solution based on HTTP, has been around for several years. Version 2 added support for annotation configuration and WebSockets. The CometD framework provides a Java server part and a Java client part, plus JavaScript client libraries based upon jQuery and Dojo. CometD uses a standardized communication protocol called Bayeux, allowing you to activate some extensions for message acknowledgement, flow control, synchronization, clustering, and so on.
CometD's event-driven approach fits very well with the new concept of event-driven web development. As with traditional desktop user interfaces, all of the components communicate through a bus to send notifications and receive events. All communication is therefore asynchronous.
The CometD framework:
  • Is well-documented.
  • Provides samples and Maven archetypes to facilitate the startup of a project.
  • Has a well-designed API that enables extension development.
  • Provides a clustering module, called Oort, that gives you the ability to run multiple CometD web servers as nodes in a cluster behind a load balancer to scale to a larger number of HTTP connections.
  • Supports security policies to allow a fine-grain configuration of who can send messages over which channel.
  • Integrates quite well with Spring and Google Guice (dependency injection frameworks).

CometD is bundled with three transports: JSON, JSONP, and WebSocket. They depend upon Jetty Continuations and the Jetty WebSocket API. By default, CometD can be used in Jetty 6, 7, and 8, as well as any other servers supporting the Servlet 3.0 Specification. 


ProsCons
CometD offers a complete solution, from client and server side, and also from a standalone Java client to a server. The framework is well-documented, has a good API, and is easy to use. Best of all, it has an event-driven approach. CometD and Bayeux are part of many event-driven web applications. Other Reverse Ajax frameworks don't provide any event-driven mechanisms, forcing end users to develop their own custom solution.
CometD supports many required features, such as reconnection, reliable timeout detection, back-off, batching, message acknowledgement, and more that you won't find in other Reverse Ajax frameworks. CometD lets you achieve the most reliable, low-latency communication possible.
CometD currently does not support any Servlet 2.5 containers other than Jetty for Comet (Tomcat), and it does not support Glassfish/Grizzly WebSocket.


[CometD 2 Concepts]

- High level View

 : CometD implements a web messaging system, in particular a web messaging system based on the publish/subscribe paradigm.

For example, let's imagine that clientAB is subscribed to channels /A and /B, and clientB is subscribed to channel /B.
If a publisher publishes a message on channel /A, only clientAB will receive it. On the other hand, if a publisher publishes a message on channel /B, both clientAB and clientB will receive the message. Furthermore, if a publisher publishes a message on channel /C, neither clientAB nor clientB will receive the message, that will just end its journey on the server.
Re-routing broadcast messages is the default behavior of the server, and it does not need any application code to perform the re-routing.

* 좀 burden 인것 같이 보이지만 central server를 두고 각 client들이 server로 subscribe하여 event/message를 받는 구조. 자신이 보낸 메세지가 각 channel(subscribe한)을 통해 모든 client(자신 포함)들에게 전달되는 구조.


- Low Level View

 CometD, at its heart, is a client/server system that communicates via a protocol, the Bayeux protocol.

In the CometD implementation, the client/server communication is captured by the half-object plus protocol pattern: when a half-object on the client establishes a communication conduit with the server, its correspondent half-object is created on the server, and the two may - logically - communicate.

The transport can be based on the HTTP protocol, but in recent CometD versions also on the WebSocket protocol (and more transports can be plugged in).

즉 CometD에서는 messaging 전달을 위해서 server, client단에 half object를 만들어서 서로간에 http, websocket을 사용해서 전달하도록 되어 있다는 얘기 인듯... 이렇게 되면  HOPP의 장점을 받을 수 있을 듯.

 * [참고] half-object plus protocol pattern (HOPP)

 - Divide an object which needs to be accessed from more than one address space into two interdependent half-objects (one in each address space) with a protocol between them. 
 - distribute systems상에서 여러 address spaces(아마도 다른 system들이 되지 않을까? 아님 하나의 system에서 각기 다른 application/component상에서 값들을 받아야 할 경우가 아닐까?)에서 실행이 되어야 할 경우 해당 처리를 위한 객체를 분리(half-object)하여 각 address spaces에서 동작하게 하고 서로간에 data/state 전달을 protocol을 사용하는 구조 인것 같음.
 - 장점으로는 처리해야할 행위를 각기 다른 분산 시스템에서 처리하게 되어 performance나 scalability 측면에서는 장점이겠으나 각 half-object 간 data synchronization 측면에서 optimization이 필요할 것으로 보임.
자세한 것은 책 보세요.




[Bayeux Specification]

- specification :  http://cometd.org/documentation/bayeux/spec (나중에 좀 읽어 봐야 겠다.)

Submitted by gregwilkins on Thu, 06/05/2008 - 01:59. 
The primary purpose of Bayeux is to support responsive bidirectional interactionsbetween web clients using Ajax and the web server.

Bayeux is a protocol for transporting asynchronous messages (primarily over HTTP), with low latency between a web server and a web client.

The messages are routed via named channels and can be delivered:
server to client
client to server
client to client (via the server)
By default, publish/subscribe routing semantics are applied to the channels.

Delivery of asynchronous messages from the server to a web client is often described as"server-push".
The combination of server push techniques with an Ajax web application has been called "Comet".
CometD is a project by the Dojo Foundation to provide multiple implementation of the Bayeux protocol in several programming languages.

The Bayeux protocol seeks to reduce the complexity of developing Comet applications by allowing implementors to more easily interoperate, to solve common message distribution and routing problems, and to provide mechanisms for incremental improvements and extensions.


Comet, WebSocket - Reverse Ajax (IBM article)

이전 블로그에서 이전 함 (원본 글 2013/05/01 작성)

[Reverse Ajax, Mathieu Carbou, Java Web Architect, Ovea]
Part 1: Introduction to Comet
Part 2: WebSockets
Part 3: Web servers and Socket.IO
Part 4: Atmosphere and CometD
* IBM article이 그렇듯이 충실하다.. 이것만 제대로 보면 OK.


Listing 2. JavaScript polling
setInterval(function() { 
    $.getJSON('events', function(events) { 
        console.log(events); 
    }); 
}, 2000);


The second technique, which is more reliable, is to use the multi-part flag supported by some browsers (such as Firefox) on theXMLHttpRequest object. An Ajax request is sent and kept open on the server side. Each time an event comes, a multi-part response is written through the same connection. Listing 6 shows an example.

Listing 6. Sample JavaScript code to set up a multi-part streaming request
var xhr = $.ajaxSettings.xhr(); 
xhr.multipart = true; 
xhr.open('GET', 'ajax', true); 
xhr.onreadystatechange = function() { 
    if (xhr.readyState == 4) { 
        processEvents($.parseJSON(xhr.responseText)); 
    } 
}; 
xhr.send(null);

On the server side, things are a little more complicated. You must first set up the multi-part request, and then suspend the connection. Listing 7 shows how to suspend an HTTP streaming request. (Part 3 of this series will cover the APIs in more detail.)

Listing 7. Suspending an HTTP streaming request in a servlet using Servlet 3 API
protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
        throws ServletException, IOException { 
    // start the suspension of the request
    AsyncContext asyncContext = req.startAsync(); 
    asyncContext.setTimeout(0); 

    // send the multipart separator back to the client
    resp.setContentType("multipart/x-mixed-replace;boundary=\""
        + boundary + "\""); 
    resp.setHeader("Connection", "keep-alive"); 
    resp.getOutputStream().print("--" + boundary); 
    resp.flushBuffer(); 

    // put the async context in a list for future usage
    asyncContexts.offer(asyncContext); 
}

Now, each time an event occurs you can iterate over all suspended connections and write the data to them, as shown in Listing 8:

Listing 8. Send events to a suspended multi-part request using Servlet 3 API
for (AsyncContext asyncContext : asyncContexts) { 
    HttpServletResponse peer = (HttpServletResponse) 
        asyncContext.getResponse(); 
    peer.getOutputStream().println("Content-Type: application/json"); 
    peer.getOutputStream().println(); 
    peer.getOutputStream().println(new JSONArray()
        .put("At " + new Date()).toString()); 
    peer.getOutputStream().println("--" + boundary); 
    peer.flushBuffer(); 
}


As usual, there are advantages and disadvantages.
  • Advantage: Only one persistent connection is opened. This is the Comet technique that saves the most bandwidth usage.
  • Disadvantage: The multi-part flag is not supported by all browsers. Some widely used libraries, such as CometD in Java, reported issues in buffering. For example, chunks of data (multi-parts) may be buffered and sent only when the connection is completed or the buffer is full, which can create higher latency than expected.



The second, and recommended, method to implement Comet is to open an Ajax request to the server and wait for the response. The server requires specific features on the server side to allow the request to be suspended. As soon as an event occurs, the server sends back the response in the suspended request and closes it, exactly like you close the output stream of a servlet response. The client then consumes the response and opens a new long-lived Ajax request to the server, as shown in Listing 9:

Listing 9. Sample JavaScript code to set up long polling requests
function long_polling() { 
    $.getJSON('ajax', function(events) { 
        processEvents(events); 
        long_polling(); 
    }); 
} 

long_polling();

On the back end, the code also uses the Servlet 3 API to suspend the request, as in HTTP streaming, but you don't need all the multi-part handling code. Listing 10 shows an example.

Listing 10. Suspending a long polling Ajax request
protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
        throws ServletException, IOException { 
    AsyncContext asyncContext = req.startAsync(); 
    asyncContext.setTimeout(0); 
    asyncContexts.offer(asyncContext); 
}

When an event is received, simply take all of the suspended requests and complete them, as shown in Listing 11:

Listing 11. Completing a long polling Ajax request when an event occurs
while (!asyncContexts.isEmpty()) { 
    AsyncContext asyncContext = asyncContexts.poll(); 
    HttpServletResponse peer = (HttpServletResponse) 
        asyncContext.getResponse(); 
    peer.getWriter().write(
        new JSONArray().put("At " + new Date()).toString()); 
    peer.setStatus(HttpServletResponse.SC_OK); 
    peer.setContentType("application/json"); 
    asyncContext.complete(); 
}

In the accompanying downloadable source files, the comet-long-polling folder contains a long polling sample web application that you can run using the mvn jetty:run command.
  • Advantages: It's easy to implement on the client side with a good error-handling system and timeout management. This reliable technique also allows a round-trip between connections on the server side, since connections are not persistent (a good thing, when you have a lot of clients on your application). It also works on all browsers; you only make use of theXMLHttpRequest object by issuing a simple Ajax request.
  • Disadvantage: There is no main disadvantage compared to other techniques. But, like all techniques we've discussed, this one still relies on a stateless HTTP connection, which requires special features on the server side to be able to temporarily suspend it



Listing 2. JavaScript client code
var ws = new WebSocket('ws://127.0.0.1:8080/async'); 
ws.onopen = function() { 
    // called when connection is opened 
}; 
ws.onerror = function(e) { 
    // called in case of error, when connection is broken in example 
}; 
ws.onclose = function() { 
    // called when connexion is closed 
}; 
ws.onmessage = function(msg) { 
    // called when the server sends a message to the client. 
    // msg.data contains the message. 
}; 
// Here is how to send some data to the server 
ws.send('some data'); 
// To close the socket:
ws.close();

Request URL:ws://127.0.0.1:8080/async 
Request Method:GET 
Status Code:101 WebSocket Protocol Handshake 

Request Headers 
Connection:Upgrade 
Host:127.0.0.1:8080 
Origin:http://localhost:8080 
Sec-WebSocket-Key1:1 &1~ 33188Yd]r8dp W75q 
Sec-WebSocket-Key2:1   7;    229 *043M 8 
Upgrade:WebSocket 
(Key3):B4:BB:20:37:45:3F:BC:C7 

Response Headers 
Connection:Upgrade 
Sec-WebSocket-Location:ws://127.0.0.1:8080/async 
Sec-WebSocket-Origin:http://localhost:8080 
Upgrade:WebSocket 
(Challenge Response):AC:23:A5:7E:5D:E5:04:6A:B5:F8:CC:E7:AB:6D:1A:39


public final class ReverseAjaxServlet extends WebSocketServlet { 
    @Override 
    protected WebSocket doWebSocketConnect(HttpServletRequest request,
                                           String protocol) { 
        return [...] 
    } 
}

With Jetty, there are several ways to handle a WebSocket handshake. The easier way is to subclass Jetty's WebSocketServletand implement the doWebSocketConnect method. This method asks you to return an instance of the Jetty's WebSocket interface. You have to implement the interface and return a sort of endpoint representing the WebSocket connection. Listing 5 provides a sample.

Listing 5. WebSocket implementation sample
class Endpoint implements WebSocket { 

    Outbound outbound; 

    @Override 
    public void onConnect(Outbound outbound) { 
        this.outbound = outbound;    
    } 

    @Override 
    public void onMessage(byte opcode, String data) { 
        // called when a message is received 
        // you usually use this method 
    } 

    @Override 
    public void onFragment(boolean more, byte opcode, 
                           byte[] data, int offset, int length) { 
        // when a fragment is completed, onMessage is called. 
        // Usually leave this method empty. 
    } 

    @Override 
    public void onMessage(byte opcode, byte[] data, 
                          int offset, int length) { 
        onMessage(opcode, new String(data, offset, length)); 
    } 

    @Override 
    public void onDisconnect() { 
        outbound = null; 
    } 
}

To send a message to the client, you write to the outbound, as shown in Listing 6:

Listing 6. Sending a message to the client
if (outbound != null && outbound.isOpen()) {
    outbound.sendMessage('Hello World !');
}

To disconnect the client and close the WebSocket connection, use outbound.disconnect();.
WebSockets is a very powerful way to implement a bi-directional communication with no latency. It is supported by Firefox, Google Chrome, Opera, and other modern browsers. According to the jWebSocket website:
  • Chrome includes native WebSockets since 4.0.249.
  • Safari 5.x includes native WebSockets.
  • Firefox 3.7a6 and 4.0b1+ includes native WebSockets.
  • Opera includes native WebSockets since 10.7.9067.
For more information about jWebSocket, see Resources.
WebSockets provides powerful, bi-directional, low-latency, and easy-to-handle errors. There isn't a lot of connection, like Comet long polling, and it doesn't have the drawbacks of Comet streaming. The API is also very easy to use directly without any additional layers, compared to Comet, which requires a good library to handle reconnection, timeout, Ajax requests, acknowledgments, and the optionally different transports (Ajax long polling and jsonp polling).

2013년 4월 30일 화요일

Comet, WebSocket

이전 블로그에서 이전 함 (원본 글 2013/04/30 작성)




[WebSocket]

- WebSocket 소개

* 말그대로 web browser, server간에서 socket을 사용하는 방법
 browser<->server간 동작을 위해 asynchronous socket operation을 지원해야 겠지..
뭐 요즘은 native programming에서도 asynchronous socket을 사용해서 프로그래밍하니.. 

- WebSocket 지원 현황
* 현재 Android browse는 web socket을 지원하지 않는다.
* 그외 대다수의 Browser(IE10, FF 20, Chrome 26, Safari, Opera)들에서 지원 중

- WebSocket과 Socket.io( Node.js 모듈)



[Comet, WebSocket 지원 현황]
* 2012년 4월 자료이긴 하지만 참고..


(LP: long-Polling HS: Http Streaming)
ServerVersionNative CometNative WebSocketWebSocketsLPHSJSONP
Netty3.3.xXXXXXX
Jetty5.xXXX
Jetty6.xXXXX
Jetty7.xXXXXXX
Jetty8.xXXXXXX
GlassFish2.xXXXX
GlassFish3.x to 3.1.1XXXX
GlassFish3.1.2XXXXXX
Tomcat5.xXXX
Tomcat6.xXXXX
Tomcat7.0.26 and lowerXXXX
Tomcat7.0.27 and upXXXXXX
JBoss5.xXXX
JBoss6.xXXXX
JBoss7.xXXXX
WebLogic10.xXXXX
WebLogic11.x and upXXXX
Resin2.xXXX
Resin3.xX XXXX
WebSphere7.xXXX
WebSphere8.xXXX

Supported Browsers

The current list of Browsers have been tested with Atmosphere using the atmosphere.js Javascript library and the transport they supports.
BrowserVersionWebSocketsLong-PollingHttp StreamingJSONP
Firefox3.x to 8.xXXX
Firefox9.x to 11.xXXXX
Chrome12.x and lowerXXX
Chrome13.x and higherXXXX
Internet Explorer6x to 9.xXXX
Internet Explorer10.xXXXX
Opera10.x and lowerXX
Opera11.xXXX
Safari4.xXXX
Safari5.xXXXX
Android2.x and upXXX
Safari (iOS)1.x to 4.xXXX
Safari (iOS)5.xXXXX



[Comet, WebSocket solutions]

- 지원 solution list

- CometD

- Atmosphere