CometD 框架
CometD 框架是基于 HTTP 的事件驱动通信解决方案。CometD 框架提供了一个 Java 服务器部件和一个 Java 客户端部件,还有一个基于 jQuery 和 Dojo 的 JavaScript 客户端库。CometD 使用了一个叫 Bayeux 的标准化通信协议,充许您针对于消息确认、流控制、同步、集群等方面进行扩展。
CometD 的事件驱动方法非常适合事件驱动 Web 开发的新概念。正如传统的桌面用户界面那样,所有的组件均通过总线进行通信,以便发送通知和接收事件。因此所有的通信都是异步的。
CometD 框架:
- 提供了一个称为 Oort 的集群模块,该模块使您能够运行多个CometD Web 服务器,将它们看作是负载均衡器背后的集群中的节点,从而扩展许多 HTTP 连接。
- 支持安全策略,允许更具体地配置由谁通过哪条通道发送消息。- 更好地与 Spring 和 Google Guice(依赖注入框架)集成。
Bayeux 协议
它定义的消息通过命名通道进行路由并且能够进行交互传 送:server -> client, client -> server 甚至 client -> client (当然还是需要通过server中转)。Bayeux 协议主要基于 HTTP 来传输低延迟的、异步的事件消息。采用Publish/Subscribe的模式,允许服务端异步push消息到客户端。CommetD实现可以基于流 (streaming) 和长轮询 (long polling)。
服务器和内部构件
CometD 与三个传输协议绑定在一起:JSON、JSONP 和 WebSocket。他们都依赖于 Jetty Continuations 和 Jetty WebSocket API。在默认情况下,可以在 Jetty 6、Jetty 7、和 Jetty 8 中以及其他所有支持 Servlet 3.0 Specification 的服务中使用 CometD。可以使用与扩展相同的方式添加和开发传输协议。您应该能够编写支持 Grizzly WebSocket API 和其他 API 的传输协议,然后再在配置 CometD 服务器的步骤中添加这些协议。 Cometd是一个提供多种开发语言的Bayeux项目,由Dojo基金会提供支持。
Comet 的反向 Ajax
客户端向服务端发送请求,当请求到达的时候服务端可以立即将处理结果发送给客户端,也可以累计客户端发送的请求再连续的发送给客户端。
CometD 的构架视图
Subscribe
订阅是将订阅某个Channel的客户端所对应的ContinuationClient对象加入到对应的channel的subscribers列表中。订阅成功后进行客户端的长轮训,服务端会将当前的请求封装到一个Continuation中,并将Continuation对象设到ContinuationClient对象中,然后将ContinuationClient对象挂起。
Publish
服务端接受到信息的时候,会找到订阅的channel,然后进行数据的广播。这个时候调用channel的push 方法,对每一个订阅当前channel客户进行分发。将ContinuationClient中的Continuation唤醒resume。
客户端与服务端建立起连接
send信息到服务端的时候会带上clientId,本身还带上id且id是递增
客户端通过channel传递test1,服务端同时将信息返回
服务器停止,关闭服务的时候客户端检测信息
前端画面建立连接
(function($)
{
var cometd = $.cometd;
$(document).ready(function()
{
/**
* Therefore the code that you put in the _connectionEstablished() function must be idempotent. In other words,
make sure that if the _connectionEstablished() function is called more than one time,
it will behave exactly as if it is called only once.
* @returns
*/
function _connectionEstablished()
{
$('#body').append('<div>CometD Connection Established</div>');
}
function _connectionBroken()
{
$('#body').append('<div>CometD Connection Broken</div>');
}
function _connectionClosed()
{
$('#body').append('<div>CometD Connection Closed</div>');
}
// Function that manages the connection status with the Bayeux server
var _connected = false;
// 检测会话连接是否建立
function _metaConnect(message)
{
if (cometd.isDisconnected())
{
_connected = false;
_connectionClosed();
return;
}
var wasConnected = _connected;
_connected = message.successful === true;
if (!wasConnected && _connected)
{
_connectionEstablished();
}
else if (wasConnected && !_connected)
{
_connectionBroken();
}
}
// Function invoked when first contacting the server and
// when the server has lost the state of this client
var loop=0;
function _metaHandshake(handshake)
{
if (handshake.successful === true)
{
cometd.batch(function()
{ //订阅
cometd.subscribe('/hello', function(message)
{
$('#body').append('<div>Server Says: ' + message.data.greeting + '</div>');
});
// Publish on a service channel since the mge is for the server only
$("#btnTest").click(function(){
cometd.publish('/service/hello', { name: $("#txtValue").val()});
})
});
}
}
// Disconnect when the page unloads
$(window).unload(function()
{
cometd.disconnect(true);
});
var cometURL = location.protocol + "//" + location.host + config.contextPath + "/cometd";
cometd.configure({
url: cometURL,
logLevel: 'debug',
});
//进行握手
cometd.addListener('/meta/handshake', _metaHandshake);
//建立连接
cometd.addListener('/meta/connect', _metaConnect);
cometd.handshake();
});
})(jQuery);
其它消息推送技术
- ActiveMQ AJAX - publish and subscribe to JMS events directly from javascript in the browser. This is quite basic, with less bells and whistles than the other approaches, but because of it's simplicity, might be a good base to start with if you a) already use activemq, b) like not having too many layers of abstraction
- Atmosphere - Event based framework, can auto detected the best communication mechanism based on which webserver and which broswer are currently in use. A pretty nice framework, which supports a full spread of browsers and web severs, even down to IE6. And there are examples of using Atmosphere with spring MVC and Spring Integration.
- Cometd - An implementation of the Bayeux protocol (to auto-negotiate the best connection type) based on jetty/hightide. Jetty was the first java webserver to support continuations, now part of the latest Servlet spec. Cometd take Jetty and wraps it up with JS client libraries for autodetection of the best connection mechanism to the browser.
- Vert.x - An event based server platform that you can build on top of. There has been some controversy around Vert.x recently when it's author left VMware, but VMware retained the project. It now looks like version 2 will be released from the Eclipse Foundation. Seems very promising, but quite low level. Not the kind of thing you just plug into an existing java web app.
- HTML5 EventSource - Standards based way of sending events to the browser. No mechanism for sending events back to the server. It's interesting, but given you need to implment a fallback for IE6, IE7 and IE8, it might not be your best choice, for now.
文献资料
cometd
wa-reverseajax
An Introduction To WebSockets
What are Long-Polling, Websockets, Server-Sent Events (SSE) and Comet
Servlet 3.0
push notification for java web app
cometd-java-examples