openfire 集群原理说明

openfire,做为一个实现xmpp的即时通信服务器端,自身提供了集群的实现,目前,理论上,能支持N个节点的集群,即节点无限制

openfire 集群原理说明_第1张图片


看了下他集群的实现,他是用到了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,去直接发送信息!重点是,这个代码,不是在本地执行的,而是在指定节点上执行的!具体怎么做到的,这个要问问coherence了




了解了这些的话,就大概知道了openfire集群的实现原理,自己也可以根据这些,实现一套自己的集群!


有对这块研究多的,可以相互交流,邮箱 [email protected]


你可能感兴趣的:(oracle,集群,中间件,session,服务器,XMPP)