Openfire Server presence(在线状态)消息处理流程
Presence处理是IM Server的核心,也是一个IM Server最复杂的部分。一个用户的状态发生变化,需要通过服务器自动投递给他所有在线的好友,因此Presence模块实际上等同一个消息处理服务器,可参看以前消息服务器相关文章
ActiveMQ性能研究及与memcacheq比较。
Presence的复杂性体现在:
1. 由于每个用户都有1到多个好友,服务器的处理量被放大。
2. 分布式处理的复杂度,你的好友可能同时分布在n个服务器上,而且同时上线的好友没有规律。
3. 请求量不均衡,可能瞬时非常大。比如你服务器刚重启所有的客户几乎同时自动重连过来。比如Twitter宕机都是在一些热点事件时,大家活跃度突然同时增大。所以系统必须按峰值的处理量设计。
4. 缓存cache设计困难。每个用户的在线好友都不同,而且随时在变。
5. 隐身同黑名单的业务逻辑很难高效处理。
Openfire Server处理presence的流程如下,以3.6.0为准。
1. ConnectionHandler.messageReceived();
mina 层面处理。
2. StanzaHander.process() => processPresence
xmpp 层面。处理所有xmpp包的方法,实际上只有login相关包在这里处理。其他类型的包交由相关逻辑类来处理。 由于是个presence包,交由下面presence逻辑处理模块进行。(also add from to packet)
3. PacketRouteImpl.route() // route presence
4. PresenceRoute.route() => handle() // route presence
由于presence是一个需要路由的包,路由主要区分目标是本机还是远程,是component/server还是普通用户。
5. PresenceUpdateHandler.process() => broadcastUpdate
// process() update db and update cache,
calls PresenceManager.userAvaliable(); session.setPresence()...
6. Roster.boradcastPresence();
检查privacy list(隐身及黑名单用户)然后路由给所有在线好友。
7. RoutingTable.routePacket, routeTable.getRoutes()
真正的工作在这里,较慢。
8. session.process(), session.deliver
已经分发到相关用户了,调用该用户的session投递给此用户
9. nioconnection().deliver, deliver to the end users
再回到MINA
因此Presence投递工作的核心是在6~7,不过其他的步骤也有不少细节的处理。Openfire中6~7的实现比较精简和优雅,但如果想作为一个大型的高效消息投递系统还是有改进的空间。
Presence的复杂性体现在:
1. 由于每个用户都有1到多个好友,服务器的处理量被放大。
2. 分布式处理的复杂度,你的好友可能同时分布在n个服务器上,而且同时上线的好友没有规律。
3. 请求量不均衡,可能瞬时非常大。比如你服务器刚重启所有的客户几乎同时自动重连过来。比如Twitter宕机都是在一些热点事件时,大家活跃度突然同时增大。所以系统必须按峰值的处理量设计。
4. 缓存cache设计困难。每个用户的在线好友都不同,而且随时在变。
5. 隐身同黑名单的业务逻辑很难高效处理。
Openfire Server处理presence的流程如下,以3.6.0为准。
1. ConnectionHandler.messageReceived();
mina 层面处理。
2. StanzaHander.process() => processPresence
xmpp 层面。处理所有xmpp包的方法,实际上只有login相关包在这里处理。其他类型的包交由相关逻辑类来处理。 由于是个presence包,交由下面presence逻辑处理模块进行。(also add from to packet)
3. PacketRouteImpl.route() // route presence
4. PresenceRoute.route() => handle() // route presence
由于presence是一个需要路由的包,路由主要区分目标是本机还是远程,是component/server还是普通用户。
5. PresenceUpdateHandler.process() => broadcastUpdate
// process() update db and update cache,
calls PresenceManager.userAvaliable(); session.setPresence()...
6. Roster.boradcastPresence();
检查privacy list(隐身及黑名单用户)然后路由给所有在线好友。
7. RoutingTable.routePacket, routeTable.getRoutes()
真正的工作在这里,较慢。
8. session.process(), session.deliver
已经分发到相关用户了,调用该用户的session投递给此用户
9. nioconnection().deliver, deliver to the end users
再回到MINA
因此Presence投递工作的核心是在6~7,不过其他的步骤也有不少细节的处理。Openfire中6~7的实现比较精简和优雅,但如果想作为一个大型的高效消息投递系统还是有改进的空间。