转载自 新浪博客 董志忠
openfire,做为一个实现xmpp的即时通信服务器端,自身提供了集群的实现,目前,理论上,能支持N个节点的集群,即节点无限制
看了下他集群的实现,他是用到了oracle 的coherence的中间件,关于coherence的话,没有过多研究,大概知道,他是一个缓存中间件,支持缓存集群,而且支持缓存改变事件触发!知道这些就够了,这些就能用来理解openfire集群的原理了
coherence集群开启以后,会为每一个节点生成一个唯一的nodeID,openfire就是使用这个nodeId,来区分当前缓存中对应的Presence,Message等是属于哪一个节点!openfire集群大概工作过程如下:
1,切换缓存实现,这时,缓存层会有其默认的本地缓存,切换到coherence缓存!通过其定义的策略接口,完成这一切换!当然此时,openfire实现的时候,又定义了一个变量用来继续保持本地缓存的实现实例,以便于在openfire的控制台上能再次将缓存层切换为本地缓存。见类
2,开启coherence集群,这块需要简单了解下coherence集群的使用,具体的可以百度一下!代码见类CoherenceClusteredCacheF
3,添加member节点事件监听,添加缓存内容监听!代码见类CoherenceClusteredCacheF
下面重点来了,他如果实现,节点a中的用户向节点b中的用户发信息的呢。
首先,我们追踪类
就是这段代码,他调用了remotePacketRouter类中的route方法,继续追这个方法的实现类
CacheFactory.doClusterTask(new RemotePacketExecution(receipient, packet), nodeID);
对,重点就在标红的部分,doClusterTask 我们看他的实现
CoherenceClusteredCacheF
Set setMembers = taskService.getInfo().getServiceMembers();
这里,他获得的coherence集群中的所有节点集合,并将非指定nodeID的所有节点移除,并在指定的节点执行了一个任务,task,即ClusterTask接口的实现类
最下面,我标红的部分,就是在指定node上执行指定任务的代码,但里面传的参数是一个Invocable实现,这个是coherence定义的接口。看
private static Invocable buildInvocable(final ClusterTask task) {
很简单,这个实现,把openfire定义的ClusterTask包装成了一个Invocable ,这样就可以使用coherence提供的方法,在指定节点上,执行ClusterTask中run的部分
说过了原理部分,我们找一个ClusterTask的实现,看看如何实现的在集群上发送信息
BroadcastMessage 类中的run方法,如下:
public void run() {
对,就一行代码,调用本地的RoutingTable,去直接发送信息!重点是,这个代码,不是在本地执行的,而是在指定节点上执行的!