【Openfire】Openfire Server presence在线状态消息处理流程

Presence处理是IM Server的核心,也是一个IM Server最复杂的部分。一个用户的状态发生变化,需要通过服务器自动投递给他所有在线的好友,因此Presence模块实际上等同一个消息处理服务器,可参看以前消息服务器相关文章ActiveMQ性能研究及与memcacheq比较。

Presence的复杂性体现在:

1.由于每个用户都有1到多个好友,服务器的处理量被放大。

2.分布式处理的复杂度,你的好友可能同时分布在n个服务器上,而且同时上线的好友没有规律。

3.请求量不均衡,可能瞬时非常大。比如你服务器刚重启所有的客户几乎同时自动重连过来。比如Twitter宕机都是在一些热点事件时,大家活跃度突然同时增大。所以系统必须按峰值的处理量设计。

4.缓存cache设计困难。每个用户的在线好友都不同,而且随时在变。

5.隐身同黑名单的业务逻辑很难高效处理。

OpenfireServer处理presence的流程如下,以3.6.0为准。

1.ConnectionHandler.messageReceived();

mina层面处理。

2.StanzaHander.process()=>processPresence

xmpp层面。处理所有xmpp包的方法,实际上只有login相关包在这里处理。其他类型的包交由相关逻辑类来处理。由于是个presence包,交由下面presence逻辑处理模块进行。(alsoaddfromtopacket)

3.PacketRouteImpl.route()//routepresence

4.PresenceRoute.route()=>handle()//routepresence

由于presence是一个需要路由的包,路由主要区分目标是本机还是远程,是component/server还是普通用户。

5.PresenceUpdateHandler.process()=>broadcastUpdate

//process()updatedbandupdatecache,

callsPresenceManager.userAvaliable();session.setPresence()...

6.Roster.broadcastPresence();

检查privacylist(隐身及黑名单用户)然后路由给所有在线好友。

7.RoutingTable.routePacket,routeTable.getRoutes()

真正的工作在这里,较慢。

8.session.process(),session.deliver

已经分发到相关用户了,调用该用户的session投递给此用户

9.nioconnection().deliver,delivertotheendusers

再回到MINA

因此Presence投递工作的核心是在6~7,不过其他的步骤也有不少细节的处理。Openfire中6~7的实现比较精简和优雅,但如果想作为一个大型的高效消息投递系统还是有改进的空间

相关推荐