一般动作
在 grails-platform-core插件的事件总线(Events Bus) 中,通过插件 platform-core 实现了一个应用内部的事件总线,但是该总线存在下面两个问题:
为了解决上述问题,BroToolkit/Framework还内置了插件cometd 并对其做了改造,集成了支持 JDK 1.6 的最新版本的 CometD,实现了支持集群、集群内消息广播、跨应用、支持BS结构的异步消息总线。
当然,作为消息总线,和前者的区别还在于:
BroFramework 提供了CometdService 服务,封装了常用的 CometD API,主要包括下面的API:
注意这里的频道和 platform-core 插件里的频道的区别,这里频道是一个以字符“/”分层的字符串,如 /foo/bar。
发布、监听时,同样可以使用通配符,如 /foo/** 代表 /foo 下所有频道(含孙子频道)、/foo/ 仅代表子频道。
关于频道的详细定义可以参考这里。
调用示例:
Comet 本身是一种基于 HTTP 长连接的“服务器推”技术。基于这种架构开发的应用中,服务器端会主动以异步的方式向客户端程序推送数据,而不需要客户端显式的发出请求。Comet 架构非常适合事件驱动的 Web 应用,以及对交互性和实时性要求很强的应用,如股票交易行情分析、聊天室和 Web 版在线游戏等。
而 CometD 是一个 Comet 的技术实现,因此,天生就提供了基于 jQuery 和 Dojo 框架的 Web API,详细可以参考这里。
BroFramework 中,对其稍稍作了封装,示例如下:
CometD 的集群方案叫做 Oort,通过应用前端的软硬件(如Apache)负载均衡器,能够实现负载均衡、失效转移、集群间消息广播等功能。
BroToolkit 默认提供了 CometD 集群功能,但是未启用,而 BroFramework 中默认启用了集群(通过Config.groovy配置 bropen.toolkit.cluster.cometd.enabled)。
但是,Oort 启动时,通过组播技术来发现集群节点时,需要告诉其他节点本服务器的地址(含端口),而 Java 技术中并没有现成的解决方案获得本 JVM 绑定的 IP 地址和端口(如8080),因此,这里需要做一点配置:
例如节点1配置:
server.host = 192.168.0.11
server.port = 8881
节点2配置:
server.host = 192.168.0.12
server.port = 8882
应用启动时,日志中会陆续输出下面这些日志:
# 本节点(节点1)的 cometURL
CometD oort.url is: http://192.168.0.11:8080/Foobar/cometd
# 根据应用名自动计算的组播端口
CometD oort multicast port: 6129
# 注册广播频道
CometD oort.channels: /broadcast/**
# 节点2加入集群
Comet joined the cloud http://192.168.0.12:8882/Foobar/cometd
各节点都加入到集群后,就能实现集群的负载均衡、失效转移等功能了。
在集群环境下,可能有不同的 CometD 客户端(web端或后台)在发送消息,默认情况下,这些消息是不会被广播到其他集群节点的。
Oort可以通过配置Servlet参数,即上面日志里的 oort.channels 来实现对这些频道的广播。BroToolkit 中,默认对频道 /broadcast/** 进行了广播配置。
因此,如果需要将消息广播到所有集群节点中,只需要将消息发送到 /broadcast 的下级频道即可,如: