openfire 集群

原文地址:openfire 集群原理说明作者:大海巨浪 openfire,做为一个实现xmpp的即时通信服务器端,自身提供了集群的实现,目前,理论上,能支持N个节点的集群,即节点无限制


看了下他集群的实现,他是用到了oracle 的coherence的中间件,关于coherence的话,没有过多研究,大概知道,他是一个缓存中间件,支持缓存集群,而且支持缓存改变事件触发!知道这些就够了,这些就能用来理解openfire集群的原理了 coherence集群开启以后,会为每一个节点生成一个唯一的nodeID,openfire就是使用这个nodeId,来区分当前缓存中对应的Presence,Message等是属于哪一个节点!openfire集群大概工作过程如下: 1,切换缓存实现,这时,缓存层会有其默认的本地缓存,切换到coherence缓存!通过其定义的策略接口,完成这一切换!当然此时,openfire实现的时候,又定义了一个变量用来继续保持本地缓存的实现实例,以便于在openfire的控制台上能再次将缓存层切换为本地缓存。见类 ClusteringPlugin中的代码实现 2,开启coherence集群,这块需要简单了解下coherence集群的使用,具体的可以百度一下!代码见类CoherenceClusteredCacheFactory中的startCluster方法!其中有一段代码,是判断当前最大支持多少个节点!这块以前可能jive打算,集群插件是收费的,所有加了这段代码,不过开源之后,这块就没啥用了,可以直接删除了,都没问题 3,添加member节点事件监听,添加缓存内容监听!代码见类CoherenceClusteredCacheFactory中的startCluster方法。member监听的话,可以监听到当前coherence集群中,有多少个节点,是否有新节点加入或有节点退出等。 下面重点来了,他如果实现,节点a中的用户向节点b中的用户发信息的呢。 首先,我们追踪类 RoutingTableImpl 中的 RoutingTableImpl 方法,看其中一段代码: // This is a route to a local user hosted in other node if (remotePacketRouter != null) { routed = remotePacketRouter .routePacket(clientRoute.getNodeID().toByteArray(), jid, packet); } 就是这段代码,他调用了remotePacketRouter类中的route方法,继续追这个方法的实现类 CoherencePacketRouter 中的方法,有如下实现 CacheFactory.doClusterTask(new RemotePacketExecution(receipient, packet), nodeID); 对,重点就在标红的部分,doClusterTask 我们看他的实现 CoherenceClusteredCacheFactory类中的doClusterTask(final ClusterTask task, byte[] nodeID) 方法 Set setMembers = taskService.getInfo().getServiceMembers(); // Remove all members except requested nodeID for (Iterator it=setMembers.iterator(); it.hasNext();) { Member member = (Member) it.next(); if (!Arrays.equals(member.getUid().toByteArray(), nodeID)) { it.remove(); } } // Check that the requested member was found if (!setMembers.isEmpty()) { // Asynchronously execute the task. taskService.execute(buildInvocable(task), setMembers, null); return true; } 这里,他获得的coherence集群中的所有节点集合,并将非指定nodeID的所有节点移除,并在指定的节点执行了一个任务,task,即ClusterTask接口的实现类 最下面,我标红的部分,就是在指定node上执行指定任务的代码,但里面传的参数是一个Invocable实现,这个是coherence定义的接口。看 buildInvocable 做了哪些工作,看代码: private static Invocable buildInvocable(final ClusterTask task) { return new AbstractInvocable() { public void run() { task.run(); } public Object getResult() { return task.getResult(); } }; } 很简单,这个实现,把openfire定义的ClusterTask包装成了一个Invocable ,这样就可以使用coherence提供的方法,在指定节点上,执行ClusterTask中run的部分 说过了原理部分,我们找一个ClusterTask的实现,看看如何实现的在集群上发送信息 BroadcastMessage 类中的run方法,如下: public void run() { // Broadcast message to client sessions connected to this node XMPPServer.getInstance().getRoutingTable().broadcastPacket(packet, true); } 对,就一行代码,调用本地的RoutingTable,去直接发送信息!重点是,这个代码,不是在本地执行的,而是在指定节点上执行的!

你可能感兴趣的:(openfire 集群)